这个问题从哪里来
第一次联调无人机任务回传,现场同时有十几台设备上报状态。很快发现有的状态一直在“任务中”,有的又提前“已完成”,调度端不知道该信谁。
当时真正难的地方
- 状态粒度:任务与执行序列的状态是否分开定义。
- 上报时机:是命令发出就算,还是设备确认才算,还是执行完成才算。
- 乱序与重放:网络不稳时,回传先后顺序被打乱怎么办。
- 幂等:同一条完成消息重复到达,会不会把状态来回翻。
created -> accepted -> flying -> returning -> finished
↘ failed / cancelled
每个状态要有一致的时间来源、幂等的触发条件、明确的终结态。宁可多一个中间态,也不要让两个终态互相覆盖。
真项目里怎么把两个编号、一条状态机定死
联动民用无人机平台时,最容易被低估的是“编号语义”和“状态口径”,它们要在联调前就写进约定:
- 两个编号别混淆:平台方发起的
missionId是飞控任务编号,我们本地要关联用的是发任务前生成的taskId。回调用taskId把状态挂回本地任务,missionId只是登记。用哪个关联、哪个登记,必须固定,不能互相替代。 - 来源编码要唯一:任务来源
rwly是有业务语义的编码,新接入方必须申请不重复的值,发起、开始回调、结束回调要一致,否则跨系统对不上账。 - 状态值先对齐:确认清楚
taskState的取值(进行中/完成/失败)以及失败时用哪个字段带原因;回调地址callbackUrl也在发任务时传给平台,是整套状态回调的入口。 - 时间口径:开始、结束时间统一到同一格式,设备时钟与我们时钟分开存,排查乱序才有依据。
状态机能不能跑通,一半靠后端状态定义,一半靠“编号语义和回调约定”在联调前就落到文档。等到现场十几台设备同时上报再发现编号对不上,就晚了。
可复用经验
- 任务级与动作级状态拆开,上层只见任务状态,细节留给执行层。
- 使用带版本号的乐观并发,避免旧消息覆盖新状态。
- 回传带上设备时钟与命令版本,方便乱序排查。
- 所有状态变化可回溯,现场才能回答“那一秒到底发生了什么”。
留给下次
想把状态机画成一张可以在评审会上直接解释的图,让非技术同事也能看懂流程。