为什么需要 OPC UA
工厂里设备五花八门:西门子 S7 用 S7 协议、三菱 MC、Modbus TCP、Profinet、EtherNet/IP。每接一种设备你都要写一套驱动,做一个客户现场要写半年。OPC UA 干的事就是把这些差异封在底下,给上面一个统一的对象模型:你只要会读"温度"这个 NodeId,不管底下是哪台 PLC。
OPC UA 不是一个简单的协议,它是"工业语义模型"。除了传数据,它还告诉你这数据是什么意思、单位是什么、属于哪台设备。
这篇不讲理论,讲怎么把一条 S7-1200 的产线数据真正采上来、建模型、订阅、再转发到云平台。
典型采集架构
一条产线的标准采集链路:PLC / 仪表 → 现场总线 → 边缘网关(跑 OPC UA Server)→ 上位机或云(OPC UA Client)。网关那一层把各种私有协议翻译成 OPC UA,对外只暴露一个标准端口。
- open62541开源 C 栈,适合嵌入式网关。
- node-opcuaNode.js 写网关很顺手。
- Python asyncua原型脚本、快速调试用。
- Kepware / Matrikon商业 Server,驱动全。
如果你只是做 Client(去连别人的 Server),用 Python asyncua 几十行就能跑。
OPC UA 地址空间建模
OPC Server 对外暴露一棵 Node 树:Root → Objects → 设备 → 产线 → 工位 → 具体变量。每个 Node 有 NodeId(比如 ns=2;s=Line1.Press.Temperature)、DisplayName、Value、DataType、EngineeringUnits。
# open62541 风格伪代码,建一个温度变量
node = {
NodeId: "ns=2;s=Line1.Press.Temperature",
BrowseName: "Temperature",
DisplayName: "压力机1# 油温",
DataType: UA_Float,
Value: 45.2,
EngUnits: "°C"
}
server.add_node(node)
建模的关键是按"设备 → 工位 → 测点"分层,不要平铺几百个 NodeId 写在顶层。这样上位机一打开就能顺着树看现场。
从 PLC 读到数据
网关内部:一边用 S7 驱动读 PLC 寄存器,一边把值写到 OPC UA Node。下面是 Python asyncua Client 读一个 S7 标签的简化流程:
from asyncua import Client
import asyncio
async def main():
async with Client("opc.tcp://192.168.1.10:4840") as c:
node = c.get_node("ns=2;s=Line1.Press.Temperature")
while True:
val = await node.read_value()
print(f"温度 = {val:.1f} °C")
await asyncio.sleep(1)
asyncio.run(main())
实际项目里网关同时是 S7 Client(读 PLC)+ OPC UA Server(对外提供数据)。协议转换都在网关内部完成。
订阅、采样与事件
1 秒一次轮询太浪费带宽。OPC UA 提供 Subscription:Client 订阅一组 Node,Server 在值变化超过 Deadband 时主动 Push 给你。
# 订阅:采样间隔 500ms,死区 0.5°C
sub = await c.create_subscription(500, handler)
await sub.subscribe_data_change(node_temp)
- 采样间隔:底层从 PLC 读的频率,通常 200ms~1s。
- Publishing Interval:往 Client 推送的频率,通常 1s。
- Deadband:值变化多少才推一次,避免噪声刷屏。
往云平台转发
现场网关拿到数据后,通常再发一份到云端 MQTT Broker,由云端平台做存储和可视化。
- 北向OPC UA Server,给本地 SCADA / MES。
- 南向S7 / Modbus / Profinet 驱动。
- 东向MQTT 上行,发云端平台。
- 本地缓存网络断了写 SQLite,恢复后续传。
关键是"断网续传":现场网络不稳,网关必须本地缓存,不能丢数据。
调试与常见坑
调试 OPC UA 最好用的工具是 UaExpert(官方免费):连 Server、浏览 Node、订阅变量、看历史。
// 常见症状
// 1. 连不上:先 ping,再看 4840 端口,证书要信任
// 2. 读出来是 NaN:DataType 不匹配,S7 的 Real 对应 UA_Float
// 3. 订阅没数据:Deadband 设太大,或 Node 没开 EventNotifier
// 4. 时间戳乱:Server 时钟没 NTP 同步
OPC UA 入门比看起来难,难的不是协议本身,是"怎么把现场信号抽象成有语义的 Node"。建模做对了,上面 MES、数字孪生、数据分析全都省事。
跑通一个从 S7 到 MQTT 的完整链路,下一个产线就是复制模板。