结构体解码
概述
OPC UA 1.04+ 把每个自定义结构体的字段定义放到 DataType 节点的 DataTypeDefinition 属性 (AttributeId=27, Part 5 §6.4.2)。客户端 Read 该属性 → 缓存 StructureDefinition → 拿到 ExtensionObject 字节后按字段顺序用 UA Binary 编码反序列化为 dict。
StructDecoder 实现了完整的协议层: 全部基本类型 + 嵌套结构 + 数组 + 枚举 + Union + Optional 字段。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| StructDecoder(ua) | 构造 | — | 绑定到会话 |
| decoder.decode(variant) | 方法 | 读 | 解码 ExtensionObject, 返回 DynamicExtensionObject |
| decoder.decode_body(body, data_type_id) | 方法 | 读 | 直接给字节 + DataType 解码 |
| decoder.get_definition(data_type_id) | 方法 | 读 | 获取 / 缓存 StructDefinition |
| decoder.prefetch_definitions(ids) | 方法 | 读 | 预热缓存 |
| obj[field_name] | 索引器 | 读 | 取字段值 |
| obj.fields | 属性 | 读 | 字段名→值 dict |
| obj.definition | 属性 | 读 | StructDefinition |
相关结构:
class StructureKind(IntEnum):
STRUCTURE = 0 # 普通
STRUCTURE_WITH_SUBTYPED_VALUES = 1 # 含子类型
STRUCTURE_WITH_OPTIONAL_FIELDS = 2 # 含可选字段 (前置 EncodingMask)
UNION = 3 # Union (前置 selector)
UNION_WITH_SUBTYPED_VALUES = 4 # Union + 子类型
代码示例
from opcua import DarraOpcUa, StructDecoder
with DarraOpcUa("opc.tcp://localhost:4840") as ua:
ua.connect()
dec = StructDecoder(ua)
# 1) 读自定义结构体
with ua.read("ns=2;s=Robot.CurrentPose") as dv:
pose = dec.decode(dv.value)
print(f"x = {pose['X']}") # 100.5
print(f"y = {pose['Y']}") # 200.3
print(f"q = {pose['Quaternion']}") # 嵌套 → DynamicExtensionObject
# 2) 全字段遍历
for name, value in pose.fields.items():
print(f"{name} = {value}")
# 3) 嵌套结构
quat = pose['Quaternion']
print(f"qw = {quat['W']}")
# 4) 数组字段
arr = pose['JointAngles'] # list
for a in arr:
print(a)
# 5) Union
with ua.read("ns=2;s=AnyValue") as uv:
u = dec.decode(uv.value)
print(f"selector field={u.definition.fields[0].name}")
# 6) 预热
dec.prefetch_definitions([
"ns=2;i=3001", # PoseType
"ns=2;i=3002", # QuaternionType
])
实现限制
- Native 层 (
DLL) 当前未导出 ExtensionObject TypeId/Body 提取接口, decode(variant) 在拿不到字节流时返回带_status字段的部分结果 - 协议层全部已实现, native 接通后立刻可用 —
decode_body(bytes, type_id)重载 - DiagnosticInfo 跳过 (生产代码极少用)
最佳实践
- 共享一个 decoder, 字段表缓存复用
- prefetch_definitions 启动时调
- 嵌套结构直接索引访问
- Union 看 selector
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| StructDecoder | StructDecoder | StructDecoder | StructDecoder | StructDecoder | DarraUa_StructDecoder |
| Decode | decode | decode | Decode | decode | DarraUa_StructDecoder_Decode |
| DynamicExtensionObject | DynamicExtensionObject | DynamicExtensionObject | DynamicExtensionObject | DynamicExtensionObject | DarraUa_DynamicExtensionObject |