4. OPC UA 服务器数据订阅
任务目标
本案例将实现一个最小可运行的 OPC UA 客户端,连接本地 OPC UA 服务器,订阅服务器上某个节点的数据变化,并实时打印最新值。通过本案例,掌握 OPC UA 订阅机制的核心调用流程。
环境与依赖
使用 Python 与 asyncua 库(基于 asyncio)。安装依赖:
pip install asyncua
需要本地有一个可访问的 OPC UA 服务器。若没有现成服务器,可使用 asyncua 自带的示例服务器(见下文验证步骤)。
关键完整代码
import asyncio
import logging
from asyncua import Client
logging.basicConfig(level=logging.INFO)
# OPC UA 服务器地址(根据实际服务器修改)
SERVER_URL = "opc.tcp://localhost:4840"
# 要订阅的节点 ID(示例:ns=2;i=1 为服务器模拟量节点)
NODE_ID = "ns=2;i=1"
async def subscribe_data():
client = Client(SERVER_URL)
try:
await client.connect()
logging.info("已连接服务器: %s", SERVER_URL)
# 获取目标节点
node = client.get_node(NODE_ID)
# 创建订阅(周期 1000ms)
subscription = await client.create_subscription(1000, SubHandler())
await subscription.subscribe_data_change(node)
logging.info("已订阅节点: %s", NODE_ID)
# 持续运行,等待数据变化回调
while True:
await asyncio.sleep(1)
finally:
await client.disconnect()
class SubHandler:
"""订阅数据变化回调处理类"""
def datachange_notification(self, node, val, data):
logging.info("节点 %s 新值: %s", node, val)
def event_notification(self, event):
logging.info("事件通知: %s", event)
if __name__ == "__main__":
asyncio.run(subscribe_data())
运行与验证
第一步:启动 OPC UA 服务器(若已有服务器可跳过)。在另一个终端运行:
python -m asyncua.server
该命令会启动一个默认服务器,监听 opc.tcp://localhost:4840,并包含一个模拟量节点 ns=2;i=1,其值会周期性变化。
第二步:运行订阅客户端
python opcua_subscriber.py
验证通过条件:
- 客户端日志显示
已连接服务器与已订阅节点,无报错。 - 持续输出类似
节点 NodeId(...) 新值: 42.5的日志,且数值随时间变化,说明订阅生效并实时接收数据。
常见问题
- 连接失败:确认服务器已启动,且
SERVER_URL与服务器实际地址一致。 - 节点不存在:若使用自定义服务器,需将
NODE_ID改为实际存在的节点 ID。可通过asyncua的浏览功能查询节点。 - 收不到数据变化:确认所订阅节点确实在周期性变化;若节点值不变,订阅不会触发回调。