Browse (C)
DarraUa_Session_BrowseNode(h, node_id, filter, &res) — 列出指定节点的直接子节点 (一层).
前置阅读 / 配套
- 大节点分页请用 BrowseWithPaging + BrowseNext.
- 路径式批量解析请用 TranslateBrowsePaths.
API
DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_BrowseNode(
DarraUa_SessionHandle h,
const char* node_id_str,
DarraUa_NodeClass filter_node_class,
DarraUa_BrowseResult** out_result);
DARRA_OPCUA_API uint32_t DARRA_OPCUA_CALL
DarraUa_BrowseResult_GetCount(const DarraUa_BrowseResult* r);
DARRA_OPCUA_API const DarraUa_ReferenceDescription* DARRA_OPCUA_CALL
DarraUa_BrowseResult_GetReference(const DarraUa_BrowseResult* r, uint32_t index);
DARRA_OPCUA_API void DARRA_OPCUA_CALL
DarraUa_BrowseResult_Delete(DarraUa_BrowseResult* r);
out_result 由 Stack 分配, 用 _Delete 释放. 失败时 *out_result = NULL.
ReferenceDescription 字段访问器
DARRA_OPCUA_API const char* DARRA_OPCUA_CALL
DarraUa_Ref_GetBrowseName(const DarraUa_ReferenceDescription* rd);
DARRA_OPCUA_API const char* DARRA_OPCUA_CALL
DarraUa_Ref_GetDisplayName(const DarraUa_ReferenceDescription* rd);
DARRA_OPCUA_API int32_t DARRA_OPCUA_CALL
DarraUa_Ref_GetNodeClass(const DarraUa_ReferenceDescription* rd);
DARRA_OPCUA_API int32_t DARRA_OPCUA_CALL
DarraUa_Ref_GetNodeIdString(
const DarraUa_ReferenceDescription* rd,
char* buf, int32_t buf_size);
Get* 返回的 const char* 生命周期 = BrowseResult, 不要 free.
用法
DarraUa_BrowseResult* br = NULL;
DarraUa_Status st = DarraUa_Session_BrowseNode(
h, "ns=2;s=Boiler1",
DARRA_UA_NODE_CLASS_UNSPECIFIED,
&br);
if (!DARRA_UA_STATUS_IS_GOOD(st) || !br) {
fprintf(stderr, "Browse failed: %s\n", DarraUa_StatusName(st));
return;
}
uint32_t n = DarraUa_BrowseResult_GetCount(br);
char id_buf[128];
for (uint32_t i = 0; i < n; ++i) {
const DarraUa_ReferenceDescription* rd =
DarraUa_BrowseResult_GetReference(br, i);
if (!rd) continue;
int32_t nc = DarraUa_Ref_GetNodeClass(rd);
const char* name = DarraUa_Ref_GetBrowseName(rd);
const char* dname = DarraUa_Ref_GetDisplayName(rd);
DarraUa_Ref_GetNodeIdString(rd, id_buf, (int32_t)sizeof(id_buf));
printf(" [class=%d] %-20s %s -> %s\n",
nc, name ? name : "", dname ? dname : "", id_buf);
}
DarraUa_BrowseResult_Delete(br);
批量浏览 (BrowseNodes)
如果同时要浏览多个节点 (例如 GUI 初次展开树), 用 BrowseNodes 一次 RPC:
DARRA_OPCUA_API DarraUa_Status DARRA_OPCUA_CALL DarraUa_Session_BrowseNodes(
DarraUa_SessionHandle h,
const char* const* node_id_strs,
uint32_t count,
DarraUa_NodeClass filter_node_class,
DarraUa_BrowseResult** out_results); /* 调用方分配 count 个槽 */
const char* roots[] = { "i=85" /* Objects */, "i=86" /* Types */ };
DarraUa_BrowseResult* results[2] = { NULL };
DarraUa_Session_BrowseNodes(h, roots, 2,
DARRA_UA_NODE_CLASS_UNSPECIFIED, results);
for (uint32_t r = 0; r < 2; ++r) {
if (!results[r]) {
printf("%s: failed\n", roots[r]);
continue;
}
uint32_t cnt = DarraUa_BrowseResult_GetCount(results[r]);
printf("%s: %u children\n", roots[r], cnt);
DarraUa_BrowseResult_Delete(results[r]);
}
如果某个节点浏览失败, 对应槽位 results[i] = NULL, 不影响其他.
NodeClass filter
typedef enum {
DARRA_UA_NODE_CLASS_UNSPECIFIED = 0,
DARRA_UA_NODE_CLASS_OBJECT = 1,
DARRA_UA_NODE_CLASS_VARIABLE = 2,
DARRA_UA_NODE_CLASS_METHOD = 4,
DARRA_UA_NODE_CLASS_OBJECT_TYPE = 8,
DARRA_UA_NODE_CLASS_VARIABLE_TYPE = 16,
DARRA_UA_NODE_CLASS_REFERENCE_TYPE= 32,
DARRA_UA_NODE_CLASS_DATA_TYPE = 64,
DARRA_UA_NODE_CLASS_VIEW = 128
} DarraUa_NodeClass;
按位或可组合 (例如 OBJECT | VARIABLE).
/* 只看 Variable */
DarraUa_Session_BrowseNode(h, "ns=2;s=Boiler1",
DARRA_UA_NODE_CLASS_VARIABLE, &br);
/* 只看 Method */
DarraUa_Session_BrowseNode(h, "ns=2;s=Calculator",
DARRA_UA_NODE_CLASS_METHOD, &br);
大节点的分页 (ContinuationPoint)
如果一个节点有 1000+ 个子节点, 单次 Browse 服务端可能截断. 此时 BrowseNode 返回的 BrowseResult 内含 ContinuationPoint, 用 _GetContinuationPoint 拿到后调 BrowseNext:
const uint8_t* cp = NULL;
int32_t cp_len = 0;
cp = DarraUa_BrowseResult_GetContinuationPoint(br, &cp_len);
if (cp && cp_len > 0) {
DarraUa_BrowseResult* next = NULL;
DarraUa_Session_BrowseNext(h, /*release*/ 0, cp, cp_len, &next);
/* ... 处理 next ... */
DarraUa_BrowseResult_Delete(next);
}
完整循环模板见 Browse 自动分页.
错误码
| 状态码 | 含义 |
|---|---|
Good | 成功 |
BadNodeIdUnknown | NodeId 不存在 |
BadNodeIdInvalid | NodeId 字符串解析失败 |
BadCommunicationError | 网络故障 |
性能
- 单次 Browse: ~5-15 ms
- BrowseNodes 批量: 总耗时 ~ 单次 (省 N-1 次往返)
- 1000+ 子节点会分页, 加 BrowseNext 处理