Trying to detect an iBeacon setup on raspberry PI using the android beacon library (with xamarin bindings)
Wondering what Im doing wrong here:
sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 01 00 00 C8 00
And setting up Beacon Parser like so
beaconManager.BeaconParsers.Add(new BeaconParser().SetBeaconLayout("m:0-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
I can detect this beacon with for example "BeaconScope" on Android but I can not get it detected using the android beacon library.
I can see the following output from debug
[BeaconParser] Processing pdu type FF: 02011a1aff4c000215e20a39f473f54bc4a12f17d1ad07a96100010000c80000000000000000000000000000000000000000000000000000000000000000 with startIndex: 5, endIndex: 29
[BeaconParser] Ignoring pdu type 06
[BeaconParser] This is not a matching Beacon advertisement. (Was expecting be ac. The bytes I see are: 02011a1aff4c000215e20a39f473f54bc4a12f17d1ad07a96100010000c80000000000000000000000000000000000000000000000000000000000000000
Setting up as AltBeacon works!
sudo hcitool -i hci0 cmd 0x08 0x0008 1F 02 01 1A 1B FF 18 01 BE AC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 C5 01
This one the library detects.
What am I missing?
I detect a RadButton setup as iBeacon but can not get it to work from raspberry PI
Try changing this:
"m:0-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"
to this:
"m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"
Note the first digit is a 2 instead of a 0
There is a similar question:
What is the path of OAT file in Android 5.0
But Android 7, in the same path:
/data/dalvik-cache/<ARCH>/
I can't find the user-installed app, but only the system ones.
Where can I find the oat file generated by the normal installation of an app?
I found the oat file generated by the normal installation of an app in:
/data/app/<PACKAGE_NAME>/oat/<ARCH>/base.odex
And I verified that is an oat file running (on my machine, not in Android) the command:
$ readelf -e base.odex
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 3928128 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 9
Section header string table index: 8
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .rodata PROGBITS 00001000 001000 34f000 00 A 0 0 4096
[ 2] .text PROGBITS 00350000 350000 06c3f4 00 AX 0 0 4096
[ 3] .bss NOBITS 003bd000 000000 034604 00 A 0 0 4096
[ 4] .dynstr STRTAB 003f2000 3bd000 00003d 00 A 0 0 4096
[ 5] .dynsym DYNSYM 003f2040 3bd040 000060 10 A 4 0 4
[ 6] .hash HASH 003f20a0 3bd0a0 000024 04 A 5 0 4
[ 7] .dynamic DYNAMIC 003f3000 3be000 000038 08 A 4 0 4096
[ 8] .shstrtab STRTAB 00000000 3bf000 00003d 00 0 0 4096
...
because it contains the .rodata and .text headers as described in: http://newandroidbook.com/files/Andevcon-ART.pdf
I am developing a semi standard ibeacon, need to use the RSP broadcast field, I am using TI CC2541 broadcasting both Adv and RSP, working fine as from TI Packet Sniffer result attached.
I fail to get the RSP test data {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF} scan on my Samsung Note3, Android 4.4.2, using example from http://developer.android.com/guide/topics/connectivity/bluetooth-le.html ,my added Log.d code is:
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
Log.d("Tag101: ", device.getAddress() + "||"+Integer.toString(rssi) + "||"+toHexadecimal(scanRecord));
}
};
Result:
10-15 21:07:28.066 19840-19853/com.example.android.bluetoothlegatt
D/Tag101:: 20:CD:39:B1:52:C2||-52||02 01 06 1a ff 4c 00 02 15 e2 c5 6d
b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 01 00 02 cd 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 10-15 21:07:28.286
19840-19840/com.example.android.bluetoothlegatt D/dalvikvm:
GC_FOR_ALLOC freed 514K, 13% free 10104K/11604K, paused 15ms, total
15ms 10-15 21:07:28.571
19840-19852/com.example.android.bluetoothlegatt D/BluetoothAdapter:
onScanResult() - Device=20:CD:39:B1:52:C2 RSSI=-52 10-15 21:07:28.571
19840-19852/com.example.android.bluetoothlegatt D/Tag101::
20:CD:39:B1:52:C2||-52||02 01 06 1a ff 4c 00 02 15 e2 c5 6d b5 df fb
48 d2 b0 60 d0 f5 a7 10 96 e0 00 01 00 02 cd 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 10-15 21:07:29.081 19840-2874/com.example.android.bluetoothlegatt
D/BluetoothAdapter: onScanResult() - Device=20:CD:39:B1:52:C2 RSSI=-51
10-15 21:07:29.081 19840-2874/com.example.android.bluetoothlegatt
D/Tag101:: 20:CD:39:B1:52:C2||-51||02 01 06 1a ff 4c 00 02 15 e2 c5 6d
b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 01 00 02 cd 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 10-15 21:07:29.581
19840-2873/com.example.android.bluetoothlegatt D/BluetoothAdapter:
onScanResult() - Device=20:CD:39:B1:52:C2 RSSI=-51
The Test Data can be scan correctly by TI Packet Sniffer:
enter image description here
Can anyone one advise on how to get the RSP in Android code, do I need to init scan-request?
Some example code will be great. Thanks.
Android normally requests a scan response all by itself, and when received, it appends the scanRecord with the PDU for the scan response. I see this is not happening in the scan record output you show.
You might try transmitting connectable advertisements and see if this makes a difference. It is possible Android only requests and processes the scan response for connectable advertisements.
try this Kotlin class to parse RSA data
also you could translate it to Java
finally you'll got a Map Array with all necessary RSA data
enum class EBLE {
EBLE_ZERO, // Zero element
EBLE_FLAGS, //«Flags» Bluetooth Core Specification:
EBLE_16BitUUIDInc, //«Incomplete List of 16-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_16BitUUIDCom, //«Complete List of 16-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_32BitUUIDInc,//«Incomplete List of 32-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_32BitUUIDCom,//«Complete List of 32-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_128BitUUIDInc,//«Incomplete List of 128-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_128BitUUIDCom,//«Complete List of 128-bit Service Class UUIDs» Bluetooth Core Specification:
EBLE_SHORTNAME,//«Shortened Local Name» Bluetooth Core Specification:
EBLE_LOCALNAME,//«Complete Local Name» Bluetooth Core Specification:
EBLE_TXPOWERLEVEL,//«Tx Power Level» Bluetooth Core Specification:
EBLE_DEVICECLASS,//«Class of Device» Bluetooth Core Specification:
EBLE_SIMPLEPAIRHASH,//«Simple Pairing Hash C» Bluetooth Core Specification:«Simple Pairing Hash C-192» Core Specification Supplement, Part A, section 1.6
EBLE_SIMPLEPAIRRAND,//«Simple Pairing Randomizer R» Bluetooth Core Specification:«Simple Pairing Randomizer R-192» Core Specification Supplement, Part A, section 1.6
EBLE_DEVICEID,//«Device ID» Device ID Profile v1.3 or later,«Security Manager TK Value» Bluetooth Core Specification:
EBLE_SECURITYMANAGER,//«Security Manager Out of Band Flags» Bluetooth Core Specification:
EBLE_SLAVEINTERVALRA,//«Slave Connection Interval Range» Bluetooth Core Specification:
EBLE_16BitSSUUID,//«List of 16-bit Service Solicitation UUIDs» Bluetooth Core Specification:
EBLE_128BitSSUUID, //«List of 128-bit Service Solicitation UUIDs» Bluetooth Core Specification:
EBLE_SERVICEDATA,//«Service Data» Bluetooth Core Specification:«Service Data - 16-bit UUID» Core Specification Supplement, Part A, section 1.11
EBLE_PTADDRESS,//«Public Target Address» Bluetooth Core Specification:
EBLE_RTADDRESS,//«Random Target Address» Bluetooth Core Specification:
EBLE_APPEARANCE,//«Appearance» Bluetooth Core Specification:
EBLE_DEVADDRESS,//«LE Bluetooth Device Address» Core Specification Supplement, Part A, section 1.16
EBLE_LEROLE,//«LE Role» Core Specification Supplement, Part A, section 1.17
EBLE_PAIRINGHASH,//«Simple Pairing Hash C-256» Core Specification Supplement, Part A, section 1.6
EBLE_PAIRINGRAND,//«Simple Pairing Randomizer R-256» Core Specification Supplement, Part A, section 1.6
EBLE_32BitSSUUID,//«List of 32-bit Service Solicitation UUIDs» Core Specification Supplement, Part A, section 1.10
EBLE_32BitSERDATA,//«Service Data - 32-bit UUID» Core Specification Supplement, Part A, section 1.11
EBLE_128BitSERDATA,//«Service Data - 128-bit UUID» Core Specification Supplement, Part A, section 1.11
EBLE_SECCONCONF,//«LE Secure Connections Confirmation Value» Core Specification Supplement Part A, Section 1.6
EBLE_SECCONRAND,//«LE Secure Connections Random Value» Core Specification Supplement Part A, Section 1.6
EBLE_3DINFDATA, //«3D Information Data» 3D Synchronization Profile, v1.0 or later
EBLE_MANDATA; //«Manufacturer Specific Data» Bluetooth Core Specification:
companion object {
private val map = EBLE.values()
fun fromInt(type: Int) = if (type > 0) map[type] else EBLE_MANDATA
fun getDistance(rssi: Int, txPower: Int) = {
/*
* RSSI = TxPower - 10 * n * lg(d)
* n = 2 (in free space)
*
* d = 10 ^ ((TxPower - RSSI) / (10 * n))
*/
Math.pow(10.0, (txPower.toDouble() - rssi) / (10 * 2))
}
/*
BLE Scan record parsing
*/
fun parseRecord(scanRecord: ByteArray): Map<EBLE, ByteArray> {
val ret = HashMap<EBLE, ByteArray>()
var index = 0
while (index < scanRecord.size) {
val length = scanRecord[index++].toInt()
//Zero value indicates that we are done with the record now
if (length == 0) break
val type = scanRecord[index].toInt()
//if the type is zero, then we are pass the significant section of the data,
// and we are thud done
if (type == 0) break
Arrays.copyOfRange(scanRecord, index + 1, index + length)?.let {
ret[EBLE.fromInt(type)] = it //HexUtil.formatHexString(it)
}
index += length
}
return ret
}
fun getServiceUUID(record: Map<EBLE, ByteArray>): String {
return when {
record.containsKey(EBLE.EBLE_128BitUUIDCom) -> {
val tmpString = HexUtil.formatHexString(record[EBLE.EBLE_128BitUUIDCom]?.reversedArray())
tmpString.substring(0, 8) + "-" + tmpString.substring(8, 12) + "-" + tmpString.substring(12, 16) + "-" + tmpString.substring(16, 20) + "-" + tmpString.substring(20, tmpString.length)
}
record.containsKey(EBLE.EBLE_32BitUUIDCom) -> {
HexUtil.formatHexString(record[EBLE.EBLE_32BitUUIDCom]?.reversedArray()) + "-0000-1000-8000-00805f9b34fb"
}
record.containsKey(EBLE.EBLE_128BitUUIDInc) -> { // Todo: Remove after bugfix !!!
val tmpString = HexUtil.formatHexString(record[EBLE.EBLE_128BitUUIDInc]?.reversedArray())
tmpString.substring(0, 8) + "-" + tmpString.substring(8, 12) + "-" + tmpString.substring(12, 16) + "-" + tmpString.substring(16, 20) + "-" + tmpString.substring(20, tmpString.length)
}
else -> {
"undefined"
}
}
}
fun getServiceUUID(scanRecord: ByteArray): String {
return getServiceUUID(parseRecord(scanRecord))
}
}
Gist link
I have solve the problem, I need to specified the length of scan_RSP:
// GAP - SCAN RSP data (max size = 31 bytes)
{
0x05, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE
};
Log.d result:
Device=20:CD:39:B1:52:C2 RSSI=-47 10-15 23:20:29.416
4780-4792/com.example.android.bluetoothlegatt D/Tag101::
20:CD:39:B1:52:C2||-47||02 01 06 1a ff 4c 00 02 15 e2 c5 6d b5 df fb
48 d2 b0 60 d0 f5 a7 10 96 e0 00 01 00 02 cd 05 aa bb cc dd ee 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 10-15 23:20:29.921 4780-4791/com.example.android.bluetoothlegatt
D/BluetoothAdapter: onScanResult() - Device=20:CD:39:B1:52:C2 RSSI=-47
10-15 23:20:29.921 4780-4791/com.example.android.bluetoothlegatt
D/Tag101:: 20:CD:39:B1:52:C2||-47||02 01 06 1a ff 4c 00 02 15 e2 c5 6d
b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 01 00 02 cd 05 aa bb cc dd
ee 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00
Followed by the sample, I started my Pi with the command:
pi#raspberrypi ~ $ sudo hciconfig hci0 up
pi#raspberrypi ~ $ hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 00:1A:7D:DA:71:13 ACL MTU: 310:10 SCO MTU: 64:8
UP RUNNING
RX bytes:1094 acl:0 sco:0 events:54 errors:0
TX bytes:768 acl:0 sco:0 commands:54 errors:0
pi#raspberrypi ~ $ sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00
< HCI Command: ogf 0x08, ocf 0x0008, plen 44
1E 02 01 1A 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60
D0 F5 A7 10 96 E0 00 00 00 00 C5 00 00 00 00 00 00 00 00 00
00 00 00 00
> HCI Event: 0x0e plen 4
01 08 20 12
pi#raspberrypi ~ $ sudo hciconfig hci0 leadv 3
Then, turned on my Android 4.4 phone which works perfectly with the Ibeacon devices I ordered from online retailers(no brand).
works perfectly means I can see all the advertising data in Java code(by following onLeScan(...) callback), as well as the RSSI, and parsing them(UUID, major, minor and etc.).
The strange thing is I put a debug info into:
public synchronized void onLeScan(final BluetoothDevice device,
int rssi, byte[] scanRecord)
the byte[] scanRecord I got from PI is:
02 01 0A 02 0A 08 0C 09 43 53 52 38 35 31 30 20 41 31 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
I can't read these bytes which seems totally mismatched with the one set via Pi command line, I tried with the App IBeacon Locate, still couldn't find my Pi, please help, thanks.
Add more details:
Only the BLE dongle is a different brand from the sample since I'm not in US, and I'm not sure if its drivers were installed correctly in PI and actually I didn't explicitly installed any drivers for it(I'm a new guy for Linux), I just pulg in and started the command line.
Some folks with different bluetooth dongles have reported having to alter the order of the commands and disabling advertising before enabling it. Try:
sudo hciconfig hci0 up
sudo hciconfig hci0 noleadv
sudo hciconfig hci0 leadv
sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00
You might also let us know the model of your bluetooth dongle and what it reports itself as to Linux. You can see this by typing lsusb
BTW, nice job capturing the bytes read by Android's onLEScan method. Super helpful!
I am trying to send a URL in a NDEF Message from my Computer and ACR 122 to a phone.
To Achieve that, I use SNEP.
The thing is that it works perfectly with Android and Blackberry, but not with any Windows Phone.
These are the commands I send using the java library Smartcardio, and the responses I got from the phone (android or Windows)
Command 1 : (configure PN532 as Target)
FF 00 00 00 2D D4 8C 00 08 00 12 34 56 40 01 FE0100000000000000000000000000FFFF01FE01000000000000000646666D01011000
Response Android : D5 8D 25 1E D4 00 D5 65 D7 84 0E 59 F9 CF B2 BA 00 00 00 32 46 66 6D 01 01 11 03 02 00 13 04 01 96 90 00
Response Windows Phone : D5 8D 05 22 D4 00 C2 65 AD 78 F4 3D 81 F8 72 8F 00 00 00 32 46 66 6D 01 01 11 02 02 03 80 03 02 00 01 04 01 64 90 00
Command 2 : (tg get data)
FF00000002 D486
Response Android : D5870000009000
Response WP : D5870000009000
Command 3 : (tg set data, ndef with "urn:nfc:sn:snep")
FF00000015 D48E 0520060F 75726E3A6E66633A736E3A736E6570
Response Android : D58F009000
Reponse WP : D58F009000
Command 4 : (tg get data)
FF00000002 D486
Response Android : D587 000000 9000
Response WP : D587 00 05 20 02 02 03 80 050105060F75726E3A6E66633A736E3A736E6570 9000
Command 5 : (tg set data)
FF00000004D48E 0000
Response Android : D5 8F 00 9000
Response WP : D5 8F 00 9000
Command 6 : (tg get data)
FF00000002 D486
Response Android : D587 00 8184 9000
Response WP : D587 00 8184 02020380050105 9000
Command 7 : (tg set data, ndef with url "journaldugeek.com")
FF00000021 D48E 132000100200000016 D1 01 12 55 01 6A6F75726E616C64756765656B2E636F6D
Response Android : D58F 00 9000
Response WP : D58F 00 9000
Command 8 : (tg get data)
FF00000002D486
Response Android : D587 00 83 44 01 9000
Response WP : D587 00 83 44 01 9000
Command 9 : (tg set data)
FF00000004D48E0000
Response Android : D58F009000
Response WP : D58F009000
Command 10 : (tg get data)
FF00000002D486
Response Android : D587 00830401108100000000 9000
Response WP : D587 00830401108100000000 9000
Command 11 : (tg set data)
FF00000005 D48E 136001
Response Android : D58F009000
Response WP : D58F009000
Command 12 : (tg get data)
FF00000002D486
Response Android : D5870000009000
Response WP : D5870000009000
Command 13 : disconnect?
FF00000004D48E1160
Response Android : D58F009000
Response WP : D58F009000
Command 14 : disconnect?
FF00000002D486
Response Android : D587 0081C400 9000
Response WP : D587 0081C400 9000
You can see that only Command 6 is different for Android and Windows Phone, however the other ones are the sames. The WP basically send a OK Message, but the url is not displayed in a browser on the phone. Does anybody know why, and know if there is another way to do SNEP with APDU Commands so that it works for Android, WP and Blackberry ?