OPC UA 故障处理案例
案例一:证书验证失败,连接被拒绝
故障现象
客户端连接 OPC UA 服务器时报错:BadCertificateUntrusted,无法建立安全连接。
排查过程
python
# 错误日志
# asyncua.ua.uaerrors._auto.BadCertificateUntrusted
# 原因:服务器未信任客户端证书
# OPC UA 使用双向证书认证,服务器需要显式信任客户端证书解决方案
bash
# 1. 将客户端证书复制到服务器的信任列表
cp client_cert.pem /etc/opcua/server/pki/trusted/certs/
# 2. 或在服务器代码中自动信任(仅测试环境)
server.set_security_IDs(["Anonymous", "Basic256Sha256"])
# 3. 生产环境:使用 CA 签发的证书,服务器信任 CA
# 将 CA 证书添加到服务器信任的 CA 列表
cp ca_cert.pem /etc/opcua/server/pki/trusted/issuers/案例二:订阅数据延迟高
故障现象
OPC UA 订阅的数据更新延迟达到 5-10 秒,而配置的发布间隔为 1 秒。
排查过程
python
# 检查订阅状态
subscription_status = await client.get_subscription_status(sub_id)
print(f"Publishing interval: {subscription_status.RevisedPublishingInterval}")
print(f"Lifetime count: {subscription_status.RevisedLifetimeCount}")
print(f"Max keepalive: {subscription_status.RevisedMaxKeepAliveCount}")
# 发现 RevisedPublishingInterval = 5000ms
# 服务器将 1000ms 修订为 5000ms(服务器最小间隔限制)
# 检查服务器配置
server_caps = await client.get_server_capabilities()
print(f"Min publishing interval: {server_caps.MinSupportedSampleRate}")解决方案
python
# 服务器端:降低最小发布间隔
server.iserver.aspace.set_attribute_value(
ua.NodeId(ua.ObjectIds.Server_ServerCapabilities_MinSupportedSampleRate),
ua.DataValue(ua.Variant(100.0, ua.VariantType.Double)) # 100ms
)
# 客户端:检查修订后的实际间隔
sub = await client.create_subscription(period=1000, handler=handler)
print(f"Requested: 1000ms, Revised: {sub.parameters.RevisedPublishingInterval}ms")案例三:大量节点读取超时
故障现象
读取 5000 个节点时,请求超时,服务器返回 BadTimeout。
解决方案
python
# 分批读取,每批不超过 500 个节点
async def read_nodes_in_batches(client, node_ids, batch_size=500):
all_values = []
for i in range(0, len(node_ids), batch_size):
batch = node_ids[i:i+batch_size]
nodes = [client.get_node(nid) for nid in batch]
values = await client.read_values(nodes)
all_values.extend(values)
await asyncio.sleep(0.1) # 避免服务器过载
return all_values常见错误码
| 错误码 | 含义 | 处理方法 |
|---|---|---|
| BadNodeIdUnknown | 节点 ID 不存在 | 检查节点 ID 是否正确 |
| BadAttributeIdInvalid | 属性不支持 | 检查节点类型和属性 |
| BadNotReadable | 节点不可读 | 检查访问权限 |
| BadNotWritable | 节点不可写 | 检查节点 Writable 属性 |
| BadUserAccessDenied | 用户无权限 | 检查用户角色配置 |
| BadCertificateUntrusted | 证书不受信任 | 添加证书到信任列表 |
| BadSecureChannelClosed | 安全通道关闭 | 重新连接 |
| BadSessionClosed | 会话已关闭 | 重新建立会话 |
| BadTooManySubscriptions | 订阅数超限 | 减少订阅数或增加服务器限制 |
| BadTimeout | 请求超时 | 增大超时时间或减小批次大小 |
调试工具
bash
# 使用 UaExpert 连接并浏览地址空间
# 1. 下载 UaExpert(免费)
# 2. 添加服务器:opc.tcp://server:4840
# 3. 浏览节点树,查看值和属性
# 命令行测试
python3 -c "
import asyncio
from asyncua import Client
async def test():
async with Client('opc.tcp://server:4840') as client:
root = client.get_root_node()
print('Root node:', root)
children = await root.get_children()
for child in children:
print(' -', await child.read_browse_name())
asyncio.run(test())
"