跳到主要内容

TranslateBrowsePaths (C)

TranslateBrowsePathsToNodeIds 服务: 输入 起始节点 + 相对路径数组 (如 "/2:Boilers/1:Drum/Level"), 输出每个路径解析后的 NodeId 字符串. 比客户端循环 Browse 快得多 (单 RPC).

前置阅读
  • 想链式探索建议用 Browse 单层浏览.
  • 100+ 路径批量初始化必用本 API.

API

DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_TranslateBrowsePaths(
DarraUa_SessionHandle h,
const char* const* starting_node_ids,
const char* const* browse_paths,
uint32_t count,
char*** out_node_ids, /* 出参 */
DarraUa_Status* out_status_per_path); /* 出参, 调用方分配 count 个 */
参数说明
starting_node_ids每个路径的起点 NodeId 字符串数组 (长度 = count)
browse_paths路径数组, 段间用 / 分 (长度 = count)
count路径数量
out_node_ids出参: char** 数组, 每项是解析到的 NodeId 字符串 (NULL = 失败)
out_status_per_path出参: 每项 StatusCode

释放

out_node_ids 数组与每个非 NULL 字符串都由 Stack malloc:

if (node_ids) {
for (uint32_t i = 0; i < count; ++i) {
if (node_ids[i]) DarraUa_Free(node_ids[i]);
}
DarraUa_Free(node_ids);
}

路径段语法

段格式含义
BrowseNamenamespace 0
2:BrowseNamenamespace 2
/A/B/C起点不含, 直接以 /

例子:

BrowsePath含义
/Serverns=0 下子节点 Server
/2:Boiler1ns=2 下子节点 Boiler1
/Server/2:Boilers/2:Boiler1/2:Temperature多层组合

/2:Boilers/1:Drum/Level 表示从起点出发, 先到 ns=2;Boilers, 再到 ns=1;Drum, 再到 Level (ns=0).


完整示例

#include <darra_opcua/darra_opcua.h>
#include <stdio.h>

int main(int argc, char** argv)
{
const char* endpoint = (argc >= 2) ? argv[1] : "opc.tcp://localhost:4840";
DarraUa_Initialize();

DarraUa_SessionConfig cfg;
DarraUa_SessionConfig_Init(&cfg);
cfg.endpoint_url = endpoint;
cfg.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#None";

DarraUa_SessionHandle h = DARRA_UA_INVALID_SESSION_HANDLE;
DarraUa_Session_Create(&cfg, &h);
DarraUa_Session_Connect(h);

/* 4 个路径 */
const char* starts[] = {
"i=85", "i=85", "ns=2;s=Boiler1", "ns=2;s=Boiler1",
};
const char* paths[] = {
"/Server/ServerStatus/CurrentTime",
"/Server/ServerStatus/State",
"/Temperature",
"/Pressure",
};
uint32_t count = 4;

char** node_ids = NULL;
DarraUa_Status results[4] = { 0 };

DarraUa_Status st = DarraUa_Session_TranslateBrowsePaths(
h, starts, paths, count, &node_ids, results);

if (!DARRA_UA_STATUS_IS_GOOD(st)) {
fprintf(stderr, "TranslateBrowsePaths failed: 0x%08X (%s)\n",
(unsigned)st, DarraUa_StatusName(st));
} else {
for (uint32_t i = 0; i < count; ++i) {
printf("[%u] %-50s -> ", i, paths[i]);
if (DARRA_UA_STATUS_IS_GOOD(results[i]) && node_ids && node_ids[i])
printf("%s\n", node_ids[i]);
else
printf("FAILED (%s)\n", DarraUa_StatusName(results[i]));
}
}

/* 释放 */
if (node_ids) {
for (uint32_t i = 0; i < count; ++i) {
if (node_ids[i]) DarraUa_Free(node_ids[i]);
}
DarraUa_Free(node_ids);
}

DarraUa_Session_Disconnect(h);
DarraUa_Session_Close(h);
DarraUa_Shutdown();
return 0;
}

与 ResolveBrowsePath 的对比

函数实现方式性能用途
DarraUa_Session_TranslateBrowsePaths服务端原生 (OPC UA 服务)快, 单 RPC, 批量生产
DarraUa_Session_ResolveBrowsePath客户端循环 Browse 爬慢, N 次 RPC, 单条Server 不支持 TranslateBrowsePaths 时, 或仅一条

ResolveBrowsePath:

DARRA_OPCUA_API int32_t DARRA_OPCUA_CALL DarraUa_Session_ResolveBrowsePath(
DarraUa_SessionHandle h,
const char* start_node_id,
const char* path,
char* out_node_id,
int32_t out_buf_size);
参数说明
out_node_id调用方提供的 buffer
out_buf_sizebuffer 字节数

返回值: 解析到的 NodeId 字符串长度 (含 NUL); ≤ 0 表示失败.

char buf[128];
int32_t n = DarraUa_Session_ResolveBrowsePath(
h, "i=85",
"/Server/ServerStatus/CurrentTime",
buf, (int32_t)sizeof(buf));
if (n > 0) printf("Resolved -> %s\n", buf);

错误码 (per path)

StatusCode含义
Good解析成功
BadNoMatch路径段在树上找不到
BadBrowseNameInvalid段语法错
BadNodeIdUnknown起点不存在

最佳实践

  • 业务启动时一次性把所有需要的"配置路径" 翻成 NodeId 缓存起来, 后续直接用 NodeId 读写
  • 不要每次读 / 写都重新 Translate, 浪费 RPC
  • 超大路径列表分批 (建议每批 ≤ 100), 防止服务端拒绝 BadTooManyOperations (0x80100000 = DARRA_UA_STATUS_BAD_TOO_MANY_OPERATIONS)

下一步