OpcUaNodeId — 强类型 NodeId
概述
OPC UA 节点 ID 默认用字符串编码 ("ns=2;s=Foo")。DarraUa_NodeId 是强类型 struct, 显式带 namespace / id_type / identifier。
对应规范段: Part 6 §5.2.2。
API
| 函数 | 类别 | 读写 | 说明 |
|---|---|---|---|
| DarraUa_NodeId_Null(&out_nid) | 工厂 | — | 空哨兵 |
| DarraUa_NodeId_FromNumeric(ns, id, &out_nid) | 工厂 | — | 数字型 |
| DarraUa_NodeId_FromString(ns, id, &out_nid) | 工厂 | — | 字符串型 |
| DarraUa_NodeId_FromGuid(ns, guid_bytes, &out_nid) | 工厂 | — | GUID 型 |
| DarraUa_NodeId_FromOpaque(ns, bytes, n, &out_nid) | 工厂 | — | 不透明型 |
| DarraUa_NodeId_Parse(s, &out_nid) | 静态 | — | 解析, 返回 StatusCode |
| DarraUa_NodeId_TryParse(s, &out_nid) | 静态 | — | 等同 Parse |
| DarraUa_NodeId_ToString(nid, &out_str) | — | — | 序列化, 调用方 Free |
| DarraUa_NodeId_IsNull(nid) | 方法 | 读 | 返回 int (0/1) |
| DarraUa_NodeId_Free(nid) | 释放 | — | 释放 (内部 strdup) |
typedef struct {
uint16_t namespace_index;
DarraUa_NodeIdType id_type;
union {
uint32_t numeric;
char* string;
uint8_t guid[16];
struct { uint8_t* bytes; size_t n; } opaque;
} id;
} DarraUa_NodeId;
相关结构:
typedef enum {
NID_NUMERIC = 0, // i= 编码, uint32
NID_STRING = 1, // s= 编码, UTF-8
NID_GUID = 2, // g= 编码, {xxxx-...}
NID_OPAQUE = 3 // b= 编码, base64
} DarraUa_NodeIdType;
代码示例
#include <opcua.h>
int main() {
// 1) 工厂
DarraUa_NodeId n1, n2, n3, n4;
DarraUa_NodeId_FromNumeric(0, 84, &n1);
DarraUa_NodeId_FromString(2, "Boiler1.Temp", &n2);
uint8_t guid[16] = { /* ... */ };
DarraUa_NodeId_FromGuid(3, guid, &n3);
uint8_t bytes[3] = { 1, 2, 3 };
DarraUa_NodeId_FromOpaque(4, bytes, 3, &n4);
// 2) 解析
DarraUa_NodeId n5;
DarraUa_StatusCode rc = DarraUa_NodeId_Parse("ns=2;s=Demo.Tag", &n5);
if (rc == UA_GOOD)
printf("ns=%u, type=%d\n", n5.namespace_index, n5.id_type);
DarraUa_NodeId n6;
if (DarraUa_NodeId_TryParse("ns=99;i=foo", &n6) != UA_GOOD)
printf("invalid\n");
// 3) 序列化
char* s = NULL;
DarraUa_NodeId_ToString(&n2, &s);
printf("%s\n", s); // "ns=2;s=Boiler1.Temp"
// 4) 与 SDK 互转
DarraUa_DataValue* dv = NULL;
DarraUa_Session_Read(ua, s, ATTR_VALUE, &dv);
DarraUa_FreeDataValue(dv);
// 5) Null
printf("%d\n", DarraUa_NodeId_IsNull(&n2)); // 0
// 6) 释放
DarraUa_NodeId_Free(&n2);
DarraUa_NodeId_Free(&n5);
DarraUa_FreeString(s);
return 0;
}
最佳实践
- 配置文件存字符串, 加载用 Parse
- 代码内部用强类型
- Numeric 优先 (uint 比较快)
- 用户输入永远先 TryParse
- 释放: 字符串 / Opaque NodeId 内部分配的资源用 Free
跨语言对照
| 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 |
| FromString | from_string | fromString | FromString | from_string | DarraUa_NodeId_FromString |