BLE 指令超时后,能不能再发一次?

0 阅读3分钟

手机让设备“向前移动一步”,等待结果时连接断了。界面出现重试按钮,用户再点一次,设备会走一步,还是两步?

问题在于,手机没收到结果,并不能证明设备没执行。这篇超维方程技术笔记讨论业务指令的重试,不涉及某款设备的实测。

BLE 业务指令重试与结果确认关系图

图:超维方程技术团队绘制。写入确认、动作完成和重启后核对是不同环节,不能只靠重发请求获得确定结果。

先区分写入确认和动作完成

Bluetooth 的 ATT 规范里,写请求的响应确认的是属性写入;无响应写入则没有对应的写响应。[1] 如果你的业务把“收到某个属性值”解释为启动一个耗时动作,还需要另外定义动作完成的反馈。

例如,消息可以依次经历“已接收”“已接受”“执行中”“已完成”。不是所有产品都需要这四个状态,但界面不能把第一个状态直接显示成最后一个。

收到写响应,也不代表执行机构已经到位。这里要等什么结果,应由业务协议决定。

能表达目标状态,就少表达相对动作

“把亮度设为 40%”与“亮度增加 10%”有不同的重试语义。前者重复处理,目标值仍是 40%;后者重复处理,结果会继续变化。

这不意味着所有指令都能改成目标状态。移动、投料或触发一次采样等动作,仍可能需要单独识别每次请求。

可以为一次业务动作分配 request_id。重发时沿用同一个标识,设备在约定范围内识别重复请求,并返回之前的结果或当前进度。新动作才使用新标识。

收到的请求一种可评审的处理方式
新标识、新动作校验参数与权限后,接受执行
相同标识、相同参数,仍在执行返回执行中,不再次启动
相同标识、相同参数,已经完成返回已保存的结果
相同标识、不同参数拒绝冲突,要求调用方核查

这张表是应用层设计建议,不是 BLE 协议自动提供的保证。

去重记录也有生命周期

仅在内存里保存最近几个标识,设备重启后就可能忘记。若断电发生在动作完成之后、结果保存之前,下一次重试仍有歧义。

对于不可逆动作,需要结合持久化记录、动作执行顺序、位置或状态传感器,设计重启后的核对过程。只加一个请求编号,不能宣称实现了跨断电的“恰好执行一次”。

还要确定标识作用域和保留时间。不同控制端、不同设备和新的会话之间,应避免把无关动作误判为重复。过期请求是否允许再次执行,也要写进协议。

测试应包含“执行了,但没回信”

正常收发只能验证最顺利的路径。更有价值的测试是:动作已经开始,结果返回前断连;动作完成后重发;相同标识携带不同参数;设备重启后再收到旧请求。

观察实际动作次数,不能只看手机日志打印了几次“成功”。涉及运动或其他不可逆动作时,先在仿真或无负载测试设备上验证。

对用户而言,超时后的正确提示有时是“结果尚未确认,正在查询设备状态”,而不是立即邀请他再执行一次。

参考:Bluetooth Core Specification:Attribute Protocol。[1]

作者:超维方程技术团队。