Python OPC-UA服务器创建ST_NameValue结构体数组变量遇阻求助
解决OPC-UA服务器创建结构体数组变量及客户端写入问题
1. 先正确注册自定义结构体类型
OPC-UA中自定义结构体必须先在服务器地址空间完成类型注册,否则无法创建对应类型的变量。以下是ST_NameValue结构体的注册示例:
from opcua import Server, ua server = Server() server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") uri = "http://your-company.com/opcua" idx = server.register_namespace(uri) # 创建ST_NameValue结构体类型 st_name_value_type = server.nodes.base_object_type.add_object_type(idx, "ST_NameValue") # 添加结构体字段:Name(String类型)、Value(这里用Double示例,可替换为你需要的类型) st_name_value_type.add_variable(idx, "Name", "", ua.VariantType.String).set_modelling_rule(True) st_name_value_type.add_variable(idx, "Value", 0, ua.VariantType.Double).set_modelling_rule(True) # 创建结构体数组类型 struct_type_node = server.get_node(f"ns={idx};i={st_name_value_type.nodeid.Identifier}") array_type_node = server.nodes.base_data_type.add_array_type(struct_type_node, idx, "ArrayOfST_NameValue")
2. 创建astParam变量节点(解决AttributeError)
AttributeError多因未正确指定变量DataType或类型未注册导致。创建数组变量时需明确指定ValueRank和ArrayDimensions参数:
# 获取父节点(以Objects节点为例) objects = server.get_objects_node() # 创建astParam变量 ast_param = objects.add_variable( idx, "astParam", [], # 初始空数组,后续可填充默认值 datatype=array_type_node.nodeid, # 必须传入数组类型的NodeId对象 valuerank=ua.ValueRank.OneDimension, # 声明为一维数组 arraydimensions=[20] # 指定数组长度为20 ) # 设置变量可读写 ast_param.set_writable()
常见AttributeError修复点:
- 避免用字符串指定
datatype:必须传入NodeId对象,而非字符串类型的类型名 - 确保结构体类型已注册:检查
ST_NameValue类型已成功添加到地址空间,可通过server.get_node验证 - 核对方法调用:比如误将
add_variable写成add_object,会导致属性不匹配
3. 客户端写入结构体数组的正确方式
客户端需先获取服务器的结构体类型定义,构造匹配的结构体实例数组,不能直接用普通字典或其他类型填充:
from opcua import Client client = Client("opc.tcp://localhost:4840/freeopcua/server/") client.connect() try: # 获取结构体类型节点和astParam变量节点 st_name_value_type = client.get_node(f"ns={idx};i={st_name_value_type.nodeid.Identifier}") ast_param_node = client.get_node(f"ns={idx};s=astParam") # 构造20个ST_NameValue实例 struct_array = [] for i in range(20): # 创建结构体实例 struct_instance = client.get_node(st_name_value_type).call_method("0:CreateInstance") struct_instance.get_child(f"ns={idx};s=Name").set_value(f"Param_{i}") struct_instance.get_child(f"ns={idx};s=Value").set_value(i * 1.0) struct_array.append(struct_instance.get_value()) # 写入数组到astParam ast_param_node.set_value(ua.Variant(struct_array, array_type_node.nodeid)) finally: client.disconnect()
客户端写入报错常见原因:
- 数据类型不匹配:客户端构造的数组元素不是服务器定义的
ST_NameValue实例,而是普通字典或其他类型 - 数组长度不匹配:写入的数组长度不等于服务器指定的
ArrayDimensions[20] - 权限问题:变量未调用
set_writable()设置为可写
内容的提问来源于stack exchange,提问作者Autolab
相关产品推荐
相关产品推荐

