接入一台工业设备,演示版本通常很快:建立连接、读取寄存器、打印数值。

真正进入平台以后,链路会变成:

物理设备
-> 协议驱动
-> 数据解析
-> 设备身份映射
-> 标准模型
-> 本地缓存或时序库
-> MQTT/HTTP 转发
-> 告警与应用

任何一层语义不一致,问题都可能在最远的下游才出现。这篇按完整链路总结工业设备接入时需要处理的核心问题。

一、连接层:连接成功不等于可以通信

常见接入方式包括串口、TCP、Modbus、厂商私有协议、HTTP、SOAP 和 MQTT。连接层需要统一管理:

  • 建连与认证;
  • 读取、写入超时;
  • 心跳;
  • 断线重连;
  • 连接状态;
  • 优雅关闭。

重连要使用退避策略,避免设备断电后所有客户端同时高频重试:

1s -> 2s -> 4s -> 8s -> 30s

成功通信后再重置退避时间。连接对象还要有明确所有者,不能由多个 goroutine 在没有协调的情况下同时重连和关闭。

二、解析层:不要让原始协议泄漏到业务层

协议返回的是字节、寄存器或厂商字段,业务需要的是温度、压力、运行状态和告警。

解析层应完成:

  • 字节序处理;
  • 数据类型转换;
  • 缩放系数;
  • 单位标准化;
  • 位域解析;
  • CRC 或校验和;
  • 异常值识别。

例如一个寄存器值 253,可能表示 25.3℃。下游不应该再次猜测缩放规则,标准模型里应直接保存数值、单位和质量信息。

三、身份层:先回答“这是谁”

设备可能同时拥有配置编号、IP、序列号、厂商编号、数据库 ID 和 GUID。IP 会变,名称会重,数据库自增 ID 只在局部有意义。

稳定身份应该由平台统一下发或维护,并贯穿:

配置 -> 采集 -> 存储 -> 转发 -> 告警 -> 页面

共享设备还需要把“设备身份”和“连接关系”分开。一个一次设备可以同时被两台 PLC 观测,不能因为树结构方便,就把设备复制成两个身份。

四、时间层:数据是什么时候发生的

工业数据里至少有三个时间:

  • 设备产生时间;
  • 网关采集时间;
  • 平台接收时间。

只保存 created_at 会丢失重要信息。网络中断后补传的数据,如果使用接收时间,就会看起来像刚刚发生。

标准事件可以包含:

{
"deviceTime": "...",
"collectTime": "...",
"receiveTime": "..."
}

还要明确设备时钟是否可信、时区如何处理、时间解析失败时使用哪个备用值。

五、质量层:数值之外还要有可信度

采集值不只有“有”和“没有”。

GOOD          正常采集
STALE 超过预期周期未更新
BAD_FORMAT 协议解析失败
OUT_OF_RANGE 超出物理范围
DISCONNECTED 设备连接中断
SUBSTITUTED 使用补偿值

如果下游只收到一个 0,它无法判断设备真实测得零,还是采集失败后填了默认值。质量码能避免错误数据被当成真实业务事实。

六、模型层:统一共性,保留差异

完全按厂商定义模型,下游会面对几十套字段;强行把所有设备压进同一张表,又会产生大量无意义字段。

更实用的方式是分两层:

通用信封

device_guid
metric_code
value
unit
quality
collect_time
source

设备专属属性

通过模型配置描述指标名称、类型、地址、倍率和业务含义。

这样传输、存储和告警可以复用通用能力,协议驱动仍能保留设备差异。

七、转发层:离线时数据怎么办

现场网关到中心平台的网络并不稳定。转发模块要明确:

  • 断网是否缓存;
  • 缓存容量上限;
  • 恢复后按什么顺序补传;
  • 重复消息如何去重;
  • 实时数据与补传数据谁优先;
  • 磁盘写满如何降级。

不能无限缓存。更合理的是按业务价值区分:告警和事件优先保留,高频实时值可以按时间窗口压缩或丢弃。

八、告警层:规则依赖统一语义

告警规则需要明确输入数据、窗口、阈值、恢复条件和去重键。

alarm_key = device_guid + metric_code + rule_id

触发和恢复必须使用同一设备身份。否则规则引擎已产生告警,页面却无法把告警映射到对应设备。

九、运维层:接入完成以后才开始长期运行

一套可维护的设备接入应提供:

  • 当前连接状态;
  • 最近成功采集时间;
  • 连续失败次数;
  • 最近一次原始报文;
  • 配置版本;
  • 驱动版本;
  • 数据吞吐与错误率;
  • 远程诊断能力。

没有这些信息,现场问题只能依靠临时加日志和反复重启。

十、接入验收清单

  • [ ] 断开网线后能自动恢复;
  • [ ] 设备重启后不会产生重复身份;
  • [ ] 非法报文不会导致进程退出;
  • [ ] 时间、单位、倍率已经标准化;
  • [ ] 缺失值与真实零可以区分;
  • [ ] 上游离线时有明确缓存策略;
  • [ ] 同一消息重复到达不会重复产生告警;
  • [ ] 日志可以关联设备 GUID;
  • [ ] 配置错误能在启动阶段发现;
  • [ ] 服务停止时连接和 goroutine 能正常退出。

工业设备接入不是把协议翻译成 JSON。它是在不稳定的物理环境与相对稳定的软件平台之间,建立一份长期可维护的数据契约。