问题描述
在iOS上,某些数据包会通过BLE丢失。
在特征上,我们当然会检查.withoutResponse
和canSendWriteWithoutResponse
的类型func peripheralIsReady(toSendWriteWithoutResponse peripheral: CBPeripheral)
。
文档中也对此进行了说明。
另一方面,如果您将写入类型指定为 CBCharacteristicWriteType.withoutResponse,核心蓝牙尝试 写下价值,但不能保证成功。如果写不 在这种情况下成功,您不会收到通知,也不会收到 错误,指示失败原因。
任何人都知道如何在不切换到withResponse
的情况下解决此问题?
解决方法
作为一个例子,您可以在您的中央设备所订阅的外围设备中创建一个“确认”特征。发送写操作时,您将等到收到来自该特征的通知。如果超时后仍未收到通知,则可能是写入已丢失。这样可以在更高的层上重新实现标准的带响应写系统。
我处理的几个BLE协议实际上是串行协议(我们写入特性,并从相同特性读取响应)。我们通常直接在串行协议中实现ACK(例如,返回<msgid>OK
),而无需BLE写响应。
另一种解决方案是写入特征,然后从特征中读取以查看其是否已更新,前提是特征是以这种方式对称的(很多不是)。我相当确定,这里没有写缓存会咬你,因为BLE读和写通常不对称,但是在依赖它之前应仔细检查。 (请参阅2019年和2017年的Core Bluetooth WWDC视频。)
与所有分布式系统一样,也永远不可能知道数据丢失。数据可能到达了,并且响应丢失了。这是分布式协议的本质,只是必须要考虑到系统中。这就是为什么可以构建至少一次传递消息 的系统(前提是可以传递),或者构建一个最多传递消息 的系统。一次,但是不可能构建一个可以准确地一次发送消息的系统。
如果您无法控制外围设备,并且不提供任何错误检测机制,那么在中央(电话)端您将无能为力。您必须双方都进行一些合作才能构建容错的分布式协议。