Browse
s.Browse(node_id, filter = NodeClass::Unspecified) — 列出指定节点的直接子节点 (一层).
前置阅读 / 配套
- 大节点分页请用 BrowseWithPaging + BrowseNext.
- 路径式批量解析请用 TranslateBrowsePaths.
签名
std::vector<Reference> Browse(
std::string const& node_id,
NodeClass filter = NodeClass::Unspecified);
std::vector<std::vector<Reference>> BrowseMany(
std::vector<std::string> const& node_ids,
NodeClass filter = NodeClass::Unspecified);
Reference 结构
struct Reference {
std::string node_id;
std::string browse_name;
std::string display_name;
NodeClass node_class;
};
| 字段 | 类型 | 说明 |
|---|---|---|
| node_id | std::string | 子节点 NodeId |
| browse_name | std::string | 浏览名 (含 NamespaceIndex 前缀, 如 2:Temperature) |
| display_name | std::string | 显示名 |
| node_class | NodeClass | 子节点类别 |
例子
// 列出 Boiler1 下所有子节点
auto children = s.Browse("ns=2;s=Boiler1");
for (auto const& c : children) {
std::cout << " " << static_cast<int>(c.node_class)
<< " " << c.browse_name << " -> " << c.node_id << "\n";
}
// 只看 Variable 类型
auto vars = s.Browse("ns=2;s=Boiler1", NodeClass::Variable);
// 只看 Method
auto methods = s.Browse("ns=2;s=Calculator", NodeClass::Method);
批量浏览 (BrowseMany)
如果同时要浏览多个节点 (例如 GUI 初次展开树), 用 BrowseMany 一次 RPC:
std::vector<std::string> roots = { "i=85" /* Objects */, "i=86" /* Types */ };
auto results = s.BrowseMany(roots);
for (size_t i = 0; i < roots.size(); ++i) {
std::cout << roots[i] << ":\n";
for (auto const& c : results[i]) {
std::cout << " " << c.browse_name << "\n";
}
}
如果某个节点浏览失败 (NodeId 错), 对应槽位返回空 std::vector<Reference>, 不抛异常.
NodeClass filter
enum class NodeClass : int32_t {
Unspecified = 0,
Object = 1,
Variable = 2,
Method = 4,
ObjectType = 8,
VariableType = 16,
ReferenceType = 32,
DataType = 64,
View = 128
};
| 值 | 包含 |
|---|---|
| Unspecified | 全部 |
| Object | 仅 Object |
| Variable | 仅 Variable |
| Method | 仅 Method |
按位或当前 SDK 暂不直接支持, 需要分多次 Browse.
异常
Exception(..., BadNodeIdUnknown) / Exception(..., BadCommunicationError) 等. transport 失败抛, 单个子节点失败不抛.
大节点的分页 (ContinuationPoint)
如果一个节点有 1000+ 个子节点, 单次 Browse 服务端可能截断. 此时 Browse 只返回第一页.
要看全部, 用 BrowseWithPaging + BrowseNext:
auto page = s.BrowseWithPaging("ns=2;s=BigFolder");
std::vector<Reference> all_refs = page.references;
while (!page.continuation_point.empty()) {
page = s.BrowseNext(page.continuation_point);
all_refs.insert(all_refs.end(), page.references.begin(), page.references.end());
}
性能
- 单次 Browse: ~5-15 ms (网络往返 + 服务端遍历)
- BrowseMany 批量: 总耗时 ~ 单次 (省 N-1 次往返)
- 1000+ 子节点会分页, 加 BrowseNext 处理
BrowseFiltered — 方向 + 引用类型过滤
BrowseFiltered 在 Browse 的基础上加 BrowseDirection + reference_type_id + include_subtypes + result_mask 过滤 (Part 4 §5.8.2.2).
std::vector<OpcUaReference> BrowseFiltered(
std::string const& nid,
NodeClass node_class_filter = NodeClass::Unspecified,
BrowseDirection direction = BrowseDirection::Forward,
std::string const& reference_type_id = "",
bool include_subtypes = true,
uint32_t result_mask = 0x3F);
相关结构:
- Forward (0) — 仅正向, 父→子
- Inverse (1) — 仅反向, 子→父
- Both (2) — 正反向都返回
示例
// 1) 正向 + 仅 HierarchicalReferences (i=33)
auto children = ua.BrowseFiltered("ns=2;s=Boiler1",
NodeClass::Unspecified, BrowseDirection::Forward, "i=33", true);
// 2) 反向找父
auto parents = ua.BrowseFiltered("ns=2;s=Tank.Level",
NodeClass::Unspecified, BrowseDirection::Inverse);
for (auto& p : parents)
std::cout << "父: " << p.browse_name << "\n";
// 3) 双向
auto all = ua.BrowseFiltered("ns=2;s=Robot.Joint1",
NodeClass::Unspecified, BrowseDirection::Both);
实现说明
- Stack 提供
DarraUa_Session_BrowseWithFilter时直调原生 - 否则 fallback 到 Browse + 客户端按 NodeClass 过滤; reference_type_id / direction 在 fallback 模式下无法精确生效, 打 Warning
BrowseAll — 自动续翻
std::vector<OpcUaReference> BrowseAll(
std::string const& nid,
NodeClass filter = NodeClass::Unspecified,
int max_pages = 32);
自动反复调 BrowseNext 直到 ContinuationPoint 为空:
auto all = ua.BrowseAll("ns=2;s=BigFolder");
std::cout << "共 " << all.size() << " 个子节点\n";