android - Programmatically, How to identify if a beacon belongs to Eddystone or iBeacon? -


i have created android application scan ble using bluetooth lescanner. need app identify if beacon belongs ibeacon or eddystone. far, i'm successful in determining uuid,majorid,minorid of ibeacon parsing ad frame.

it's relatively easy read bytes of advertisements if know byte offsets of fields. 2 code snippets below show how can parse these out. first shows how can in own onlescan callback using android beacon library, , second shows how can roll own scratch.

to explain how layouts work, @ code below. uses android beacon libray's beaconparser class handles of parsing configurable layout. (even if want roll own shown in second code snippet, worthwhile looking @ layout expressions know how work. expressions below show details altbeacon similar ibeacon. altbeacon shown because there no intellectual property restrictions discussing implementation. both altbeacon , eddystone open source standards.)

the first layout expression shows altbeacon (again similar ibeacon) has 3 identifiers ("i" expressions). first 1 (known uuid in ibeacon) 16 bytes goes byte offset 4-19. second 1 (known major on ibeacon) 2 bytes goes byte offset 20-21. third 1 (known minor on ibeacon) 2 bytes goes byte offset 22-23.

the second layout expression shows eddystone-uid service advertisement has 16-bit service uuid of 0xfeaa followed matching byte code of 0x00. has 2 identifiers, first known "namespace identifier" byte offsets 4-13. second identifier known "instance identifier" byte offsets 14-19.

    public void onlescan(bluetoothdevice device, int rssi, byte[] scanrecord) {          arraylist<beaconparser> beaconparsers = new arraylist<beaconparser>();         final string altbeacon_layout = "m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25";         final string eddystone_uid_layout = "s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19";          beaconparsers.add(new beaconparser().setbeaconlayout(eddystone_uid_layout));          beaconparsers.add(new beaconparser().setbeaconlayout(altbeacon_layout));          beacon beacon = null;         (beaconparser parser : beaconparsers) {             beacon = parser.fromscandata(scanrecord,                     rssi, device);              if (beacon != null) {                 if (beacon.getserviceuuid() == 0xfeaa) {                     // eddystone, uses service uuid of 0xfeaa                     identifier eddystonenamespaceid = beacon.getid1();                     identifier eddystoneinstanceid = beacon.getid2();                 }                 else {                     // type of beacon altbeacon or ibeacon                     identifier uuid = beacon.getid1();                     identifier major = beacon.getid2();                     identifier minor = beacon.getid3();                 }             }         } 

the open source android beacon library handles details variable length pdus can alter byte offsets within scan response. can see source code of how beaconparser works here.

if want roll own scratch, easiest way loop through bytes looking pattern want find, parse out bytes of interest based on offsets. (the android beacon library uses more robust , sophisticated method of parsing individual pdus.) looping technique still works.

   public void onlescan(bluetoothdevice device, int rssi, byte[] scanrecord) {          (int startbyte = 0; startbyte < scanrecord.length; startbyte++) {             if (scanrecord.length-startbyte > 19) { // need @ least 19 bytes eddystone-uid                 // check has right pattern needed eddystone-uid                 if (scanrecord[startbyte+0] == (byte)0xaa && scanrecord[startbyte+1] == (byte)0xfe &&                         scanrecord[startbyte+2] == (byte)0x00) {                     // eddystone-uid beacon.                     byte[] namespaceidentifierbytes = arrays.copyofrange(scanrecord, startbyte+4, startbyte+13);                     byte[] instanceidentifierbytes = arrays.copyofrange(scanrecord, startbyte+14, startbyte+19);                     // todo: above identifiers here                 }             }             if (scanrecord.length-startbyte > 24) { // need @ least 24 bytes altbeacon                 // check has right pattern needed altbeacon                 // ibeacon has different layout.  google search find it.                 if (scanrecord[startbyte+2] == (byte)0xbe && scanrecord[startbyte+3] == (byte)0xac) {                     // altbeacon                     byte[] uuidbytes = arrays.copyofrange(scanrecord, startbyte+4, startbyte+19);                     byte[] majorbytes = arrays.copyofrange(scanrecord, startbyte+20, startbyte+21);                     byte[] minorbytes = arrays.copyofrange(scanrecord, startbyte+22, startbyte+23);                     // todo: above identifiers here                 }              }         }     } 

again, code above shows how parse open source altbeacons (for intellectual property reasons). parse ibeacons, you'll need google search beaconlayout, , make small adjustments code above.


Comments