Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BLE obtain uuid encoded in advertising packet

Tags:

Im trying to get UUID of ble device. I was following android developers guide and so far I can get only device name and rssi. Im trying to get Uuid of the device that comes to scanning method that looks like this:

    public void onLeScan(final BluetoothDevice device, int rssi,byte[] scanRecord) {          ParcelUuid[] myUUid =device.getUuids();         for(ParcelUuid a :myUUid){             Log.d("UUID",a.getUuid().toString());         }         String s = new String(scanRecord);         int len = scanRecord.length;         String scanRecords =new String(scanRecord) ;            deviceMap.put(device.getName().toString(), rssi);         Message msg = MainActivity.myHandler.obtainMessage();         Bundle bundle = new Bundle();         bundle.putCharSequence("dev_name", device.getName().toString());         bundle.putCharSequence("rssi", Integer.toString(rssi));         msg.setData(bundle);         MainActivity.myHandler.sendMessage(msg);    } 

this returns - btif_gattc_upstreams_evt: Event 4096

like image 337
Boris Pawlowski Avatar asked Feb 25 '14 13:02

Boris Pawlowski


People also ask

What is service UUID in BLE?

A Universally Unique Identifier (UUID) is a globally unique 128-bit (16-byte) number that is used to identify profiles, services, and data types in a Generic Attribute (GATT) profile. For efficiency, the Bluetooth® Low Energy (BLE) specification adds support for shortened 16-bit UUIDs.

What is advertising data in BLE?

Advertising Data Format. When a BLE device is advertising, it periodically transmits packets, which contain information such as the preamble, access address, CRC, Bluetooth sender address, and so on.

What is service UUID and characteristic UUID?

UUID. The UUID is the standard 16-bit UUID for a primary service declaration, UUIDprimaryservice ( 0x2800 ). Value. The value is the 16-bit UUID for the Heart Rate Service, assigned by the SIG ( 0x180D ).


2 Answers

If you want to get UUID / any other data e.g. Manufacturer Data out of scanRec[] bytes after BLE Scan, you first need to understand the data format of those Advertisement Data packet.

Came from Bluetooth.org: Advertising or Scan Response Data format

Too much theory, want to see some code snippet? This function below would straight forward print parsed raw data bytes. Now, you need to know each type code to know what data packet refers to what information. e.g. Type : 0x09, refers to BLE Device Name, Type : 0x07, refers to UUID.

public void printScanRecord (byte[] scanRecord) {      // Simply print all raw bytes        try {         String decodedRecord = new String(scanRecord,"UTF-8");         Log.d("DEBUG","decoded String : " + ByteArrayToString(scanRecord));     } catch (UnsupportedEncodingException e) {         e.printStackTrace();     }      // Parse data bytes into individual records     List<AdRecord> records = AdRecord.parseScanRecord(scanRecord);       // Print individual records      if (records.size() == 0) {         Log.i("DEBUG", "Scan Record Empty");     } else {         Log.i("DEBUG", "Scan Record: " + TextUtils.join(",", records));     }  }   public static String ByteArrayToString(byte[] ba) {   StringBuilder hex = new StringBuilder(ba.length * 2);   for (byte b : ba)     hex.append(b + " ");    return hex.toString(); }   public static class AdRecord {      public AdRecord(int length, int type, byte[] data) {         String decodedRecord = "";         try {             decodedRecord = new String(data,"UTF-8");          } catch (UnsupportedEncodingException e) {             e.printStackTrace();         }          Log.d("DEBUG", "Length: " + length + " Type : " + type + " Data : " + ByteArrayToString(data));              }      // ...      public static List<AdRecord> parseScanRecord(byte[] scanRecord) {         List<AdRecord> records = new ArrayList<AdRecord>();          int index = 0;         while (index < scanRecord.length) {             int length = scanRecord[index++];             //Done once we run out of records             if (length == 0) break;              int type = scanRecord[index];             //Done if our record isn't a valid type             if (type == 0) break;              byte[] data = Arrays.copyOfRange(scanRecord, index+1, index+length);              records.add(new AdRecord(length, type, data));             //Advance             index += length;         }          return records;     }      // ... } 

After this parsing, those data bytes would make more sense, and you can figure out next level of decoding.

like image 56
Khulja Sim Sim Avatar answered Oct 20 '22 08:10

Khulja Sim Sim


As mentioned in comments, a BLE device doesn't really have a specific UUID (but rather many for included services). However, some schemes such as iBeacon encode a unique identifier in a manufacturer-specific data record in an advertising packet.

Here's a quite inefficient but conceptually simple way to convert the entire scanRecord to a hex string representation for debug printing:

String msg = "payload = "; for (byte b : scanRecord)   msg += String.format("%02x ", b); 

Note that this will include both the actual advertising packet and a number of meaningless trailing bytes, which should be ignored after parsing the structure (length field) contained in the advertising packet itself.

like image 45
Chris Stratton Avatar answered Oct 20 '22 08:10

Chris Stratton