使用BluetoothLeScanner for android时如何过滤制造商数据?

时间:2016-10-06 07:05:30

标签: android bluetooth-lowenergy

我正在使用自己的BLE设备。在听完这些设备之后我想使用ScanFilter,所以我只得到我感兴趣的设备。我现在的解决方案是在回调内部进行过滤,但如果这种过滤可能更早发生并且根据它应该是可能的。我试图过滤制造商的具体数据,但我无法让它工作。这是我的代码:

BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
ScanFilter filter = getScanFilter();
List<ScanFilter> scanFilters = new ArrayList<>();
scanFilters.add(filter);
ScanSettings scanSettings = getScanSettings();
bleScanner.startScan(scanFilters, scanSettings, scanCallback);

这是创建过滤器和设置的功能:

private ScanSetting getScanSettings(){
    ScanSettings.Builder builder = new ScanSettings.Builder();
    builder.setReportDelay(0);
    builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
    return builder.build();
}

private ScanFilter getScanFilter(){
    ScanFilter.Builder builder = new ScanFilter.Builder();
    ByteBuffer manData = ByteBuffer.allocate(6); //The sensors only sends 6 bytes right now
    ByteBuffer manMask = ByteBuffer.allocate(6);
    manData.put(0, (byte)0x50);
    manData.put(1, (byte)0x41);
    manData.put(2, (byte)0x43);
    manData.put(3, (byte)0x4b);
    manData.put(4, (byte)0x45);
    manData.put(5, (byte)0x54);
    for(int i = 0; i < 6; i++){
        manMask.put((byte)0x01);
    }
    builder.setManufacturerData(20545, manData.array(), manMask.array()); //Is this id correct?
    return builder.build();
}

如果我不使用任何只有此功能的过滤器或设置:

bluetoothLeScanner.startScan(scanCallback);

我得到了我的BLE设备,所以我知道它们正在正确播放。我还可以打印制造商特定的数据,并且可以看到它是我在过滤器中使用的6个相同字节。我不确定id(.setManufacturerData函数中的第一个参数)是否正确,因为我能找到的唯一信息来自于ScanFilter.Builder:

"Note the first two bytes of the manufacturer Data is the manufacturerId"

当我使用此代码并尝试扫描设备后,我什么都没得到。我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

我设法让它发挥作用。这是不正确的manufacturerId。我从前两个字节得到的不是20545。相反,我发现我可以通过执行以下操作从ScanResult(当我没有使用过滤器时)获取此ID:

ScanRecord scanRecord = scanResult.getScanRecord();
SparseArray<byte[]> manufacturerData = scanRecord.getManufacturerSpecificData();
for(int i = 0; i < manufacturerData .size(); i++){
    int manufacturerId = manufacturerData.keyAt(i);
}

通过这样做,我得到了正确的manufacturerId,然后我可以放在bleScanner.startScan函数中。

答案 1 :(得分:0)

SIG定义了“制造商特定数据”,以包括制造商ID作为前2个字节,后跟任何其他数据。然后,Android会通过提取前2个字节(剩下的剩余字节)来确定制造商ID。如果您的广告包没有使用制造商ID(不建议使用,但根据我的情况),那么Android的“制造商数据”实际上将丢失您的2个字节。

就我而言,固件工程师需要为数据分配所有字节。因此,我最终在Android端错误地解析了制造商数据。

解决方案是将过滤器的前两个字节分隔为ID的整数。其余字节用于数据。像这样:

fun createAndroidManufacturerDataFilter(query: String): ScanFilter {
    return ScanFilter.Builder().setManufacturerData(
        convertASCIItoByteArrayToInt(query.substring(0, 2)),
        convertASCIItoByteArray(query.substring(2))
    ).build()
}