工业一体机是集成了工业级主板、显示面板、触摸输入和I/O接口的一体化计算终端,专为工业自动化现场的宽温、抗振、防尘和7×24小时连续运行设计。在工业一体机上做OPC-UA通信,核心目标是把现场设备(PLC、传感器、CNC)的数据读上来,再往MES、SCADA或数据库送。**OPC-UA(OPC Unified Architecture,OPC统一架构)是由OPC基金会制定的跨平台工业通信标准,定义了客户端与服务器之间安全、可互操作的数据交换机制,通过地址空间模型把设备数据组织成可浏览的节点结构。**
相比Modbus这类老协议,OPC-UA的优势是原生跨平台、自带加密认证、支持信息模型建模,所以现在新建产线项目越来越多地指定走OPC-UA。这篇直接讲怎么在一台装了Linux/Windows的工业一体机上从零跑通:SDK选型、服务器搭建、节点读写、数据采集循环,附可直接运行的代码。
一、SDK选型:三种主流方案怎么选
Python生态里能用的OPC-UA库主要有三个路线,先对比再选:
| 对比维度 | python-opcua(opcua) | opcua-asyncio(asyncua) | open62541 |
| --- | --- | --- | --- |
| 开发语言 | Python | Python | C(提供Python绑定) |
| 并发模型 | 同步阻塞 | asyncio异步 | 事件循环/多线程 |
| 安装方式 | `pip install opcua` | `pip install asyncua` | 源码编译或系统包 |
| 维护状态 | 稳定、更新放缓 | 活跃、功能持续补充 | 工业级、功能最全 |
| 适用场景 | 中小规模数据采集 | 高并发客户端、网关服务 | 嵌入式、资源受限设备 |
选型建议:**项目简单、追求开箱即用选python-opcua;要做网关聚合多路数据、强调高吞吐选opcua-asyncio;设备侧资源紧张或有嵌入式需求选open62541。** 本文以python-opcua为例,它的API最直观,逻辑通了换其他库成本很低。
二、搭建一个测试服务器
先在工业一体机上装依赖:
```bash
pip install opcua
```
以下是服务端代码,模拟一台设备,暴露温度和报警两个节点,每秒更新一次温度:
```python
import time
from opcua import Server
server = Server()
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
server.set_server_name("IPC Data Server")
uri = "urn:ipc:demo:data"
idx = server.register_namespace(uri)
objects = server.get_objects_node()
device = objects.add_object(idx, "Device") # 设备对象
temp_var = device.add_variable(idx, "Temperature", 25.0)
temp_var.set_writable() # 允许客户端写入
alarm_var = device.add_variable(idx, "Alarm", False)
alarm_var.set_writable()
server.start()
try:
while True:
temp_var.set_value(temp_var.get_value() + 0.1)
time.sleep(1)
finally:
server.stop()
```
注意 `register_namespace` 返回的 `idx` 会分配给你注册的第一个命名空间(通常是1,0是标准保留命名空间),后面客户端寻址要用这个编号。
三、客户端读写节点
服务端跑起来后,客户端用 `get_root_node().get_child()` 沿路径找节点。路径格式是 `"名称空间索引:节点名"`:
```python
from opcua import Client
client = Client("opc.tcp://192.168.1.100:4840/freeopcua/server/")
client.connect()
try:
root = client.get_root_node()
device = root.get_child("0:Objects", "1:Device")
temp_node = device.get_child("1:Temperature")
alarm_node = device.get_child("1:Alarm")
print("当前温度:", temp_node.get_value())
alarm_node.set_value(True) # 远程置位报警
print("报警置位成功")
finally:
client.disconnect()
```
`0:Objects` 是标准地址空间里所有对象的挂载点,`1:Device` 就是服务端里 `add_object` 创建的那个对象,命名空间编号要和注册时一致。
四、数据采集循环(带断线重连)
现场工况下网络抖动是常态,采集程序必须扛得住断线。用外层循环做重连、内层循环做轮询:
```python
import time
from opcua import Client
SERVER_URL = "opc.tcp://192.168.1.100:4840/freeopcua/server/"
def collect(client):
"""读取设备全部关注节点,返回元组"""
device = client.get_root_node().get_child("0:Objects", "1:Device")
temp = device.get_child("1:Temperature").get_value()
alarm = device.get_child("1:Alarm").get_value()
return temp, alarm
while True:
client = Client(SERVER_URL)
try:
client.connect()
print("已连接OPC-UA服务器")
while True:
temp, alarm = collect(client)
print(f"{time.strftime('%H:%M:%S')} "
f"temperature={temp:.2f} alarm={alarm}")
time.sleep(5) # 轮询周期,按现场要求调整
except Exception as e:
print(f"连接异常: {e},5秒后重连")
time.sleep(5)
finally:
client.disconnect()
```
五、部署时的几个坑
-
**端口与防火墙**:默认TCP 4840,Windows防火墙和现场网闸都要放通,别只顾着改代码忘了改策略。
-
**安全策略**:python-opcua默认用None安全策略,明文传输。跨车间走以太网建议升级 `SecurityPolicy.Basic256Sha256_SignAndEncrypt` 并启用用户认证(证书路径按实际部署替换):
```python
from opcua import Client, ua
client = Client("opc.tcp://192.168.1.100:4840/freeopcua/server/")
client.set_security(
ua.SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
"certs/client_cert.der", # 客户端证书
"certs/client_key.pem", # 客户端私钥
)
client.set_user("opcuser")
client.set_password("opcpass")
client.connect()
```
-
**轮询还是订阅**:采集周期在1秒以上的用轮询就够了;周期短、点数多的场景用订阅(`create_subscription`)让服务器主动推送,省网络又省CPU。
-
**时区和时钟**:数据打时间戳统一用UTC或统一北京时间,不然多台设备数据入库后对不齐时序。
常见问题(FAQ)
**Q1:python-opcua和opcua-asyncio到底该选哪个?**
采集点数少、逻辑简单、只想尽快跑通,选python-opcua,同步API好调试;要做并发网关、同时对接多个服务器的,选opcua-asyncio,异步模型在高并发下资源占用更低。两者API风格接近,迁移成本可控。
**Q2:工业一体机上跑OPC-UA服务器,性能扛得住吗?**
一般完全够。OPC-UA服务器本身是轻量服务,一台ARM架构的工业一体机带几千个节点的地址空间、几十个并发客户端都没压力。瓶颈通常不在OPC-UA,而在你后面接的数据库写入和业务逻辑,注意把IO任务丢到独立线程或异步队列。
**Q3:OPC-UA比起Modbus TCP强在哪,为什么非要换?**
两点最实在:一是安全,Modbus TCP是明文而且没有认证机制,谁都能读写;二是建模能力,OPC-UA可以定义设备信息模型,把参数、状态、方法组织成结构化的对象,而不是一堆裸寄存器地址。但Modbus兼容性好、老设备支持全,OPC-UA网关通常还会保留Modbus下行接入的能力。