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

mat*_*ker 27 android android-sensors bluetooth-lowenergy android-bluetooth

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

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

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

Android文档没有提及扫描方法中的设备过滤如何工作.我已经能够在网上找到一个试图解决同样问题的帖子,它有一个未解决的响应:BLE:在扫描期间多次发现相同的外设.在iOS中,我的同事通知我,有一个参数可以传递给扫描功能,使其成为可能.

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

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

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

One*_*rld 27

到目前为止,Android 4.3和4.4似乎是一团糟:有些设备在一次扫描中对一台设备多次调用 LeScan(BluetoothDevice设备,int rssi,byte [] scanRecord),有些则没有.无法在iOS中配置过滤(请参阅Arkadiusz Konior的回答).所以,我现在开始列表,因为我无法向用户询问有关其设备的问题.

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

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

  • 三星Galaxy S4和4.2.2使用三星BLE sdk(我拥有该设备)
  • Nexus 5和4.4(由[vegarwe]添加.设备将在扫描时连续为附近的设备提供扫描记录)
  • 三星Galaxy S3 4.3(JSS15J.I9300XXUGMK6,我正在该设备上测试)
  • 使用Android SDK的4.3和4.4.2三星Galaxy S4(由arnaud.b添加,未提供构建)
  • HTC One 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(我在这台设备上测试)
  • Motorola Moto X(由user1603602添加,没有提供关于android版本的信息)
  • 摩托罗拉Moto G 4.3(falcon_umts,我的测试设备)
  • 索尼Xperia平板电脑Z Wifi搭配Android 4.3(Build 10.4.B.0.577,型号SGP311,我的测试设备)
  • OnePlus One 5.0.1和5.1.1(Cyanogen 12.1)

未知的过滤行为(请帮助将设备关联到某个组)

  • Nexus 7 2013(此处报告的行为不同.但我已阅读更多报告称其属于第一组.)
  • 其他SAMSUNG,HTC,Motorola,...,设备

  • 似乎相同的Android版本在所有设备上都没有相同的行为.所以我想这是过滤设备的蓝牙驱动程序?(任何专家都可以确认?)另外,Nexus 5使用Snapdragon 800(8974-AA)芯片组,与三星Galaxy S4(GT-I9506)的某些版本相同.Galaxy S4还有其他版本:基于snapdragon 600(APQ8064T)和GT-I9500(exynos)Nexus 4的GT-I9505,sony xperia平板电脑Z使用相同的芯片组(snapdragon s4 pro APQ8064).Moto X和Moto G也基于snapdragon s4 Nexus 7 2013基于snapdrago的不同芯片组(全部?) (2认同)

Tob*_*lin 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.我的经验是蓝牙芯片中从未进行任何过滤,即为蓝牙芯片接收的每个ADV_IND和ADV_NONCONN_IND发送HCI事件"LE广告报告事件".这适用于配备蓝牙芯片Qualcomm/Atheros WCN 3680和Broadcom BCM 4339的手机.

更正:btsnoop_hci.log的路径可能会有所不同,具体取决于手机制造商.你可以通过adb shell cat etc/bluetooth/bt_stack.conf找到正确的路径 grep BtSnoopFileName


phi*_*s77 8

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

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

假设我们有2个范围内的设备.一个是fe 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()
Run Code Online (Sandbox Code Playgroud)

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

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

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


Tim*_*mmm 6

实际的蓝牙规格说:

不需要将重复的广告报告发送给主机. 重复的广告报告是同一设备地址的广告报告,而链接层保持在扫描状态.广告数据可能会改变; 在确定重复的广告报告时,广告数据或扫描响应数据不被认为是重要的.

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

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

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


Ark*_*ior 0

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