OpcUaNode
OpcUaNode 是 NodeCollection 索引器返回的包装对象, 表示远程一个节点. Lazy Load — 只有访问属性才触发 RPC.
前置阅读
- 入口请看 NodeCollection.
- 想避免链式索引的多次 RPC 请用 translate_browse_paths 一次性解析路径.
公共属性
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 标识 (无 RPC) | node_id | str | R | 节点 ID 字符串 |
| 数据 (触发 RPC) | value | OpcUaDataValue | R | 当前值 — 触发 read(Value) |
display_name | Optional[str] | R | 显示名 — 触发 read(DisplayName) | |
browse_name | Optional[str] | R | 浏览名 — 触发 read(BrowseName) | |
description | Optional[str] | R | 描述 — 触发 read(Description) | |
node_class | NodeClass | R | 节点类别 — 触发 read(NodeClass) | |
data_type_node_id | Optional[str] | R | 数据类型 NodeId — 触发 read(DataType) | |
is_readable | bool | R | AccessLevel bit0 | |
is_writable | bool | R | AccessLevel bit1 | |
| 子节点 (触发 RPC) | children | List[Reference] | R | 子节点列表 — 触发 browse |
索引器
| 索引 | 返回 | 说明 |
|---|---|---|
node[browse_name] | Optional[OpcUaNode] | 按 BrowseName 取直接子节点, 未找到返回 None |
公共方法
| 方法 | 说明 |
|---|---|
read_attribute(attr) | 读指定 Attribute, 返回 OpcUaDataValue |
write(value) | 写 Value 属性, 返回 StatusCode |
write_attribute(attr, value) | 写任意属性 |
resolve(path) | 按 BrowsePath 深层解析 (相对当前节点) |
call(parent_object_node_id, *inputs) | 调用本节点为方法 |
例子
from darra_opcua import OpcUaVariant, AttributeId
# 1. 拿节点 (无 RPC)
temp = ua.nodes["ns=2;s=Temperature"]
# 2. 读基本信息 (各 1 次 RPC)
print(f"NodeId = {temp.node_id}")
print(f"display_name = {temp.display_name}")
print(f"node_class = {temp.node_class.name}")
print(f"data_type = {temp.data_type_node_id}")
# 3. 读值 (with 自动 dispose)
with temp.value as dv:
print(f"Value = {dv.value} °C @ {dv.source_timestamp}")
# 4. 写
temp.write(OpcUaVariant().set_double(25.5))
# 5. 浏览子节点
for child in temp.children:
print(f" {child.browse_name} -> {child.node_id}")
# 6. 链式访问 (Server.ServerStatus.CurrentTime)
with ua.nodes.server["ServerStatus"]["CurrentTime"].value as dv:
print(f"Server time = {dv.value}")
注意事项
- 所有触发 RPC 的属性都是"读一次返回一次", 不缓存. 想缓存自己存变量
- 链式访问
a["b"]["c"]每段都是一次 browse RPC, 总计 N 次 OpcUaDataValue必须 dispose, 否则泄漏 native 内存. 用with.- 跨线程使用
OpcUaNode安全 (它只持有 NodeId 字符串), 但OpcUaDataValue不要跨线程
与 resolve 的对比
# 方式 A: 链式索引器 - 4 次 RPC
with ua.nodes.server["ServerStatus"]["CurrentTime"].value as dv: # 1+2+3+4
print(dv.value)
# 方式 B: 路径解析 - 2 次 RPC
node = ua.resolve("/Objects/Server/ServerStatus/CurrentTime") # 1
with node.value as dv: # 1
print(dv.value)
# 方式 C: 直接 NodeId - 1 次 RPC
with ua.read("i=2258") as dv:
print(dv.value)
如果路径已知 → 方式 C; 探索式开发 → 方式 A.