首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >BLE 控制超时后再点一次,设备会不会执行两遍?

BLE 控制超时后再点一次,设备会不会执行两遍?

原创
作者头像
用户12804073
发布于 2026-10-07 22:04:04
发布于 2026-10-07 22:04:04
180
举报

手机发送一次动作,设备开始执行,结果还没回到手机,连接断了。按钮恢复可点,用户再点一下。第二次点击究竟是在查询上次结果,还是在创建一个新动作?

如果协议没有区分,界面里的“重试”就可能变成设备上的“再执行一次”。下面用虚构的移动指令讨论这个问题,实际动作测试应在仿真或无负载环境中进行。

业务指令接收、去重、执行和重启核对的关系
业务指令接收、去重、执行和重启核对的关系

图:超维方程技术团队绘制。BLE 链路确认与业务动作完成需要分开处理。

写响应不是执行结果

Bluetooth ATT 定义了写请求和写响应,也定义了没有对应写响应的写命令。但设备把某个属性值解释为“移动一次”以后,动作多久完成、怎样报告失败,是应用协议要补充的内容。

手机收到写响应,只能按协议解释这个响应,不能直接把执行机构显示为“已到位”。反过来,手机没收到业务结果,也不能证明动作没有发生。

这里真正需要区分的是:请求是否被接受、动作是否开始、动作是否完成、手机是否已经获知结果。四者可能在不同时间成立。

一次动作一个编号,重试沿用旧编号

下面是一个说明性的业务消息,不是 Bluetooth 标准数据格式:

代码语言:json
复制
{
  "controller": "demo-controller-A",
  "request_id": "demo-move-017",
  "operation": "move_relative",
  "arguments": { "axis": "x", "steps": 1 }
}

同一次动作因通信失败重发时,保持 request_id 不变。只有用户确实要求另一轮动作,才生成新编号。控制端重新连接,不应自动把所有未确认请求变成新请求。

设备侧用控制端作用域与请求编号定位记录,再比较规范化后的业务参数。同一个编号配上不同参数,应返回冲突,而不是覆盖旧记录。参数摘要可辅助比较,但不能替代原始业务校验和访问授权。

设备已有的记录

收到同一请求后的处理

没有记录

校验参数、权限和当前状态,再决定是否接受

已接受或执行中

返回现有进度,不再次启动动作

已完成

返回保存的结果,注明这是上次动作的结果

参数不同

拒绝冲突,不擅自解释成新动作

记录已过期且无法核实

返回结果不确定,要求重新核对设备状态

“查询不到”不是“从未执行过”。记录可能已过期,也可能在掉电时丢失。设备没有证据时,应把不确定性传给上层。

两个重复请求同时到达怎么办?

如果程序先查询编号、再启动动作、最后写记录,两条并发请求可能同时查到“没有”,然后都执行。单线程主循环或任务队列也不能凭名称就保证没有这种交错,需要查看实际执行路径。

常见做法是将“占用编号并记录已接受”放到受控的原子边界内,后续重复请求只读取同一条记录。这个边界怎样实现取决于设备运行环境,可能是串行处理、临界区或具有一致性保证的存储操作。不要把一段内存字典伪代码当成跨任务、跨掉电都可靠的实现。

资源也有限。去重记录应有容量、保留时间和清理规则。清理后收到迟到请求,协议要能回答“记录已不在保留窗口”,而不是默默执行一次。

掉电会留下最难解释的窗口

考虑这样的顺序:接受记录已经写入,动作完成,完成结果还没落盘就断电。重启后只看到“执行中”,该不该再做一次?

对不可逆动作,简单重做并不安全。可能需要读取位置或状态传感器、人工核对,或者让动作本身具有可恢复的检查点。软件日志与物理世界不天然构成一个事务,因此仅加一个请求编号,不能宣称实现了跨掉电的“恰好一次”。

能表达目标状态的业务,可以优先考虑目标式命令,例如“亮度设为 40%”,而不是“增加 10%”。但这只改善业务语义,不会自动解决所有副作用、授权和硬件恢复问题。

把失败窗口写成测试步骤

比正常收发更有价值的是下面几组测试,所有次数统计都要看实际动作,不能只数手机上的成功日志:

  1. 动作接受后断连,再用原编号重发,确认没有多启动一次。
  2. 动作完成后丢弃结果,再查询和重发,确认返回原结果。
  3. 同编号改参数,确认设备拒绝冲突。
  4. 两个相同请求并发到达,检查接受路径是否只建立一个执行实例。
  5. 在接受记录、实际动作和结果保存的交界处安排受控故障,检查重启后的核对方式。
  6. 记录过期后重发旧请求,确认系统不会把“不知道”显示成“从未执行”。

最后检查手机文案。超时后先显示“结果尚未确认,正在查询设备”,比立即恢复一个含义不清的重试按钮更符合真实状态。

参考资料:Bluetooth Core Specification:Attribute Protocol。本文的编号、状态和去重表是应用层设计建议,不是 ATT 自动提供的保证。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 写响应不是执行结果
  • 一次动作一个编号,重试沿用旧编号
  • 两个重复请求同时到达怎么办?
  • 掉电会留下最难解释的窗口
  • 把失败窗口写成测试步骤
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档