跳到主要内容

结构体解码

概述

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#PythonJavaC++RustC
StructDecoderStructDecoderStructDecoderStructDecoderStructDecoderDarraUa_StructDecoder
DecodedecodedecodeDecodedecodeDarraUa_StructDecoder_Decode

下一步