具有BLE GATT特征的流数据的方案

Tra*_*ggs 5 bluetooth-lowenergy gatt

BLE的GATT架构适用于小的固定数据(每个特性最多20个字节).但在某些情况下,您最终希望"流式传输"一些任意长度的数据,即大于20个字节.例如,固件升级,即使您知道它很慢.

我很好奇其他人使用过什么方案,以便在BLE特征上"流式传输"数据(即使是小而慢).

到目前为止,我使用了两种不同的方案:

一种是使用控制特性,其中接收设备通知发送设备已经接收了多少数据,然后发送设备使用它来触发对不同特征的下一次写入(我同时执行with_response和without_response).

我最近做的另一个方案是将数据基本上分成19个字节的段,其中第一个字节表示当它达到0时要跟随的数据包的数量,这表明接收器可以将所有最近的更新连接并处理为一个包.

我正在寻找的那种答案,概述了有经验的人如何实现这样做的体面模式.并且可以证明为什么他们所做的是最好的(或至少更好的)解决方案.

Nip*_*ipo 17

在对现有协议进行一些审查之后,我最终设计了一个用于无线更新我的BLE外设的协议.

设计假设

  1. 我们无法预测堆栈行为(协议将与我们的所有产品一起使用,无论使用哪种芯片和供应商堆栈,无论是在外围设备侧还是在中心端,可能还未知),
  2. 使用标准的GATT服务,
  3. 避免L2CAP碎片,
  4. 假设数据包在TX之前排队,
  5. 假设可能有一些丢弃的数据包(即使堆栈不应该),
  6. 避免不必要的包往返,
  7. 将代码复杂性放在中心端,
  8. 假设4.2增强功能不可用.

1表示2-5,6表示性能要求,7表示优化,8表示可移植性.

整体设计

在发现服务并读取一些只读特征以检查设备与要上载的图像的兼容性之后,所有上载都发生在两个特征之间:

  • 有效载荷(只写,无响应),
  • 身份(须予公布).

整个固件映像通过有效负载特性以块的形式发送.

有效负载是一个20字节的特性:4字节的块偏移量加上16字节的数据块.

状态通知告知是否存在错误条件,以及下一个预期的有效负载块偏移量.这样,上传者可以判断它是否可以继续推测,从其自己的偏移量发送其块,或者它是否应该从状态通知中找到的偏移量恢复.

发送状态更新有两个主要原因:

  • 当一切顺利(有效载荷按顺序飞入)时,以给定的速率(如4Hz,而不是每个数据包),
  • 出现错误(乱序,经过一段时间没有收到有效载荷等),具有相同的给定速率(不是每个错误的数据包).

Receiver期望所有块按顺序排列,它不会重新排序.如果块发生故障,它将被丢弃,并且会推送错误状态通知.

当状态进入时,它会隐式地确认具有较小偏移的所有块.

最后,在发送方有一个传输窗口,许多成功的确认飞行允许发送者扩大其窗口(在匹配确认之前发送更多的块).如果发生错误,窗口会减少,丢弃的块可能是因为队列在某处溢出.

讨论

使用"单向"PDU(无响应和通知写入)是为了避免6.以上,因为ATT协议明确告知已确认的PDU(写入,指示)不得流水线化(即,在收到响应之前,您可能不会发送下一个PDU).

状态,包含最后收到的块,缓和5.

为了遵守2.和3.,有效载荷是20字节的特征写入.4 + 16有许多优点,一个是偏移验证,一个16字节的块只涉及移位,另一个是块总是在目标闪存中页面对齐(更好的是7).

为了处理4.在接收状态更新之前发送了多个块,推测它将被正确接收.

该协议具有以下功能:

  • 它适应无线电条件,
  • 它适应发送方的队列,
  • 目标没有任何状态泛滥,
  • 队列保持填充,这允许整个中央堆栈使用每个可能的TX机会.

一些参数超出了此协议:

  • central应强制执行短连接间隔(尝试在更新程序应用程序中强制执行);
  • slave PHY应该具有良好的从属延迟(YMMV,测试你的供应商的堆栈);
  • 您应该压缩有效负载以减少传输时间.

数字

附:

  • 15%压缩,
  • 与connectionInterval = 10ms连接的设备,
  • 主PHY将每个连接事件限制为4-5个TX数据包,
  • 平均无线电条件.

我平均每个连接事件得到3.8个数据包,即在数据包丢失,协议开销等之后有效负载约为6 kB/s.

这样,在不到10秒的时间内完成60 kB图像的上传,整个过程(连接,发现,传输,图像验证,解压缩,闪烁,重启)在20秒内完成.