4. 报警消息的实时生成与推送
报警从“被检测到”到“被人看到”,中间要经过一条完整的消息链路:报警源产生事件、系统组装成标准消息、进入队列、按订阅关系分发、经协议映射落到具体通道,最后由 HMI、短信、邮件或声光设备呈现。这条链路上任何一环设计不当,都会造成漏报、重复报或延迟超标。本节围绕消息结构、队列与发布订阅、协议映射、推送通道和延迟控制五个方面展开。
一、报警消息的标准化结构
报警消息必须结构化,否则下游无法路由、无法去重、无法统计。一条典型的报警消息至少包含六个字段:消息ID、发生时间、设备标识、报警代码、描述文本、报警等级。工程上还会附加状态(激活/确认/清除)、来源协议、区域、建议处置等扩展字段。
其中时间字段最容易出问题。建议统一使用带时区的 UTC 时间戳(如 ISO 8601 格式 2025-03-11T08:15:32.480Z),由采集端打时间戳,而不是由推送端补时间,否则队列积压时时间会整体偏移。消息ID建议采用“设备ID+代码+发生时间”的确定性组合或全局递增序列,前者便于去重,后者便于排序。报警等级可按四级划分:紧急(需立即停机处置)、重要(影响质量或节拍)、一般(需关注)、提示(仅记录)。等级直接决定推送通道和延迟预算,是后续路由的核心依据。
{
"msgId": "L3-PRESS-0217-20250311T081532480Z",
"ts": "2025-03-11T08:15:32.480Z",
"device": "PR-03 液压冲压机",
"code": "E0217",
"desc": "液压油温超上限",
"level": "重要",
"state": "激活",
"source": "OPC-UA"
}
二、消息队列与发布订阅
报警产生速率具有明显的突发性:平时每分钟几条,故障连锁时可能每秒上百条。若采集端直接调用推送接口,接口阻塞会反压到采集线程,导致更多报警丢失。因此中间必须引入消息队列做削峰和解耦。常用选择包括 MQTT(轻量、适合边缘)、Kafka(高吞吐、可回溯)、RabbitMQ(路由灵活)。
队列之上采用发布订阅模型:报警服务作为发布者,把消息发布到按主题划分的通道,例如 alarm/line1/press/important;HMI 网关、短信服务、邮件服务、声光控制器各自作为订阅者,按主题通配符订阅自己关心的消息。这样新增一个推送通道时,只需增加订阅者,不必改动报警源,扩展性最好。订阅端还应实现幂等消费:以 msgId 为键做短期去重缓存,防止网络重投造成重复弹窗或重复短信。
三、OPC UA 与 Modbus 的报警映射
不同协议带来的报警语义不同,映射时要保留原始语义。OPC UA 本身有成熟的报警与条件模型(AlarmCondition),事件通过订阅(Subscription)以 MonitoredItem 方式上报,带有 EventId、Severity、SourceName、Time 等字段,可直接映射到标准消息的 ID、等级、设备和时间,Severity 通常为 1~1000,可按阈值折算为四级。
Modbus 没有报警语义,只有寄存器。工程上通常约定:某保持寄存器或线圈的某一位为 1 表示报警激活,配合一张“寄存器地址—报警代码—描述—等级”的映射表完成翻译。例如 40001 的第 3 位对应 E0217 油温超限。由于 Modbus 是轮询式,采集周期直接决定报警发现延迟,周期设为 200 ms 时,最坏发现延迟约 200 ms,这是延迟预算中不可忽略的一项。映射表应作为配置资产统一维护,避免代码里硬编码地址。
四、推送通道与实时性要求
不同通道的定位不同,延迟预算也不同。HMI 弹窗是操作工的第一感知手段,要求从报警发生到画面刷新不超过 1 秒;声光报警器用于现场强提醒,要求 500 毫秒内动作;短信面向班组长和值班工程师,10 秒内送达即可;邮件用于归档和日报,60 秒内可接受。紧急等级应同时触发 HMI、声光和短信,重要等级触发 HMI 与声光,一般和提示等级只进 HMI 与事件库。
延迟控制要从链路上逐段核算。以 Modbus 油温报警为例:轮询周期 200 ms(最坏发现延迟 200 ms)+ 映射与组装约 10 ms + 队列排队(正常小于 50 ms,突发时可能到数百毫秒)+ 分发与推送 100 ms,合计正常约 360 ms,满足 HMI 1 秒预算。若队列积压导致排队超过 500 ms,就应触发队列深度告警,并考虑提高消费者并发或对低等级消息降级批量处理。此外,短信网关和邮件服务器属于外部依赖,必须设置超时与失败重试上限,避免一个慢通道拖垮整个分发线程;实践中常把外部通道放入独立线程池或独立消费者组,与 HMI 推送隔离。
五、一个可执行的推送策略配置示例
把上述规则固化为配置,是保证一致性的有效做法。下面是一份按等级路由的策略片段,可作为实际配置的参考骨架:
routes:
- level: 紧急
channels: [hmi, sound_light, sms]
max_delay_ms: 500
repeat_until_ack: true
- level: 重要
channels: [hmi, sound_light]
max_delay_ms: 1000
- level: 一般
channels: [hmi]
max_delay_ms: 2000
- level: 提示
channels: [hmi, event_log]
max_delay_ms: 5000
dedup:
key: msgId
window_s: 30
queue:
depth_alert: 500
consumer_concurrency: 4
上线后应做一次端到端验证:人为短接或模拟一个 Modbus 报警位,用抓包或日志时间戳比对“报警置位时刻”与“HMI 弹窗时刻”,确认差值落在预算内;再连续触发 200 条报警,观察队列深度是否超过告警阈值、是否有消息因去重窗口设置不当被误吞。只有这条链路在正常与突发两种工况下都可观测、可判断,报警推送才算真正落地。