web-dev-qa-db-fra.com

BLE obtient des uuid encodés dans un paquet publicitaire

J'essaie d'obtenir l'UUID du périphérique ble. Je suivais le guide du développeur Android et, jusqu'à présent, je ne peux obtenir que le nom de l'appareil et les flux RSS. J'essaie d'obtenir Uuid du périphérique qui utilise la méthode de numérisation qui ressemble à ceci:

    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);
   }

cela retourne - btif_gattc_upstreams_evt: événement 4096 

17
Boris Pawlowski

Si vous souhaitez obtenir un UUID/toute autre donnée, par exemple Les données du fabricant sur scanRec [] octets après le scan BLE, vous devez d'abord comprendre le format des données de ce paquet de données de publicité. 

Venu de Bluetooth.org:Advertising or Scan Response Data format

Trop de théorie, vous voulez voir un extrait de code? La fonction ci-dessous permet d’imprimer directement des octets de données brutes analysées. Maintenant, vous devez connaître chaque code de type pour savoir quel paquet de données fait référence à quelle information. par exemple. Type: 0x09, fait référence au nom du périphérique BLE, Type: 0x07, fait référence à l'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;
    }

    // ...
}

Après cette analyse, ces octets de données auront plus de sens et vous pourrez déterminer le prochain niveau de décodage.

38
Khulja Sim Sim

Comme mentionné dans les commentaires, un périphérique BLE n'a pas vraiment d'UUID spécifique (mais plutôt plusieurs pour les services inclus). Cependant, certains systèmes, tels que iBeacon, codent un identifiant unique dans un enregistrement de données spécifique au fabricant dans un paquet publicitaire. 

Voici un moyen peu efficace mais simple sur le plan conceptuel de convertir l'intégralité de scanRecord en une représentation chaîne hexadécimale pour l'impression de débogage:

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

Notez que cela inclura à la fois le paquet publicitaire réel et un certain nombre d'octets de fin sans signification, qui doivent être ignorés après l'analyse de la structure (champ de longueur) contenue dans le paquet publicitaire lui-même.

3
Chris Stratton

J'ai eu le même problème lors du développement de l'application ble, mais après avoir lu la documentation sur le lien suivant: https://developer.Android.com/reference/Android/bluetooth/le/ScanResult.html

les classes importantes en ce qui concerne l'UUID (en fonction de l'API pour laquelle vous développez) sont les suivantes:

PublierDonnées PublierDonnées.Builder ScanRecord ScanResult

après avoir lu la documentation de ces classes, voici le code que j'ai écrit pour obtenir l'UUID de tout périphérique analysé:

// Pour 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;
}

Pour les 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;
}

J'ai pu obtenir un UUID 128 bits de tout périphérique utilisant ce code. :)

0
ADEBAYO OSIPITAN

J'ai trouvé une bibliothèque Java pour analyser le paquet de publicité

https://github.com/TakahikoKawasaki/nv-bluetooth

0
Andy J