跳到主要内容

NodeCollection — s.nodes()

NodeCollection 是 Session 的节点访问入口, 通过 get(node_id) 返回 Node 包装对象, 不立即触发 RPC (Lazy Load).

前置阅读

入口方法

方法返回说明
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()NodeRAddress Space 根 (i=84)
objects()NodeR业务数据根 (i=85)
types()NodeR类型定义根 (i=86)
views()NodeR视图根 (i=87)
server()NodeRServer 自身对象 (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(...), 不要循环

跨线程使用

NodeSend + 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()?;

下一步