OpcUaNodeId — 强类型 NodeId
概述
OPC UA 节点 ID 默认用字符串编码 ("ns=2;s=Foo")。OpcUaNodeId 是不可变值类型, 显式带 namespace / id_type / identifier 三件套。
对应规范段: Part 6 §5.2.2。
API
| 成员 | 类别 | 读写 | 说明 |
|---|---|---|---|
| OpcUaNodeId::Null | 静态 | 读 | 空哨兵 |
| OpcUaNodeId::FromNumeric(ns, id) | 工厂 | — | 数字型 |
| OpcUaNodeId::FromString(ns, id) | 工厂 | — | 字符串型 |
| OpcUaNodeId::FromGuid(ns, uuid) | 工厂 | — | GUID 型 |
| OpcUaNodeId::FromOpaque(ns, bytes) | 工厂 | — | 不透明型 |
| OpcUaNodeId::Parse(s) | 静态 | — | 解析, 失败抛 std::invalid_argument |
| OpcUaNodeId::TryParse(s, out_nid) | 静态 | — | 安全解析, 返回 bool |
| nid.ToString() | — | — | 序列化 |
| nid.namespace_index() / id_type() / identifier() / IsNull() | 属性 | 读 | 字段 |
相关结构:
- Numeric (0) — 编码
i=, uint32 - String (1) — 编码
s=, UTF-8 - Guid (2) — 编码
g=,{xxxx-...} - Opaque (3) — 编码
b=, base64
代码示例
#include <darra/opcua.h>
using namespace darra::opcua;
// 1) 工厂
auto n1 = OpcUaNodeId::FromNumeric(0, 84); // i=84
auto n2 = OpcUaNodeId::FromString(2, "Boiler1.Temp");
auto n3 = OpcUaNodeId::FromGuid(3, /*uuid_t*/ ...);
auto n4 = OpcUaNodeId::FromOpaque(4, std::vector<uint8_t>{1,2,3});
// 2) 解析
auto n5 = OpcUaNodeId::Parse("ns=2;s=Demo.Tag");
std::cout << "ns=" << n5.namespace_index() << ", type=" << n5.id_type() << "\n";
OpcUaNodeId n6;
if (!OpcUaNodeId::TryParse("ns=99;i=foo", n6))
std::cout << "invalid\n";
// 3) 序列化
auto s = n2.ToString(); // "ns=2;s=Boiler1.Temp"
// 4) 与 SDK 互转
auto dv = ua.Read(n2.ToString());
// 5) 字典 key (有 operator< / std::hash 特化)
std::map<OpcUaNodeId, std::string> dict;
dict[n2] = "锅炉一温度";
// 6) Null
std::cout << OpcUaNodeId::Null.IsNull() << "\n"; // 1
最佳实践
- 配置文件存字符串, 加载用 Parse
- 代码内部用强类型
- Numeric 优先 (uint 比较快)
- 用户输入永远先 TryParse
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| OpcUaNodeId | OpcUaNodeId | OpcUaNodeId | OpcUaNodeId | OpcUaNodeId | DarraUa_NodeId |
| Parse | parse | parse | Parse | parse | DarraUa_NodeId_Parse |
| FromNumeric | from_numeric | fromNumeric | FromNumeric | from_numeric | DarraUa_NodeId_FromNumeric |