Android 4.3:BLE:startLeScan()的过滤行为

时间:2013-10-21 19:17:02

标签: android android-sensors bluetooth-lowenergy android-bluetooth

我正在开发一个蓝牙传感器设备,我需要为此形成一对多的数据广播。根据规范,外设可能只有一个主机,由于我正在设计的芯片和堆栈的限制,主机只能有三个从机。根据我的理解,Android无论如何都不能成为BLE奴隶,因此将我的设备作为主设备不是一种选择。

BT4规范和制造商文档都讨论了另一种操作模式,称为广播模式。在广播模式中,从不进行连接,并且应用数据作为广告包的一部分被发送。这完全符合我的需求,因为许多Android / iOS手机可以同时扫描每个数据包。广告数据包以突发方式多次传输,因此我怀疑数据接收最可靠。如果数据包在此处丢失,则可以容忍。

这有趣的地方在于,我希望这些数据包能够传输实时传感器数据,并以10-20Hz的速率进行更新。从我在网上找到的例子来看,这种模式下的BLE主要用于“iBeacon”类型的实现,它们在那里广播静态数据。我找不到有关如何在Android堆栈中过滤广告数据包的任何信息。它可能是每个蓝牙硬件地址返回一个结果,或者它可能是地址和数据的唯一组合。第二个选项适用于此应用程序。如果启动和停止扫描重置过滤器,我也可以做一些工作。

Android文档未提及扫描方法中的设备过滤如何工作。我已经能够在网上找到一个试图解决同一问题的帖子,该问题有一个未解决的问题:BLE: Multiple discovery of the same peripheral during scan。在iOS中,我的同事通知我,有一个参数可以传递给扫描函数,使其成为可能。

我试图从Android源代码中的startLeScan()调用回溯代码,但是代码非常复杂,并且使用抽象使得很难识别包含它的对象的实现。我得到的最远的是从BluetoothManagerService类方法getBluetoothGatt()返回的IBluetoothGatt对象。该对象接收开始扫描的请求。它正在github上的当前版本上实例化line 790 of BluetoothManagerService.java。该对象是从消息的结果转换而来的,所以我怀疑结果可能是电话/驱动程序特定的。能够进一步追踪它是我的专长。

我想解决的另一个问题是可以快速打开和关闭扫描。扫描是一项功耗密集型操作,但数据广播将在相当精确的实时计时器上定期进行。因此,如果可以打开和关闭扫描,这将是一个很好的优化,使得广播和扫描同步,扫描仪关闭其他90%以上的时间。这可能需要通过实验进行测试。

我仍在进行可行性研究,看看我们的Android配件是否可行。我现在的手机还没有运行4.3版,所以我无法通过实验测试/黑客攻击。

5 个答案:

答案 0 :(得分:27)

到目前为止,Android 4.3和4.4似乎是一团糟:有些设备会调用 在一次扫描中,一个设备多次onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord),有些则没有。没有办法像在iOS中那样配置过滤(参见答案) Arkadiusz Konior)。所以,我现在开始列表,因为我无法向用户询问有关其设备的问题。

但是,重新开始扫描对“不过滤”设备也没有问题。所以,我现在重新开始扫描每台设备。

不过滤(连续调用onLecan())

  • 三星Galaxy S4和4.2.2使用Samsung BLE sdk(我拥有该设备)
  • Nexus 5 with 4.4(由[vegarwe]添加。设备将在扫描时连续为附近的设备提供扫描记录)
  • Samsung Galaxy S3 with 4.3(JSS15J.I9300XXUGMK6,我正在该设备上测试)
  • 使用Android SDK的4.3和4.4.2的三星Galaxy S4(由arnaud.b添加,未提供构建)
  • HTC One with 4.4.2(arnaud.b添加,未提供内部版本号)

过滤设备(适用于标准版)

  • Nexus 4 4.3,4.4(我拥有该设备)
  • Nexus 7 2013 4G 4.4.2(KOT49H,我正在该设备上测试)
  • 三星Galaxy S4 mini 4.2.2(我在此设备上测试)
  • 摩托罗拉Moto X(由user1603602添加,没有提供有关Android版本的信息)
  • 摩托罗拉Moto G 4.3(falcon_umts,我的测试设备)
  • 采用Android 4.3的Sony Xperia Tablet Z Wifi(Build 10.4.B.0.577,Model SGP311,我的测试设备)
  • OnePlus One 5.0.1和5.1.1(Cyanogen 12.1)

未知的过滤行为(请帮助将设备与特定群组相关联)

  • Nexus 7 2013(报告的行为与here不同。但我已阅读更多报告,表明它属于第一组。)
  • 其他SAMSUNG,HTC,摩托罗拉,......,设备

