如果您使用 CoreBluetooth 而不是 CoreLocation 来扫描信标,则检测到的每个广告数据包都会收到一个回调,而 CoreLocation 每秒会收到一个回调。这两种方法各有利弊,所以重要的是要准确了解每个工作是如何做出正确选择的。 Beacon 的广告速率对优缺点影响很大,标准的 iBeacon 广告速率为 10 Hz。
使用 CoreLocation 测距
以下方法将每秒获得一次回调,但仅适用于匹配 iBeacon 布局并匹配该布局内的 ProximityUUID 的 BLE 广告,该布局已注册为 CLBeaconRegion 对象的一部分。当满足这些条件时,每秒调用一次以下回调无论在该时间间隔内检测到多少信标数据包:
locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion).
beacons 数组中的每个 CLBeacon 对象都有一个 rssi 字段。该字段包含在过去一秒间隔内检测到的所有信标数据包的平均 rssi。
如果信标以 10 Hz 的频率进行广播,则此 rssi 读数将是过去一秒内收到的 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 数据收集没有用处。