上位机报警界面的核心挑战在于:PLC、机器人、相机三类设备的通信机制完全不同,报警的“发生—确认—消失”状态流转逻辑复杂,且必须在 UI 层做线程安全的汇聚展示
上位机报警界面的核心挑战在于:PLC、机器人、相机三类设备的通信机制完全不同,报警的“发生—确认—消失”状态流转逻辑复杂,且必须在 UI 层做线程安全的汇聚展示。这里从架构到三类设备的具体对接方式逐层拆解。
🏗️ 整体架构:报警汇聚层是核心
报警界面不能让每个设备的回调线程直接去更新 UI,也不能把报警判定逻辑塞在通信循环里。推荐的结构是六层工作域 + 事件总线:
┌─────────────────────────────────────────────────────┐
│ UI 线程(仅显示与交互,不阻塞、不计算) │
├─────────────────────────────────────────────────────┤
│ 报警汇聚层(Alarm Hub) │
│ - 订阅三类设备的报警事件 │
│ - 统一报警编号、级别、时间戳 │
│ - 维护报警状态机(Raised → Acked → Cleared) │
│ - 节流:同一条报警 5 秒内不重复弹窗 │
├─────────────────────────────────────────────────────┤
│ 事件总线(EventBus) │
│ - 所有线程通过 Channel<T> 或 BlockingCollection 通信 │
├──────────────┬──────────────┬───────────────────────┤
│ PLC 通信线程 │ 机器人线程 │ 相机回调线程 │
│ (S7/Modbus)│ (PC SDK/ │ (Basler/海康 SDK) │
│ │ TCP 直连) │ │
└──────────────┴──────────────┴───────────────────────┘
关键原则:相机 SDK 的回调线程“什么都别干,除了入队”。PLC 通信线程只负责周期读写数据镜像,报警判定放在独立的报警循环里读镜像。这样任何一路设备卡死或断线,都不会让报警界面失去响应。
🤖 三类设备的报警获取方式(完全不同)
PLC:读数据镜像,自己判定报警
PLC 报警有两种模式:PLC 内部判定(PLC 程序比较阈值,置位一个 BOOL 变量)和上位机判定(上位机读模拟量,自己比较)。推荐优先用 PLC 判定,因为 PLC 的扫描周期确定,判定时机精确。
上位机侧的做法:通信线程周期性读取报警位到 ProcessImage 对象中,报警循环每个周期检查镜像里的报警位,检测上升沿(从 0 变 1)时触发报警事件。
机器人:通过组输出信号映射故障码
这是三类设备中最需要协议设计的。ABB 机器人的典型做法是:在机器人控制器中配置系统输出或错误处理程序,将故障码写入一个组输出信号,PLC 读取该组信号后传递给上位机。
具体流程:
- 整理一份故障码清单(
Errnum→ 文本描述),例如119136: Robot not on path。 - 在机器人错误处理程序中执行
SetGO goMyErrorGroup, ERRNO,把故障码写入组输出。 - PLC 读取该组输入,上位机从 PLC 数据镜像中获取故障码,查表得到报警文本。
优先使用系统输出(如 ExecutionError、MotorsOn),因为系统输出不依赖 RAPID 程序是否在执行,更可靠。用户自定义的 TPWrite 消息则需要确认是否已写入事件日志,并非所有消息都会自动进入 EVENTS。
相机:回调线程只做“入队 + 标记”
相机的报警来源有两种:SDK 内部的错误回调(相机掉线、触发超时、采集失败)和算法判定的 OK/NG 结果。无论哪种,回调线程的处理逻辑都是:复制数据 + 写入一个带时间戳的报警记录 + 丢进队列,然后立即返回。
相机掉线自动重连是必备功能。开一个后台线程定时发心跳,连续 3 次无响应就判定掉线,标记工位状态为异常并通知 MES 或上位机报警层,不要静默重连导致产线“盲跑”。
🔄 报警状态机:比“弹窗”重要得多
一条报警的完整生命周期不是“发生 → 弹窗 → 关掉”这么简单。标准的工业报警状态流转是:
正常 → 报警发生(Raised) → 操作员确认(Acknowledged) → 报警消失(Cleared) → 归档
中间的“已确认但未消失”(Acked but not Cleared)状态是最重要的:操作员按了确认按钮,声音停了,弹窗不再闪烁,但报警仍然处于激活状态(设备的实际故障还没排除)。这时报警记录不能从界面上消失,必须以“已确认”的视觉状态保留。
数据库设计要存事件流,不是只存“当前状态”。每条记录包含:报警名、级别、发生时间、确认时间、确认人、消失时间。这样才能回答“这条报警是谁什么时候处理的”。
🎛️ 用 HslControls 做报警界面呈现
报警界面的视觉层可以结合 HslControls 的控件来增强表达:
- 信号灯控件:每个报警位对应一盏灯,颜色编码(灰=正常,黄=未确认,红=已确认但未消失,绿=消失归档)。HslControls 的信号灯支持渐变和闪烁效果,比标准 PictureBox 更直观。
- 数码管控件:显示“当前活动报警数”“未确认报警数”等统计值。
- 实时曲线:如果报警与温度、压力等模拟量关联,在报警发生时用辅助线标记阈值线,操作员能立即看到触发报警的数据点位置。
弹窗节流是必须的:同一条报警在 5 秒内不重复弹窗。如果 PLC 的报警位因为通信抖动而快速跳变,没有节流的话弹窗会刷屏。做法是在报警汇聚层维护一个 Dictionary<string, DateTime> _lastPopupTime,触发弹窗前检查距上次弹出是否超过节流窗口。
🔍 调试重点:状态转换的边界
报警界面的调试核心在状态机边界,用条件断点验证:
- “未确认就消失”:报警从
Raised直接跳到Cleared,没有经过Acknowledged。状态记录应该标记为RaisedCleared,而不是错误地记录为RaisedAcknowledgedCleared。 - “重复报警”:同一个报警位在 1 秒内跳变多次(通信抖动导致),验证去抖逻辑是否生效。
- “确认权限”:如果报警复位需要权限(如工程师级),在确认逻辑处设断点,验证低权限用户的操作被正确拦截。
💡 核心思维提炼
1. 报警不是“消息”,是“状态机”
PLC 编程里用 R_TRIG 检测上升沿触发报警,C# 里的报警汇聚层必须实现同样的边沿检测逻辑。不要每次读到的报警位是 1 就触发一次,那会重复报警。
2. 三类设备的通信差异要用“事件总线”抹平
相机回调线程是 SDK 的非托管线程,机器人可能通过组输出信号,PLC 是周期读写。事件总线让报警汇聚层不需要关心报警来自哪里,只处理“一条报警发生了”这个事实。
3. UI 只做最后一件事:渲染
报警汇聚层完成所有判定、去抖、状态流转,然后把一个已经确定状态的报警对象推送到 UI。UI 收到后只负责:弹窗、变色、写入 ListBox。不要在 UI 事件里做任何等待、查询、判断。
4. 相机报警最容易出“静默故障”
PLC 断线你会看到通信超时,机器人报错你会看到故障码。但相机可能静默掉线——没有回调、没有异常,只是不再产生图像。必须用心跳机制主动检测,不能依赖 SDK 的错误回调。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)