结构体解码
概述
OPC UA 1.04+ 把每个自定义结构体的字段定义放到 DataType 节点的 DataTypeDefinition 属性 (AttributeId=27, Part 5 §6.4.2)。StructDecoder 实现完整协议层。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| StructDecoder::new(ua) | 构造 | — | 绑定到会话 |
| decoder.decode(variant) | 方法 | 读 | 返回 Result<DynamicExtensionObject> |
| decoder.decode_body(bytes, data_type_id) | 方法 | 读 | 直接给字节 |
| decoder.get_definition(data_type_id) | 方法 | 读 | 获取 / 缓存 |
| decoder.prefetch_definitions(ids) | 方法 | 读 | 预热 |
| obj.get(field_name) | 方法 | 读 | 取字段 (返回 Option<&FieldValue>) |
| obj.fields() | 方法 | 读 | 字段名→值 HashMap |
| obj.definition() | 方法 | 读 | StructDefinition |
相关结构:
pub enum StructureKind {
Structure = 0, // 普通
StructureWithSubtypedValues = 1, // 含子类型
StructureWithOptionalFields = 2, // 含可选 (前置 EncodingMask)
Union = 3, // Union (前置 selector)
UnionWithSubtypedValues = 4, // Union + 子类型
}
pub enum FieldValue {
Bool(bool),
Int64(i64),
UInt64(u64),
Float(f32),
Double(f64),
String(String),
Bytes(Vec<u8>),
DateTime(DateTime<Utc>),
Nested(Box<DynamicExtensionObject>),
Array(Vec<FieldValue>),
Null,
}
代码示例
use opcua::{DarraOpcUa, StructDecoder, FieldValue};
let ua = DarraOpcUa::new("opc.tcp://localhost:4840")?;
ua.connect()?;
let dec = StructDecoder::new(&ua);
// 1) 读自定义结构
let dv = ua.read("ns=2;s=Robot.CurrentPose", AttributeId::Value)?;
let pose = dec.decode(&dv.value)?;
if let Some(FieldValue::Double(x)) = pose.get("X") { println!("x = {}", x); }
if let Some(FieldValue::Double(y)) = pose.get("Y") { println!("y = {}", y); }
// 2) 全字段遍历
for (name, value) in pose.fields() {
println!("{} = {:?}", name, value);
}
// 3) 嵌套
if let Some(FieldValue::Nested(quat)) = pose.get("Quaternion") {
if let Some(FieldValue::Double(qw)) = quat.get("W") {
println!("qw = {}", qw);
}
}
// 4) 数组字段
if let Some(FieldValue::Array(arr)) = pose.get("JointAngles") {
for a in arr {
println!("{:?}", a);
}
}
// 5) 预热
dec.prefetch_definitions(&["ns=2;i=3001", "ns=2;i=3002"])?;
实现限制
- Native 层未导出 ExtensionObject 字节提取接口, decode(variant) 在拿不到字节时返回
FieldValue::Null占位 - 协议层全部已实现, native 接通后 decode_body(bytes, type_id) 立刻可用
- DiagnosticInfo 跳过
最佳实践
- 共享一个 decoder, 字段表缓存复用
- prefetch_definitions 启动时调
- 嵌套结构 match 解构访问
- Union 看 definition().is_union()
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| StructDecoder | StructDecoder | StructDecoder | StructDecoder | StructDecoder | DarraUa_StructDecoder |
| Decode | decode | decode | Decode | decode | DarraUa_StructDecoder_Decode |