答案 1 :(得分:14)

蓝牙规范(Core_v4.1.pdf)第2535-2536页中有关重复广告报告的文字有点不清楚。但是,第1258页上的文字很清楚。它为HCI_LE_Set_Scan_Enable命令指定Filter_Duplicates参数。在Android版本4.4(Kitkat)中,此参数为0x00(禁用重复过滤)。

有一种简单的方法可以确定是否在Android版本4.4(Kitkat)的蓝牙芯片中进行了任何过滤。将手机设为开发人员手机,输入开发人员选项并选中“启用蓝牙HCI监听日志”。然后将蓝牙关闭并打开一次以进行设置咬合。从现在开始,应用程序处理器和蓝牙芯片之间的所有HCI数据包将存储在手机中的文件中,该文件由adb pull storage / emulated / legacy / btsnoop_hci.log提取。这不是文本文件,您需要来自http://www.fte.com/products/default.aspx或wireshark的程序才能查看btsnoop_hci.log。对于wireshark,你需要一个非常新的版本,因为旧版本不支持BLE。我的经验是蓝牙芯片中没有任何过滤,即HCI事件“LE广告报告事件 “为每个ADV_IND发送  和ADV_NONCONN_IND  蓝牙芯片收到的。这适用于配备蓝牙芯片Qualcomm / Atheros WCN 3680和Broadcom BCM 4339的手机。

更正:btsnoop_hci.log的路径可能因手机制造商而异。你可以通过adb shell cat etc / bluetooth / bt_stack.conf找到正确的路径grep BtSnoopFileName

答案 2 :(得分:8)

我正在使用BLE为Android 4.3(Nexus 4& 7)开发应用程序,并且根据我的观察,如果没有扫描请求发送回外围设备,扫描会多次返回同一设备。

设备可以通过两种方式进行宣传:被动和主动。在被动模式下,外围设备只是广告其所有数据,并且在发送周期性数据包后不会监听。它只是发送,睡觉,发送,睡觉...... 在活动模式下,传感器也会通告但消息尽可能短。发送后,它会切换到收听很短的时间。当扫描检测到短消息时,它立即将SCAN REQUEST命令发送到外设并获得更多详细信息的响应。据我所知,Android在一次扫描中没有多次发送SCAN REQUEST。

假设我们有2个范围内的设备。一个是f.e. Nordic的nRF Temp传感器(无源广告)和另一种可连接设备。我收到了以下扫描回复:

11-10 21:32:54.281: D/BluetoothAdapter(13468): startLeScan(): null
11-10 21:32:54.281: D/BluetoothAdapter(13468): onClientRegistered() - status=0 clientIf=4
11-10 21:32:54.321: D/BluetoothAdapter(13468): onScanResult() - Device=CD:61:1A:A8:BC:BE RSSI=-94
11-10 21:32:55.122: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:56.414: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:32:57.715: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:59.016: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:01.609: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:02.901: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:04.212: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:33:04.282: D/BluetoothAdapter(13468): stopLeScan()

正如您所看到的那样,可连接设备只出现一次而另一次出现了7次。

  

我想解决的另一个问题是可以快速打开和关闭扫描。扫描是一项功耗密集型操作,但数据广播将在相当精确的实时计时器上定期进行。因此,如果可以打开和关闭扫描,这将是一个很好的优化,使得广播和扫描同步,扫描仪关闭其他90%以上的时间。这可能需要通过实验进行测试。

扫描频率取决于设备。此外,广告通常在3个频道上进行:37,38和39,以增加被发现的概率。但是,多次从“活动”设备获取广告数据包可能是个好主意。

答案 3 :(得分:6)

实际的蓝牙规格说:

  

不需要将重复的广告报告发送给主机。   重复的广告报告是针对该广告报告的广告报告   链路层保持扫描状态时的设备地址。该   广告数据可能会改变; 广告数据或扫描回复数据   在确定重复广告时不被视为重要   报告。

根据规范,这适用于扫描期间,这表明正确的方法是每次收到广告时停止并重新开始扫描。

根据我对BLE的经验,似乎在广告中发送可变数据似乎不是一个好主意。几乎所有内容都假设来自广告的数据不会改变。如果你想实际发送可变数据(例如温度计读数),那么实际连接到设备并通过特性来实现它会好得多。它更可靠,功耗更低。缺点是你一次只能连接8台设备。

广告用于检测设备的存在并识别它们。

答案 4 :(得分:0)

在iOS中,此标志名为CBCentralManagerScanOptionAllowDuplicatesKey。将其传递给扫描功能会导致每个广告包的通知。我在Android中找不到类似的标志。