Browse
browse(String nodeId, Enums.NodeClass filter) — 列出指定节点的直接子节点 (一层).
前置阅读 / 配套
- 大节点分页请用 BrowseWithPaging + BrowseNext.
- 路径式批量解析请用 TranslateBrowsePaths.
签名
public List<Reference> browse(String nodeId);
public List<Reference> browse(String nodeId, Enums.NodeClass filter);
public List<List<Reference>> browseMany(List<String> nodeIds, Enums.NodeClass filter);
Reference 字段
| 方法 | 返回 | 说明 |
|---|---|---|
| getNodeId() | String | 子节点 NodeId |
| getBrowseName() | String | 浏览名 (含 NamespaceIndex 前缀, 如 2:Temperature) |
| getDisplayName() | String | 显示名 |
| getNodeClass() | Enums.NodeClass | 子节点类别 |
| toNode(OpcUaSession) | OpcUaNode | 转为可操作的 OpcUaNode |
例子
// 列出 Boiler1 下所有子节点
List<Reference> children = ua.browse("ns=2;s=Boiler1");
for (Reference c : children) {
System.out.printf(" %s %s -> %s%n",
c.getNodeClass(), c.getBrowseName(), c.getNodeId());
}
// 只看 Variable 类型
List<Reference> vars = ua.browse("ns=2;s=Boiler1", Enums.NodeClass.Variable);
// 只看 Method
List<Reference> methods = ua.browse("ns=2;s=Calculator", Enums.NodeClass.Method);
批量浏览 (browseMany)
如果同时要浏览多个节点 (例如 GUI 初次展开树), 用 browseMany 一次 RPC:
List<String> roots = Arrays.asList(
"i=85" /* Objects */,
"i=86" /* Types */);
List<List<Reference>> results = ua.browseMany(roots, Enums.NodeClass.Unspecified);
for (int i = 0; i < roots.size(); i++) {
System.out.println(roots.get(i) + ":");
for (Reference c : results.get(i)) {
System.out.println(" " + c.getBrowseName());
}
}
如果某个节点浏览失败 (NodeId 错), 对应槽位返回空列表, 不抛异常.
NodeClass filter
| 值 | 包含 |
|---|---|
| Unspecified (0) | 全部 |
| Object (1) | 仅 Object |
| Variable (2) | 仅 Variable |
| Method (4) | 仅 Method |
Java 不支持按位或运算 enum, 想要"Object + Variable"组合请分两次 browse 后合并, 或循环过滤结果.
异常
OpcUaException(BadNodeIdUnknown) / OpcUaException(BadCommunicationError) 等. transport 失败抛, 单个子节点失败不抛.
大节点的分页 (ContinuationPoint)
如果一个节点有 1000+ 个子节点, 单次 browse 服务端可能截断. 此时 browse 只返回第一页, 续点被丢弃.
要看全部, 用 browseWithPaging + browseNext, 或直接 browseAll:
List<Reference> all = ua.browseAll("ns=2;s=BigFolder"); // 自动分页
System.out.println("Total " + all.size() + " children");
性能
- 单次 browse: ~5-15 ms (网络往返 + 服务端遍历)
- browseMany 批量: 总耗时 ~ 单次 (省 N-1 次往返)
- 1000+ 子节点会分页, 用
browseAll或手动browseNext
browseFiltered — 方向 + 引用类型过滤
browseFiltered 在 browse 的基础上加 BrowseDirection + referenceTypeId + includeSubtypes + resultMask 过滤 (Part 4 §5.8.2.2).
public List<Reference> browseFiltered(
String nid,
NodeClass nodeClassFilter,
BrowseDirection direction, // FORWARD / INVERSE / BOTH
String referenceTypeId, // null 表所有引用
boolean includeSubtypes,
int resultMask); // 0x3F 全字段
相关结构:
public enum BrowseDirection {
FORWARD, // 仅正向, 父→子
INVERSE, // 仅反向, 子→父
BOTH // 正反向都返回
}
示例
// 1) 正向 + 仅 HierarchicalReferences (i=33)
List<Reference> children = ua.browseFiltered("ns=2;s=Boiler1",
NodeClass.Unspecified, BrowseDirection.FORWARD, "i=33", true, 0x3F);
// 2) 反向找父
List<Reference> parents = ua.browseFiltered("ns=2;s=Tank.Level",
NodeClass.Unspecified, BrowseDirection.INVERSE, null, true, 0x3F);
for (Reference p : parents)
System.out.println("父: " + p.browseName);
// 3) 双向
List<Reference> all = ua.browseFiltered("ns=2;s=Robot.Joint1",
NodeClass.Unspecified, BrowseDirection.BOTH, null, true, 0x3F);
实现说明
- Stack 提供
DarraUa_Session_BrowseWithFilter时直调原生 - 否则 fallback 到 browse + 客户端按 NodeClass 过滤; referenceTypeId / direction 在 fallback 模式下无法精确生效, 打 Warning