跳到主要内容

Browse

browse(String nodeId, Enums.NodeClass filter) — 列出指定节点的直接子节点 (一层).

前置阅读 / 配套

签名

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 — 方向 + 引用类型过滤

browseFilteredbrowse 的基础上加 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

下一步