繁体   English   中英

安卓低功耗。 如何通过原始广告数据过滤扫描

[英]Android BLE. How to filter Scan by raw advertising data

我必须构建一个 Android 应用程序来读取一种设备上的信息,该设备仅在被过滤时才会在扫描时显示(一般扫描不会显示它)。 该设备类似于信标,因此它只广告数据,其中包含我想要的广告信息(不可连接)。 制造商给我的过滤器是原始数据。 这是:

0x02010612435542

我无法按名称过滤它,因为该设备不会宣传它的名称。 我也不能通过MAC Address来做到这一点,因为应用程序之前不会知道设备的地址(它将是许多此类设备)。

nrfConnect 应用程序做得很好,如下所示:

nrfConnect 正确执行过滤

应用程序上的过滤器名称是:

按原始广告数据过滤

而且,当过滤后,这就是设备在应用程序上的显示方式:

通过原始数据过滤后在 nrfConnect 上找到的设备

所以,事情就是这样。 我无法按 name 或MAC Address过滤。

Java(android/ble标准库)中用于过滤的其他选项是:

    ScanFilter scanFilter1 = new ScanFilter.Builder().setManufacturerData(manufacturerId, manufacturerData).build();
    ScanFilter scanFilter2 = new ScanFilter.Builder().setServiceData(serviceDataUuid, serviceData).build();
    ScanFilter scanFilter2 = new ScanFilter.Builder().setServiceUuid(serviceUuid).build();

我有制造商提供的 UUID。 它是

B54ADC00-67F9-11D9-9669-0800200C9A66

但是,正如制造商所说,UUID 用于扫描 iOS,不适用于 Android(经过测试,这是真的)。

所以,我只剩下上面 scanFilters 的 2 个选项。

我有这样的知识:“制造商数据在原始广告数据中进行广告,可以通过 nrfConnect 应用程序找到。制造商数据的前两个字节是制造商 ID,与setManufacturerData()过滤器一起使用”。 我什至能够检索原始制造商广告数据(使用setDeviceAddress()过滤器(用于测试,使用测试设备,因为正如我所说,应用程序之前不知道 MACAddresses),我得到了这样的东西:

0X020106124355420000080390BECB49400400CB500CF

抱歉问了这么长的问题,但我尽量使它尽可能完整。

我已经尝试了所有可以使用这些 scanFilter 方法的方法,但无法使其正常工作。

有人知道如何实现这个吗? 我为此疯狂了一个多月。

提前致谢!

我终于用两种方法弄清楚了。

  1. 使用 ScanCallback

     ScanCallback mScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { byte[] scanRecord = result.getScanRecord().getBytes(); //scanRecord will give you the raw advertisement data given by the device in byte array. } @Override public void onBatchScanResults(List<ScanResult> results) { for (ScanResult sr : results) { // } } @Override public void onScanFailed(int errorCode) { // } };
  2. 使用 LeScanCallback

     BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { //scanRecord will give you the raw advertisement data given by the device in byte array. } };

你可以从这个字节数组中筛选出你想要的设备。

例如:

为了仅找出心率监测设备,我已将 scanRecord 字节数组转换为字符串,然后检查其中是否出现了“0d 18”。

如果设备原始广告数据包含“0d 18”字符串,则它是心率监测器,否则不是。

如果有人还需要帮助,请告诉我

我终于找到了解决方案。 它没有回答有关通过原始广告数据进行过滤器扫描的问题,但是,我可以扫描我需要的设备。 这就是我所做的:

首先,我按名称做了一个过滤器。 虽然设备没有名称,但我按名称过滤以扫描name == null设备。

private List<ScanFilter> scanFilters() {
    List<ScanFilter> list = new ArrayList<ScanFilter>();

    ScanFilter scanFilterName = new ScanFilter.Builder().setDeviceName(null).build();

    list.add(scanFilterName);

    return list;
}

在那之后,我需要第二个过滤器(它不在上面的 scanFilters() 方法上,它在 scanResult 上)因为它返回给我大量的设备,并且该过滤器是通过 MAC 地址前缀(这是我的设备也是如此)。

private Set<String> btDevice = new LinkedHashSet<String>();

private ScanCallback scanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {

        BluetoothDevice device = result.getDevice();

        ScanRecord record = result.getScanRecord();
        byte[] dataByteArray = record.getBytes();

        if (device.getAddress().startsWith("F8:36:9B")) {
            btDevice.add(device.getAddress());
        }
    }
};

最后,我只需要扫描我需要的设备。 我仍然想知道主要问题,所以如果有人对此有解决方案,请随时回答。 谢谢!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM