NodeCollection — s.nodes()
NodeCollection 是 Session 的节点访问入口, 通过 get(node_id) 返回
Node 包装对象, 不立即触发 RPC (Lazy Load).
前置阅读
- 单节点 API 请看 Node.
- 标准节点常量请看 WellKnownNodes.
入口方法
| 方法 | 返回 | 说明 |
|---|---|---|
s.nodes() | NodeCollection | 廉价 clone (内部 Arc<SessionInner>) |
公共方法
| 方法 | 返回 | 说明 |
|---|---|---|
get(&self, node_id: &str) | Node | 字符串 NodeId 访问 |
make_numeric(uri, id) | Result<Node, OpcUaError> | 用 NamespaceUri + 数字 ID 构造 |
make_string(uri, id) | Result<Node, OpcUaError> | 用 NamespaceUri + 字符串 ID 构造 |
预定义入口属性
为方便, 内置常用入口:
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 标准入口 | root() | Node | R | Address Space 根 (i=84) |
objects() | Node | R | 业务数据根 (i=85) | |
types() | Node | R | 类型定义根 (i=86) | |
views() | Node | R | 视图根 (i=87) | |
server() | Node | R | Server 自身对象 (i=2253) |
let server = s.nodes().server();
println!("Server NodeId = {}", server.node_id());
用法
字符串 NodeId
let nodes = s.nodes();
let temp = nodes.get("ns=2;s=Temperature");
let dv = temp.value()?;
println!("{} = {:?}", temp.node_id(), dv.variant());
用 NamespaceUri 构造 (推荐, 不依赖 Index)
// 数字 NodeId: 自动反查 ns=
let temp = s.nodes().make_numeric("urn:my-company:plc1", 1234)?;
// 字符串 NodeId
let press = s.nodes().make_string("urn:my-company:plc1", "Pressure")?;
namespace URI 不存在时返回
Err(OpcUaError { status: DARRA_INVALID_ARGUMENT, ... }).
Lazy Load 机制
let node = s.nodes().get("ns=2;s=Temperature"); // ← 不触发 RPC
let dv = node.value()?; // ← 第一次 .value() 才触发 Read
第二次访问 .value() 还是会重新 Read (无缓存), 因为变量值随时变. 想缓存自己存变量.
何时用 nodes().get(), 何时用 s.read()
| 场景 | 推荐 |
|---|---|
| 已知精确 NodeId, 单次操作 | s.read("ns=2;s=...") |
| 需要多次访问同一节点的不同属性 | let n = s.nodes().get(...); n.value(); n.display_name(); ... |
| 标准节点 (Server 状态等) | s.nodes().server().child("...") |
| 浏览树 / 写一次性脚本 | s.nodes().get(...).children() |
| 批量 (100+ 节点) | s.read_many(...) / s.browse_many(...), 不要循环 |
跨线程使用
Node 是 Send + Sync, 内部 Arc<SessionInner>. 安全跨线程克隆和使用:
let nodes = s.nodes();
let n1 = nodes.get("ns=2;s=T1");
let n2 = nodes.get("ns=2;s=T2");
let h1 = std::thread::spawn(move || n1.value());
let h2 = std::thread::spawn(move || n2.value());
let v1 = h1.join().unwrap()?;
let v2 = h2.join().unwrap()?;