结构体解码
概述
OPC UA 1.04+ 把每个自定义结构体的字段定义放到 DataType 节点的 DataTypeDefinition 属性 (AttributeId=27, Part 5 §6.4.2)。StructDecoder 实现完整协议层。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| StructDecoder(ua) | 构造 | — | 绑定到会话 |
| decoder.Decode(variant) | 方法 | 读 | 返回 DynamicExtensionObject |
| decoder.DecodeBody(bytes, data_type_id) | 方法 | 读 | 直接给字节 |
| decoder.GetDefinition(data_type_id) | 方法 | 读 | 获取 / 缓存 |
| decoder.PrefetchDefinitions(ids) | 方法 | 读 | 预热 |
| obj[field_name] | 索引 | 读 | 取字段 (返回 std::any) |
| obj.fields() | 属性 | 读 | 字段名→值 map |
| obj.definition() | 属性 | 读 | StructDefinition |
相关结构:
- Structure (0) — 普通
- StructureWithSubtypedValues (1) — 含子类型
- StructureWithOptionalFields (2) — 含可选 (前置 EncodingMask)
- Union (3) — Union (前置 selector)
- UnionWithSubtypedValues (4) — Union + 子类型
代码示例
#include <darra/opcua.h>
#include <any>
using namespace darra::opcua;
DarraOpcUa ua("opc.tcp://localhost:4840");
ua.Connect();
StructDecoder dec(ua);
// 1) 读自定义结构
auto dv = ua.Read("ns=2;s=Robot.CurrentPose");
auto pose = dec.Decode(dv.value);
std::cout << "x = " << std::any_cast<double>(pose["X"]) << "\n";
std::cout << "y = " << std::any_cast<double>(pose["Y"]) << "\n";
// 2) 全字段遍历
for (auto& [name, value] : pose.fields())
std::cout << name << " = " << /* any_cast / printer */ "\n";
// 3) 嵌套
auto quat = std::any_cast<DynamicExtensionObject>(pose["Quaternion"]);
std::cout << "qw = " << std::any_cast<double>(quat["W"]) << "\n";
// 4) 数组字段
auto arr = std::any_cast<std::vector<std::any>>(pose["JointAngles"]);
for (auto& a : arr)
std::cout << std::any_cast<double>(a) << "\n";
// 5) 预热
dec.PrefetchDefinitions({ "ns=2;i=3001", "ns=2;i=3002" });
实现限制
- Native 层未导出 ExtensionObject 字节提取接口, Decode(Variant) 在拿不到字节时返回带
_status字段的部分结果 - 协议层全部已实现, native 接通后 DecodeBody(bytes, type_id) 立刻可用
- DiagnosticInfo 跳过
最佳实践
- 共享一个 decoder, 字段表缓存复用
- PrefetchDefinitions 启动时调
- 嵌套结构 any_cast 后访问
- Union 看 selector
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| StructDecoder | StructDecoder | StructDecoder | StructDecoder | StructDecoder | DarraUa_StructDecoder |
| Decode | decode | decode | Decode | decode | DarraUa_StructDecoder_Decode |