我有一个需要信标范围的项目,我查看过大量使用CLLocationManager
和CLBeaconRegion
的示例代码。我的问题是didRangeBeacons
回调每秒只调用一次。
虽然我没有找到专门针对信标的任何代码示例,但我认为CoreBluetooth可以让我更好地控制我的应用扫描信标的频率吗?
我的想法是,如果我能够以更高的速率(比如说200ms)扫描信标,我将能够在我的过滤功能中使用更多的rssi值,因此可以获得更准确的接近度,而不需要花费太长时间。我假设这是正确的吗?
有人能指出我使用带信标的CoreBluetooth的任何示例代码/教程(如果值得付出额外的努力)?
答案 0 :(得分:3)
如果您使用CoreBluetooth扫描信标而不是CoreLocation,则每次检测到的广告数据包都会收到一次回调,而CoreLocation每秒都会收到一次回调。这两种方法都有优点和缺点,所以重要的是要准确理解每项工作如何做出正确的选择。优势和劣势受信标广告费率的影响很大,标准iBeacon广告费率为10 Hz。
使用CoreLocation范围
以下方法每秒将获得一次回调,但仅适用于与iBeacon布局匹配的BLE广告,并且匹配该布局中的ProximityUUID,该布局已作为CLBeaconRegion
对象的一部分进行了注册。满足这些条件时,每隔调用以下回调,无论在该时间间隔内检测到多少个信标数据包:
locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion)
。
CLBeacon
数组中的每个beacons
对象都有一个rssi
字段。该字段包含在过去一秒间隔内检测到的所有信标数据包的平均值rssi。
如果信标以10 Hz的频率发布,则此rssi读数将是过去2秒内收到的8-10个数据包的平均值(由于无线电噪声,冲突和干扰,通常仅接收80-90%的数据包)
如果信标以1Hz或更低的频率广告(典型的电池信标试图节省电力),则平均值中只包含一个rssi读数。 (无法知道回调返回的rssi值中有多少次检测。)
因此,虽然您无法从每次检测中访问rssi值,并且无法控制平均间隔,但在rssi值平均且噪声较小的意义上,您确实可以获得多次检测的好处比如果只有一个阅读。 CoreLocation因此为您提供与CoreBluetooth一样多的准确性,前提是您愿意接受其硬编码的平均间隔。
CLBeacon
对象还包含accuracy
和proximity
的字段,这些字段基于较长间隔过滤的rssi的派生值(实验显示它大约为20秒)。 API在此平均间隔内无法控制,对于某些需要快速更新距离估计值的应用程序,20秒是一个非常长的延迟。
使用CoreBluetooth扫描
这通常通过设置允许重复结果的标志来完成:
centralManager.scanForPeripherals(withServices: [], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true] )
开始上述扫描时,会对检测到的每个蓝牙广告进行以下回调:
centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
此回调中的rssi编号是单个数据包检测的原始值。如果您的信标以10 Hz的频率发布广告,则此方法每秒将获得8-10次回调(同样,不会收到100%的数据包),您可以根据需要对rssi进行平均或过滤。这使您可以对使用rssi进行细粒度控制,并且可以对任意平均间隔进行距离估计。
上述动机促使我开发了开源iOS Beacon Tools,它允许检测具有CoreBluetooth
的培根,并根据通过任意指定的平均间隔收集的rssi计算距离估计值。
但是,使用CoreBluetooth
:
iBeacon数据包无法解码,因为操作系统会过滤掉与其布局匹配的任何数据包的数据有效负载。因此,您必须使用类似AltBeacon的布局,或使用Eddystone框架。
像AltBeacon这样的制造商广告不会在后台投放,只能在前台投放。
Eddystone等服务广告在后台发布,但速度非常慢。所以它对rssi数据收集没用。