实时更新外设RSSI

昨天在蓝牙技术交流群中有人提出了这样一个需求:
需要实时更新曾经搜索过并缓存下来的设备的RSSI, 不论连接与否

我当时随便想了下给出的建议是:

场景一: 没有连接过设备
1. 通过首次搜索, 能够获取到临近手机的外设, 拿到并更新一次RSSI
2. 定时调用`readRSSI`方法, 通过`peripheral: didReadRSSI:(NSNumber *)RSSI error:`回调来获取RSSI, 如果在身边的应当可以获取到RSSI并更新, 不在附近的会返回error, 将其置为离线状态(如果基于GAP协议的设备, 被其他设备连接后, 也将不再进行广播)
3. 至于时效性, 看定时器的间隔时间
场景二: 绑定过设备
这种情况可能不存在手动搜索这个环节, 直接按照场景一步骤2来

今天有空试了一下, 其实是满足不了这个需求的, 而我也想到了另外的实现方式, 先来分析下这种思路的问题在哪里

关键点就在与需要通过外设调用readRSSI, 然后 通过peripheral: didReadRSSI:(NSNumber *)RSSI error:回调来获取RSSI, 而我正是忽略了这两个API

按照这种思路直接遍历数组, 通过外设调用readRSSI, 那么控制台下你将看到如下报错:

 [CoreBluetooth] API MISUSE: Reading RSSI for peripheral  while delegate is either nil or does not implement peripheral:didReadRSSI:error:

如果你以为设置了delegate就可以了, 那么你将遇到下面的报错:

[CoreBluetooth] API MISUSE:  can only accept commands while in the connected state

我猜想将所有在周边的设备都连接上然后去更新RSSi的方式, 不是每个项目都满足的, 所以这个方法不太实际 , 仅适用于连接中的设备.

我想到的另外一种方式是:
通过设置搜索选项, 调用搜索外设API来拿到RSSI值信息
设置KEY: CBCentralManagerScanOptionAllowDuplicatesKey

这个KEY的官方介绍:

A Boolean value that specifies whether the scan should run without duplicate filtering.

The value for this key is an NSNumber object. 
If `YES`, filtering is disabled and a discovery event is generated each time the central receives an advertising packet from the peripheral. 
Disabling this filtering can have an adverse effect on battery life and should be used only if necessary.
If `NO`, multiple discoveries of the same peripheral are coalesced into a single discovery event.
If the key is not specified, the default value is `NO`.

过滤默认是开启的, 如果搜索选项设置为YES, 那么将会收到每次设备广播的信息, 外设广播一次会在37,38,39三个信号分别发送一次广播, 算是一次广播事件, 而广播事件间隔时间完全取决于嵌入式设置 (Link Layer允许Host在这三个物理信道中,任意选取一个或者多个,用于广播)

你可能感兴趣的:(实时更新外设RSSI)