NodeCollection — ua.nodes
NodeCollection 是 Session 的节点访问入口, 通过 get(String nodeId) 返回 OpcUaNode 包装对象, 不立即触发 RPC (Lazy Load).
前置阅读
- 单节点 API 请看 OpcUaNode.
- 标准节点常量请看 WellKnownNodes.
入口方法
| 方法 | 返回 | 说明 |
|---|---|---|
nodes.get(String nodeId) | OpcUaNode | 字符串 NodeId 访问 (对应 C# Nodes[nodeId] 索引器) |
nodes.makeNumeric(String nsUri, long id) | OpcUaNode | 按 ns URI + Numeric Id 构造 (内部走 namespaces.indexOf) |
nodes.makeString(String nsUri, String id) | OpcUaNode | 按 ns URI + String Id 构造 |
预定义入口方法 (标准节点)
为方便, 内置常用入口:
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 标准入口 | root() | OpcUaNode | R | Address Space 根 (i=84) |
objects() | OpcUaNode | R | 业务数据根 (i=85) | |
types() | OpcUaNode | R | 类型定义根 (i=86) | |
views() | OpcUaNode | R | 视图根 (i=87) | |
server() | OpcUaNode | R | Server 自身对象 (i=2253) |
// 这两行等价
try (OpcUaDataValue t1 = ua.nodes.server().get("ServerStatus").get("CurrentTime").getValue()) {
// ...
}
try (OpcUaDataValue t2 = ua.nodes.get("i=2253").get("ServerStatus").get("CurrentTime").getValue()) {
// ...
}
Lazy Load 机制
OpcUaNode node = ua.nodes.get("ns=2;s=Temperature"); // ← 不触发 RPC
try (OpcUaDataValue dv = node.getValue()) { // ← 第一次 .getValue() 才触发 Read
// ...
}
第二次访问 getValue() 还是会重新 Read (无缓存), 因为变量值随时变. 想缓存自己存变量.
子节点 BrowseName 索引
OpcUaNode sub = node.get("ChildName"); // 通过 BrowseName 浏览子节点
底层逻辑:
- 立即用
browse(currentNodeId)拿到子节点列表 - 找到
BrowseName == "ChildName"(或 DisplayName) 的子, 返回OpcUaNode包装 - 找不到返回
null(Java 风格, 不抛异常)
第一次访问会有 RPC 开销 (~5-10 ms), 后续路径访问连串都是单次 Browse 的结果.
按 NamespaceUri 构造 NodeId (推荐)
NamespaceIndex 不稳定, 生产代码用 NamespaceUri:
// 服务端的 ns 索引可能是 2 / 3 / 5, 不稳定 — 用 URI 反查
OpcUaNode temp = ua.nodes.makeString("urn:my-company:plc1", "Temperature");
try (OpcUaDataValue dv = temp.getValue()) {
// ...
}
Namespace 必须存在
makeNumeric / makeString 在 URI 不存在时抛 OpcUaException(DarraInvalidArgument). 调用前确保 ua.connect() 成功 (NamespaceArray 已加载).
何时用入口方法, 何时用字符串
| 场景 | 推荐 |
|---|---|
| 已知精确 NodeId | 字符串 (ua.read("ns=2;s=...")) |
| 标准节点 (Server 状态等) | nodes.server().get(...) |
| 浏览树 / 写一次性脚本 | 索引器 (nodes.get("...").get("...")) |
| 跨 Server NamespaceUri 移植 | nodes.makeString(uri, id) |
| 批量 (100+ 节点) | readMany / browseMany, 不要循环 |