第四章:数据采集协议与接入

各位工程师朋友,今天我们来聊聊数据采集协议。说实话,这是整个AALC系统最底层的功夫。协议选不对,后面全是白搭。我见过太多项目,硬件装好了,软件写完了,结果数据上不来——问题就出在协议理解不透彻。

这一章,我会把Modbus RTU/TCP、OPC UA、MQTT这三个主流协议掰开揉碎了讲。还会聊聊数据解析和格式统一的问题。嗯,都是实战中踩过的坑,希望能帮你少走弯路。

核心观点:没有最好的协议,只有最合适的协议。选型要看场景、看设备、看网络环境。

4.1 Modbus RTU/TCP:工业现场的老黄牛

Modbus,1979年诞生的协议。你想想看,比我都大。但它至今还在大量使用,为什么?简单、可靠、成本低。我在一个老旧的水泥厂改造项目中,现场全是Modbus RTU设备,RS485总线拉了上千米,照样跑得稳稳的。

4.1.1 Modbus RTU(串行通信)

RTU模式走的是RS232或RS485物理层。我个人习惯用RS485,抗干扰能力强,传输距离远。波特率一般设9600或19200,别贪快,稳定第一。

数据帧结构是这样的:

地址码(1字节) + 功能码(1字节) + 数据区(N字节) + CRC校验(2字节)

举个例子,读取保持寄存器的指令:

发送:01 03 00 00 00 02 C4 0B
解释:地址01,功能码03(读保持寄存器),起始地址0000,读取2个寄存器,CRC校验C40B

我的经验:CRC校验一定要做对。我曾经因为CRC计算错误,排查了整整两天。后来发现是高低字节顺序搞反了。Modbus RTU的CRC是低字节在前,高字节在后,别记错了。

4.1.2 Modbus TCP(以太网通信)

Modbus TCP就是把RTU的报文封装在TCP/IP包里。去掉了CRC校验(TCP本身有校验),加了个MBAP头(7字节)。

结构对比:

协议 物理层 最大节点数 传输距离 典型场景
Modbus RTU RS485/RS232 32(无中继) 1200米 传感器、PLC、仪表
Modbus TCP 以太网 无限制 100米(交换机级联可扩展) 上位机与PLC通信

避坑指南:我曾经在一个项目中,RTU和TCP混用,结果地址映射搞乱了。建议:同一系统尽量统一协议。如果必须混用,一定要做好地址映射表,文档写清楚。

4.2 OPC UA:跨平台的工业通信标准

OPC UA,说白了就是工业界的"通用翻译器"。不同厂商的设备,语言不通怎么办?OPC UA来当中间人。我参与过一个汽车焊装线项目,西门子PLC、罗克韦尔变频器、库卡机器人,全靠OPC UA统一接入。

OPC UA的核心优势:

  • 平台无关:Windows、Linux、嵌入式都能跑
  • 安全机制:支持加密、签名、认证
  • 信息模型:不只是传数据,还能传数据结构
  • 历史数据:内置历史数据访问功能

连接示例(Python + opcua库):

from opcua import Client

client = Client("opc.tcp://192.168.1.100:4840")
client.connect()

# 读取变量
temp = client.get_node("ns=2;i=1001")
value = temp.get_value()
print(f"当前温度:{value}°C")

client.disconnect()

我的建议:OPC UA的节点ID(NodeId)一定要提前规划好。我见过一个项目,节点ID乱得像蜘蛛网,后期维护简直是噩梦。建议用命名空间+数字ID的方式,清晰明了。

4.3 MQTT:物联网时代的轻量级协议

MQTT,发布/订阅模式。你想想看,就像微信群聊——有人发消息(发布者),有人收消息(订阅者),中间有个服务器(Broker)转发。非常适合设备多、网络不稳定的场景。

为什么选MQTT?

  • 轻量级:最小报文只有2字节
  • QoS机制:三种服务质量等级,按需选择
  • 遗嘱消息:设备掉线自动通知
  • 保留消息:新设备上线就能拿到最新数据

QoS等级对比:

QoS等级 含义 可靠性 适用场景
0 最多发一次 传感器数据(可丢失)
1 至少发一次 状态上报(可重复)
2 恰好发一次 控制指令(不能丢不能重)

发布示例(Python + paho-mqtt):

import paho.mqtt.client as mqtt

client = mqtt.Client()
client.connect("broker.emqx.io", 1883, 60)

# 发布温度数据,QoS=1
client.publish("factory/temperature", "25.6", qos=1)

# 订阅所有传感器数据
def on_message(client, userdata, msg):
    print(f"主题:{msg.topic},数据:{msg.payload}")

client.on_message = on_message
client.subscribe("factory/#")
client.loop_forever()

避坑指南:我曾经在生产环境中用过QoS 2,结果Broker负载飙升,消息堆积严重。后来发现,大部分场景QoS 1就够了。QoS 2只在控制指令等关键场景使用。别滥用。

4.4 数据解析与格式统一

协议搞定了,数据上来了,但格式五花八门怎么办?有的设备发JSON,有的发二进制,有的发自定义格式。这时候就需要做数据解析和格式统一。

4.4.1 JSON格式

JSON,人类可读,调试方便。我建议在边缘网关层统一转成JSON,方便上层应用处理。

标准格式示例:

{
  "device_id": "sensor_001",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "temperature": 25.6,
    "humidity": 68.2,
    "pressure": 1013.25
  },
  "quality": "good"
}

4.4.2 Protobuf格式

Protobuf,二进制格式,体积小、解析快。适合带宽有限或数据量大的场景。我在一个风电项目中,上千个传感器数据,用JSON传带宽不够,换成Protobuf后,数据量减少了70%。

定义文件示例:

syntax = "proto3";

message SensorData {
  string device_id = 1;
  int64 timestamp = 2;
  float temperature = 3;
  float humidity = 4;
  float pressure = 5;
  string quality = 6;
}

4.4.3 格式统一策略

我个人习惯的做法:

  1. 边缘层统一:在网关或边缘设备上,把各种协议数据转成统一格式
  2. JSON用于调试:开发阶段用JSON,方便查看
  3. Protobuf用于生产:正式部署用Protobuf,节省带宽
  4. 时间戳标准化:统一用Unix时间戳或ISO 8601格式
  5. 质量标签:每个数据点加quality字段,标记数据可信度

我的经验:格式统一这件事,越早做越好。我见过一个项目,数据格式混乱,后期写了几百行转换代码,还经常出bug。一开始就定好规范,能省很多事。

4.5 本章知识体系

下面这张图,是我梳理的本章知识结构。你可以看到,从底层协议到上层数据格式,是一条完整的数据链路。

数据采集协议与接入知识体系 物理层与通信方式 核心协议 Modbus RTU/TCP OPC UA MQTT 数据解析与格式统一 数据格式:JSON / Protobuf 从物理层到数据格式,构建完整的数据采集链路

这张图展示了从物理层到数据格式的完整链路。你想想看,每个环节都环环相扣。物理层选错了,协议层再牛也白搭。协议层选对了,数据解析才能顺畅。

好了,这一章的内容就到这里。协议选型、数据解析、格式统一,这三件事做好了,你的AALC系统就成功了一半。剩下的,就是把这些知识用到实际项目中去。