结构体解码
概述
OPC UA 1.04+ 把每个自定义结构体的字段定义放到 DataType 节点的 DataTypeDefinition 属性 (AttributeId=27, Part 5 §6.4.2)。StructDecoder 实现完整协议层: 全部基本类型 + 嵌套结构 + 数组 + 枚举 + Union + Optional 字段。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| new StructDecoder(ua) | 构造 | — | 绑定到会话 |
| decoder.decode(variant) | 方法 | 读 | 解码, 返回 DynamicExtensionObject |
| decoder.decodeBody(bytes, dataTypeId) | 方法 | 读 | 直接给字节 + DataType 解码 |
| decoder.getDefinition(dataTypeId) | 方法 | 读 | 获取 / 缓存 StructDefinition |
| decoder.prefetchDefinitions(ids) | 方法 | 读 | 预热缓存 |
| obj.get(fieldName) | 方法 | 读 | 取字段 |
| obj.fields() | 方法 | 读 | 字段名→值 Map |
| obj.definition() | 方法 | 读 | StructDefinition |
相关结构:
public enum StructureKind {
STRUCTURE, // 普通
STRUCTURE_WITH_SUBTYPED_VALUES, // 含子类型
STRUCTURE_WITH_OPTIONAL_FIELDS, // 含可选 (前置 EncodingMask)
UNION, // Union (前置 selector)
UNION_WITH_SUBTYPED_VALUES // Union + 子类型
}
代码示例
import com.darra.opcua.*;
try (DarraOpcUa ua = new DarraOpcUa("opc.tcp://localhost:4840")) {
ua.connect();
StructDecoder dec = new StructDecoder(ua);
// 1) 读自定义结构
try (DataValue dv = ua.read("ns=2;s=Robot.CurrentPose")) {
DynamicExtensionObject pose = dec.decode(dv.value);
System.out.println("x = " + pose.get("X"));
System.out.println("y = " + pose.get("Y"));
// 2) 全字段遍历
for (var e : pose.fields().entrySet())
System.out.println(e.getKey() + " = " + e.getValue());
// 3) 嵌套
DynamicExtensionObject quat = (DynamicExtensionObject) pose.get("Quaternion");
System.out.println("qw = " + quat.get("W"));
// 4) 数组字段
Object[] arr = (Object[]) pose.get("JointAngles");
for (Object a : arr) System.out.println(a);
}
// 5) 预热
dec.prefetchDefinitions(List.of("ns=2;i=3001", "ns=2;i=3002"));
}
实现限制
- Native 层未导出 ExtensionObject 字节提取接口, decode(Variant) 在拿不到字节时返回带
_status字段的部分结果 - 协议层全部已实现, native 接通后 decodeBody(bytes, typeId) 立刻可用
- DiagnosticInfo 跳过
最佳实践
- 共享一个 decoder, 字段表缓存复用
- prefetchDefinitions 启动时调
- 嵌套结构 cast 后访问
- Union 看 selector
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| StructDecoder | StructDecoder | StructDecoder | StructDecoder | StructDecoder | DarraUa_StructDecoder |
| Decode | decode | decode | Decode | decode | DarraUa_StructDecoder_Decode |