You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OPC UA服务器连接断开后二次迭代取值报BadAttributeIdInvalid错误求助

OPC UA二次循环获取节点值报错BadAttributeIdInvalid的排查与解决

可能的原因

  • 首次循环后节点对象失效:连接断开或重新初始化后,之前获取的Node对象已无法复用,二次请求时触发属性不支持错误。
  • 属性ID传递错误:部分客户端库在循环中可能默认请求了节点不支持的属性,而非Value属性。
  • 连接状态管理混乱:循环中未正确维护连接状态,断开后未重新建立连接或重新获取节点。

解决方案

1. 每次循环重新获取节点对象

不要复用首次循环的Node实例,每次轮询前重新通过节点路径获取节点:

from opcua import Client
import time

# 配置PLC端点和节点路径
plc_endpoints = ["opc.tcp://phoenix_plc:4840", "opc.tcp://bachmann_plc:4840"]
target_node_paths = ["ns=2;s=DataPoint1", "ns=2;s=DataPoint2"]

while True:
    for endpoint in plc_endpoints:
        try:
            # 每次循环重新创建客户端并连接
            client = Client(endpoint)
            client.connect()
            # 重新获取节点
            target_nodes = [client.get_node(path) for path in target_node_paths]
            # 获取节点值
            node_values = client.get_values(target_nodes)
            print(f"{endpoint} 数据: {node_values}")
            client.disconnect()
        except Exception as e:
            print(f"{endpoint} 操作失败: {str(e)}")
    time.sleep(10)

2. 显式指定请求Value属性

如果客户端库默认请求的属性不是Value,显式指定属性ID:

from opcua.ua import AttributeIds

# 获取值时明确指定属性为Value
node_values = client.get_values(target_nodes, attribute_id=AttributeIds.Value)

3. 维护持久连接(避免频繁重连)

如果频繁重连引发问题,可保持连接长期打开,循环内仅执行数据获取:

from opcua import Client
import time

plc_endpoints = ["opc.tcp://phoenix_plc:4840", "opc.tcp://bachmann_plc:4840"]
target_node_paths = ["ns=2;s=DataPoint1", "ns=2;s=DataPoint2"]
active_clients = []

# 初始化所有连接
for endpoint in plc_endpoints:
    try:
        client = Client(endpoint)
        client.connect()
        active_clients.append((client, endpoint))
        print(f"已连接 {endpoint}")
    except Exception as e:
        print(f"初始化 {endpoint} 失败: {str(e)}")

try:
    while True:
        for client, endpoint in active_clients:
            try:
                # 检查连接状态,断开则重连
                if not client.is_connected():
                    client.reconnect()
                    print(f"重新连接 {endpoint}")
                # 重新获取节点(避免节点对象失效)
                target_nodes = [client.get_node(path) for path in target_node_paths]
                node_values = client.get_values(target_nodes)
                print(f"{endpoint} 数据: {node_values}")
            except Exception as e:
                print(f"{endpoint} 获取数据失败: {str(e)}")
        time.sleep(10)
finally:
    # 程序退出时统一断开所有连接
    for client, _ in active_clients:
        if client.is_connected():
            client.disconnect()
            print("已断开连接")

4. 提前验证节点属性支持性

首次获取节点时,检查是否支持Value属性,排除节点本身问题:

from opcua.ua import AttributeIds

node = client.get_node(target_node_paths[0])
# 请求Value属性
attr_result = node.get_attributes([AttributeIds.Value])[0]
if attr_result.StatusCode.is_good():
    print("节点支持Value属性")
else:
    print(f"节点不支持Value属性: {attr_result.StatusCode}")

内容的提问来源于stack exchange,提问作者amanie11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:28:08