BLE получает uuid, закодированную в рекламном пакете
Я пытаюсь получить UUID устройства. Я следил за руководством разработчиков Android и до сих пор могу получить только имя устройства и rssi. Я пытаюсь получить Uuid устройства, которое приходит к методу сканирования, который выглядит так:
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);
}
это возвращает - btif_gattc_upstreams_evt: Событие 4096
Ответы
Ответ 1
Если вы хотите получить UUID/любые другие данные, например. Данные изготовителя из scanRec [] байт после BLE Scan, вам сначала нужно понять формат данных этого пакета данных рекламы.
Пришел с Bluetooth.org:
![Advertising or Scan Response Data format]()
Слишком много теории, хотите увидеть фрагмент кода? Эта функция, приведенная ниже, прямо вывела на печать проанализированные необработанные байты данных. Теперь вам нужно знать каждый тип кода, чтобы узнать, какой пакет данных относится к какой информации. например Тип: 0x09, относится к имени устройства BLE, Тип: 0x07, относится к 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;
}
// ...
}
После этого разбора эти байты данных будут иметь больше смысла, и вы можете определить следующий уровень декодирования.
Ответ 2
Как упоминалось в комментариях, устройство BLE действительно не имеет определенного UUID (но довольно много для включенных сервисов). Однако некоторые схемы, такие как iBeacon, кодируют уникальный идентификатор в записи данных конкретного производителя в рекламном пакете.
Здесь довольно неэффективный, но концептуально простой способ преобразования всего файла scanRecord в шестнадцатеричное строковое представление для отладочной печати:
String msg = "payload = ";
for (byte b : scanRecord)
msg += String.format("%02x ", b);
Обратите внимание, что это будет включать как фактический рекламный пакет, так и количество бессмысленных байтов, которые следует игнорировать после разбора структуры (поля длины), содержащейся в самом рекламном пакете.
Ответ 3
У меня была эта же проблема при разработке моего приложения, но после прочтения документации по следующей ссылке: https://developer.android.com/reference/android/bluetooth/le/ScanResult.html
важными классами в отношении UUID (в зависимости от API, который вы разрабатываете для) являются:
AdvertiseData
AdvertiseData.Builder
ScanRecord
ScanResult
после прочтения документации для этих классов, это код, который я написал, чтобы получить UUID для любого проверяемого устройства:
//Для API < 21:
private BluetoothAdapter.LeScanCallback scanCallBackLe =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {
final int RSSI = rssi;
if (RSSI >= signalThreshold){
scanHandler.post(new Runnable() {
@Override
public void run() {
AdvertiseData data = new AdvertiseData.Builder()
.addServiceUuid(ParcelUuid
.fromString(UUID
.nameUUIDFromBytes(scanRecord).toString())).build();
scannerActivity.addDevice(device, RSSI, getUUID(data));
}
});
}
}
};
//For APIs less than 21, Returns Device UUID
public String getUUID(AdvertiseData data){
List<ParcelUuid> UUIDs = data.getServiceUuids();
//ToastMakers.message(scannerActivity.getApplicationContext(), UUIDs.toString());
String UUIDx = UUIDs.get(0).getUuid().toString();
Log.e("UUID", " as list ->" + UUIDx);
return UUIDx;
}
Для API > 21:
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, final ScanResult result) {
Log.i("callbackType", String.valueOf(callbackType));
Log.i("result", result.toString());
final int RSSI = result.getRssi();
if (RSSI>=signalThreshold) {
scanHandler.post(
new Runnable() {
@Override
public void run() {
BluetoothDevice device = result.getDevice();
scannerActivity.addDevice(device, result.getRssi(), getUUID(result));
}
});
}
} ...}
//For APIs greater than 21, Returns Device UUID
public String getUUID(ScanResult result){
String UUIDx = UUID
.nameUUIDFromBytes(result.getScanRecord().getBytes()).toString();
ToastMakers.message(scannerActivity.getApplicationContext(), UUIDx);
Log.e("UUID", " as String ->>" + UUIDx);
return UUIDx;
}
Мне удалось получить 128-битный UUID любого устройства, использующего этот код.:)
Ответ 4
Вы можете использовать стандартный android BluetoothGattCharacteristic apis, такой как getFloatValue (int formatType, int offset), getIntValue (int formatType, int offset), getStringValue (int offset).. обратитесь к очень хорошему учебному сайту разработчика Android здесь
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, "Received heart rate: " + heartRate);
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
}