我最近正在研究一个使用低功耗蓝牙的项目。我实现了大多数通信协议,但是我开始担心,实际上我不知道数据传输的工作方式,以及我实现的解决方案是否在所有设备上都以相同的方式运行。
所以我主要关心的是,当我收到peripheral(_:didUpdateValueFor:error:)
的通知时收到了什么数据块?它仅与协商的MTU大小一样大吗?还是iOS会接收有关块大小的信息,然后等待接收所有信息,然后再触发peripheral(_:didUpdateValueFor:error:)
?
当外围设备发送块时,假设每个块发送100个字节,我是否可以假设我总是在单个通知中得到100个字节?还是前一个块的后50个字节和下一个块的前50个字节?那将非常棘手,而且很难检测到我帧的开始位置。
我试图在Apple文档中找到更多信息,但与此无关。
我的猜测是,我总是会收到单一的特征状态。因此,这意味着块依赖于外围方面的实现。但是,如果特征大于MTU大小怎么办?
答案 0 :(得分:2)
首先,请记住,通过特征发送流数据并不是为该特征设计的。特征的要点是代表一些小信息(约20字节),例如当前电池电量,设备名称或当前心跳。这个想法是,只有当潜在价值改变时,特征才会改变。它从未被设计为串行协议。因此,您的默认假设应该是由您来管理与此有关的所有事情。
向特征写入的数据不应超过从maximumWriteValueLength(for:)
获得的值。分块是您的工作。
您写入的每个值都会自动显示给接收器。请记住,这些值旨在作为单个值,而不是较大数据流中的块,因此,将来自同一特征的值重叠是没有意义的。 “原子”表示全部到达或完全不到达。因此,如果您的MTU可以处理100个字节,而您写入100个字节,则另一端将收到100个字节或什么都不接收。
也就是说,BLE中几乎没有错误检测功能,您绝对可以丢弃数据包。由您来验证数据是否正确到达。
如果您可以使用iOS 11+,请查看L2CAP,它是为串行协议而不是使用GATT设计的。
如果您不能这样做,建议您观看WWDC 2013 Session 703,其中详细介绍了此用例。 (不过,我现在找不到链接了。)