10

我正在编写一个 BLE 应用程序,需要跟踪外围设备是广告还是停止。

我遵循了没有重复的外围设备和 startLeScan() 的 BLE过滤行为,我完全同意这里。

为了使其可行,我保留了计时器,该计时器在一定时间(3 秒)后重新扫描外围设备。但是随着市场上的新设备(带有 5.0 更新),重新扫描需要一些时间来查找外围设备。

有什么建议或者是否有人实现了这一点?

4

3 回答 3

5

听起来您对扫描广告而不是连接到设备感兴趣。这是 Bluetooth Low Evergy 中的“观察者”角色,对应于通常称为 Beacon 的“广播者”角色。(蓝牙核心 4.1 第 1 部分 A 部分第 6.2 节)

通常,您启用被动扫描,寻找信标广播的 ADV_IND 数据包。这些可能包含也可能不包含 UUID。或者,您可以通过发送 SCAN_REQ 来进行主动扫描,您可能会收到 SCAN_RSP。许多设备在 ADV_IND 和 SCAN_RSP 中使用不同的广告内容来增加可以广播的信息量 - 例如,您可以将 UUID128 放入 ADV_IND,然后在 SCAN_RSP 中添加设备名称。(蓝牙核心 4.1 第 2 部分 E 部分第 7.8.10 节)

现在您需要定义“消失”——您希望广告停止还是消失?您将获得每个广告的接收信号强度指示“RSSI” (蓝牙核心 4.1 第 2 部分 E 部分第 7.7.65.2 节) - 这就是 iBeacon 定位的工作原理,并且在 Android 中有大量对信标接收器的支持。

或者,您等待N秒等待应该每T秒传输一次的广告,其中N>2T。定时方法的缺点是可能没有收到信标与肯定收到弱信标不同。确保您需要N很大,这会影响广播公司被关闭或超出范围与您的应用程序检测到它之间的延迟。

还有一件事——注意如果有东西连接到外围设备(如果你真的在扫描外围设备),广告就会停止,这是监控 RSSI 的另一个好理由。

于 2015-07-20T14:13:26.620 回答
3

编辑:我忘了,您是否尝试将广告商设置为不可连接?这样你应该能够得到重复的扫描结果

我正在处理一个类似的问题,即随着时间的推移可靠地跟踪多个广告设备的 RSSI 值。

可悲的是,我发现的最可靠的方法不是很好,很脏而且很耗电。似乎由于处理 BLE 的方式不同的 android 设备的数量是最可靠的。

我开始 LE 扫描,一旦我收到回调,我就会设置一个标志来停止并再次开始扫描。这样您就可以解决DUPLICATE_PACKET 过滤器问题,因为它会在您开始新扫描时重置

我将 ScanResults 转储到一个 sqlite db 中,我每 x 秒收缩和评估一次。

应该很容易使收缩适应您的用例,即删除早于 X 的条目,然后查询设备的存在以查明您是否在最后 X 秒内收到了 ScanResult。但是不要把这个 X 值放得太低,因为你必须考虑到你仍然会在 android LE 扫描上丢失很多广告数据包,与 ie bluez 上的 BLE 扫描相比。

编辑: 我可以添加一些我已经找到的信息,以加快广告发现的性能。它涉及修改和编译 bluedroid 源代码以及对设备的 root 访问权限。最简单的方法是自己构建一个完整的 android,即 Cyanogenmod。

当 LE 扫描运行时,蓝牙模块通过 HCI 将扫描响应发送到 bluedroid 堆栈。在最终将其交给onScanResult(...)通过 JNI 访问的 Java 之前,会进行各种检查。

通过比较从蓝牙模块发送的 hci 数据日志(可以在 /etc/bluetooth/bt_stack.conf 中启用)与 bluedroid 堆栈以及 Java 端中的调试输出,我注意到很多广告数据包被丢弃,尤其是在一些检查。我不太明白,除了它与 bluedroid 查询数据库 有关。从 ScanResult 的文档中,我们看到 ScanRecord 包括广告数据和扫描响应数据。因此,可能是 android 会阻止报告,直到它获得扫描响应数据/直到明确没有扫描响应数据。这我无法验证,但有可能。

因为我只对这些数据包的 RSSI 的快速更新感兴趣,所以我只是评论了检查。似乎我通过 hci 从蓝牙模块获得的每个数据包都被传递到 Java 端。

在文件btm_ble_gap.c中,从第 2265 行开始的以下检查中的函数BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_type, UINT8 *p) 注释掉to_report = FALSE;

/* active scan, always wait until get scan_rsp to report the result */
if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
     (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
{
    BTM_TRACE_DEBUG("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
                          scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
    p_i->scan_rsp = FALSE;
    // to_report = FALSE; // to_report is initialized as TRUE, so we basically leave it to report it anyways.
}
else
    p_i->scan_rsp = TRUE;
于 2015-07-21T13:35:11.133 回答
3

第一种情况:绑定设备

我们知道,如果bond制作了a,那么大多数市售设备都会directed advertisements在重新连接期间发送。在这种情况下,根据 BLE 4.0 规范,您无法在任何 BLE 嗅探器上扫描这些设备。

第二种情况:可连接设备

当外围设备最初处于复位阶段时,它们通常处于这种模式。中央发送一个connect发起者来响应一个advertisement数据包。此方案为您提供了很大的灵活性,因为您可以使用两个主要的配置选项来改变连接时间。它们是:slavelatency在外围和conninterval中央。现在,我不知道要让它在 Android 平台上运行需要付出多少努力,但如果您使用 Bluez BLE 堆栈和可配置的外围设备(例如 TI 传感器标签),那么您可以使用这些值。

第三种情况:信标设备

由于这是您的问题所围绕的问题,因此根据 BLE 架构,没有可使用的参数。在这种情况下,中央只是一个愚蠢的设备,任由外围设备选择发送它的信标信号。

参考:

http://www.amazon.com/Inside-Bluetooth-Communications-Sensing-Library/dp/1608075796/ref=pd_bxgy_14_img_z

http://www.amazon.com/Bluetooth-Low-Energy-Developers-Handbook/dp/013288836X/ref=pd_bxgy_14_img_y

于 2015-07-17T01:23:27.303 回答