设备现场最常见的“恢复方案”是弹窗、重试和重启:捕获异常后提示用户,用户点击确定,程序再发一次命令;仍然失败就重启软件。这种做法偶尔能恢复通信,却无法证明机械位置、物料状态和安全条件已经恢复,反而可能覆盖最有价值的故障证据。
可靠的故障处理不是一个 catch 代码块,而是一条从检测、隔离、报警到恢复验证的闭环。本文讨论通用方法,不替代具体设备的风险评估、安全标准和操作规程;半导体设备异常恢复的领域实践见《半导体设备软件(六):实时性、并发与异常恢复》。
1. 事件、提示、报警和故障不要混用
系统中出现的每条消息并不都需要操作员处理:
- 事件(Event):值得记录的事实,例如连接建立、Recipe 激活、任务完成;
- 提示(Notification):需要了解但通常不要求立即行动的信息,例如维护周期临近;
- 报警(Alarm):需要人在规定时间内采取行动的异常条件;
- 故障(Fault):设备或软件无法满足预期能力的状态,可能触发报警和联锁;
- 日志(Log):供诊断使用的技术记录,数量通常远多于报警。
一次相机断连是故障;系统可以产生一条报警提醒操作员,并写入多条重连和驱动日志。若把每次重试都弹成报警,真正需要行动的信息会被报警洪泛淹没。
ISA-18.2 面向过程工业的报警管理,但其中的生命周期思想同样值得设备软件借鉴:报警需要经过识别、合理化、详细设计、运行监测和变更管理等阶段,而不是开发者看到异常就随手加一个红色弹窗。离散设备采用时仍应结合自身行业和风险边界。
2. 故障模型同时保存判断和证据
一条可操作的故障记录应包含稳定分类、来源、严重级别、时间和原始证据:
| |
注意"严重级别"和"可恢复性"其实是两个维度:Warning/Critical 描述影响程度,Recoverable 描述恢复方式。示例为保持简单混用在一个枚举里;生产代码中若两个维度都需要独立决策,应拆成两个属性分别建模。
Kind 应是软件长期维护的稳定分类,例如 CommunicationLost、InterlockOpen、PositionUnknown;VendorCode 保留厂商证据。面向操作员的消息说明“发生什么、影响什么、建议做什么”,技术堆栈和原始报文进入诊断记录,而不是全部塞进弹窗。
严重级别不应只根据异常类型决定。同一个读取超时,在非关键温度趋势采样中可能只是降级,在等待夹具到位的步骤中却可能使物料状态未知。
3. 先判断物理副作用,再决定重试
网络和 SDK 调用失败时,最重要的问题不是“能否再试一次”,而是第一次操作有没有发生:
| 结果 | 例子 | 处理重点 |
|---|---|---|
| 明确未执行 | 本地参数校验失败 | 修正输入后可以重新提交 |
| 明确已完成 | 控制器返回完成并通过回读确认 | 不应重复执行 |
| 执行中断 | 移动过程中驱动报警 | 先停止并确认位置 |
| 结果未知 | 命令发出后连接断开 | 先查询或进入人工确认,不能盲重试 |
读取状态通常比改变物理世界的命令更容易安全重试,但也要考虑设备和总线负载。写命令只有在协议提供幂等键、序列号或可查询结果时,才能可靠地去重。没有这些能力时,自动重试可能造成重复运动、重复出料或覆盖数据。
4. 恢复是一台独立状态机
不要在各层 catch 中零散地写复位命令。恢复流程本身应建模并保留检查点:
| |
“复位命令返回成功”只是 Correct 阶段的一步。只有 Verify 重新证明必要条件,状态机才可以从 Faulted 回到 Ready。确认报警也只是说明操作员已经看见,不应自动清除故障条件。
恢复步骤需要声明:
- 是否自动执行,还是必须授权人员确认;
- 可执行的设备状态和安全前提;
- 超时及失败后的终止状态;
- 是否幂等,重复进入会不会造成额外动作;
- 成功判据采用什么独立回读;
- 是否需要重新回零、重新校准或报废当前物料。
5. 安全动作必须有独立保证
应用层的异常处理无法替代安全功能。GC 暂停、线程阻塞、操作系统故障和进程崩溃都可能让上位机不能及时执行。涉及人身或设备危险的联锁、急停和能量切断,需要按风险评估放在具备相应安全完整性的硬件、安全 PLC、驱动器或回路中。
上位机的责任是:不绕过安全条件、准确显示安全链状态、在触发后停止业务流程、保存上下文,并引导受控复位。软件中的 try/finally 可以释放资源,却不能证明继电器已经断开或气缸已经回到安全位置。
6. 降级比“全好或全坏”更实用
并非所有故障都要求整机停机。诊断相机不可用时,可以禁用高级诊断但保留手动维护;非关键温度传感器失效时,可以降低速度并禁止自动生产;关键联锁失效则必须阻止危险动作。
降级模式必须显式定义:
- 哪些功能仍可使用;
- 性能或质量承诺如何变化;
- 操作员需要看到什么持续提示;
- 多久后必须升级为停机;
- 恢复到正常模式需要哪些验证。
不要在异常处理中临时“忽略一次”,这会形成未记录的隐式降级。
7. 抑制报警洪泛,但不抹掉事实
断开一根总线可能让十个从设备同时报错。如果每个轮询周期都创建新报警,操作员无法找到根因。可以采用:
- 相同来源和故障键合并为一条活动报警;
- 记录首次发生、最近发生和重复次数;
- 基于因果关系抑制下游派生报警;
- 对抖动信号设置经过工程确认的延时和死区;
- 恢复后保留历史,而不是删除记录;
- 定期统计报警频率、持续时间和洪泛区间。
抑制只改变呈现和通知,不应删除底层事件。关键报警的停用、阈值和优先级变更也应纳入审计和测试。
8. 用故障注入验证恢复路径
正常路径跑一百次,不能证明恢复路径可靠。模拟器和硬件在环(Hardware-in-the-Loop,HIL)环境应能够注入:
- 命令发送前、发送后和完成确认前断连;
- 状态长时间不变化;
- 迟到、重复或乱序响应;
- 传感器抖动和不合理组合;
- 磁盘写满、日志后端不可用;
- 进程在检查点前后终止。
验证的不只是“抛出了预期异常”,还包括设备最终状态、是否继续接受命令、证据是否完整、报警是否可操作,以及重启后是否拒绝从未知状态继续。
总结
可靠故障处理先区分事件、报警和故障,再根据物理副作用判断能否重试。恢复是一条带安全前提、检查点和成功判据的状态机;确认消息、清除报警和修复故障是不同动作。安全链负责最后保障,上位机负责不绕过它并保存足够证据。
下一篇将搭建从纯软件模拟器到 HIL 的测试梯度,说明如何模拟时间、失败和设备动态,而不是只让 Mock 永远返回成功。