Session 会话 — Session
Session 是 Client 主类, 一个实例对应一个 OPC UA Session. 所有访问 (read / write / browse / subscribe / call / history) 都从这个对象出发.
子页跳转
- 构造与连接参数请参考 构造函数.
- 连接 / 断开请参考 连接管理.
- 单点 / 批量读写请参考 Read / Write.
- 内部事件统一通道请参考 Events.
- 命名空间反查请参考 Namespaces.
- 心跳与会话保活请参考 KeepAlive.
公共字段 / 属性方法
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 连接 | endpoint_url() | &str | R | 构造时指定的 endpoint URL |
handle() | u32 | R | C 层句柄 (内部用) | |
| 状态 | state() | SessionState | R | 当前会话状态 (Disconnected / Connecting / Connected / Reconnecting / Closing / Failed) |
is_connected() | bool | R | 是否已连接 (= state() == Connected) | |
| 子对象 | nodes() | NodeCollection | R | Lazy Load 节点访问器 |
namespaces() | NamespaceCollection | R | 命名空间 URI ↔ Index 互转 | |
| 事件 | events | Arc<Mutex<OpcUaEvents>> | RW | 会话级事件统一通道, 用 .lock() 访问 |
| 配置 | keep_alive_interval_ms() | u32 | R | KeepAlive 心跳周期 (默认 10000 ms, 0 = 禁用) |
set_keep_alive_interval_ms(ms) | () | W | 改心跳周期 (&mut self) | |
auto_publish() | bool | R | 是否启了后台 Publish 线程 | |
set_auto_publish(b) | () | W | 启停后台 Publish 线程 (&mut self) |
公共方法
构造
Session::new(url: &str)— 简化构造 (None 安全, 匿名)Session::with_config(cfg: ConnectionConfig)— 全配置构造 (加密 / Username / 超时全部)
连接管理
connect(&mut self)— 建立连接 (Hello → SecureChannel → Session → Activate)disconnect(&mut self)— 主动断开, 实例可重连Drop(隐式) — 离开作用域自动 disconnect + close
心跳与发布
publish(timeout_ms: u32) -> StatusCode— 手动触发一次 Publish (一般无需调用)
读 / 写
read(&self, node_id) -> Result<DataValue>— 读单节点 Value 属性read_attr(&self, node_id, attr) -> Result<DataValue>— 读单节点指定属性read_many(&self, node_ids, attr) -> Result<Vec<Option<DataValue>>>— 批量读write(&self, node_id, &Variant) -> Result<StatusCode>— 写单节点 Valuewrite_attr(&self, node_id, attr, &Variant) -> Result<StatusCode>— 写指定属性
浏览
browse(&self, node_id, filter)— 单层浏览browse_many(&self, node_ids, filter)— 批量浏览browse_with_paging(&self, node_id, filter)— 含 ContinuationPoint 翻页支持browse_next(&self, cp, release)— 续翻分页browse_all(&self, node_id, filter, max_pages)— 自动循环 BrowseNexttranslate_browse_paths(&self, paths)— 路径批量解析为 NodeIdresolve(&self, path)— 单条绝对路径解析resolve_from(&self, start_node_id, path)— 单条相对路径解析register_nodes(&self, node_ids)— 注册临时高效 NodeIdunregister_nodes(&self, registered_ids)— 注销临时 NodeId
订阅
create_subscription(&self, interval_ms: f64)— 创建数据订阅subscribe_events(&self, node_id, existing, callback)— 订阅事件 (报警 / 条件)transfer_subscriptions(&self, sub_ids, send_initial_values)— 跨 Session 迁移订阅
方法调用
call(&self, object_id, method_id, &[Variant])— 调用 OPC UA Method 节点
历史
read_history(&self, node_id, start, end, max_values)— 读原始历史read_history_modified(...)— 读含修改记录的历史read_history_at_time(...)— 读指定时间点的内插值read_history_processed(...)— 聚合 (Average / Min / Max / TimeAverage / ...)read_history_events(...)— 读历史事件update_history(...)— Insert / Replace / Update / Remove 历史delete_history_range(...)— 按区间删除历史
控制
cancel(&self, request_handle: u32)— 取消未完成请求
完整示例
use opcua::{Session, Variant};
fn main() -> Result<(), Box<dyn std::error::Error>> {
opcua::initialize()?;
let mut s = Session::new("opc.tcp://localhost:4840")?;
s.events.lock().unwrap().on_connected.push(Box::new(|e| {
println!("Connected to {}", e.endpoint_url);
}));
s.events.lock().unwrap().on_disconnected.push(Box::new(|e| {
println!("Disconnected: {}", e.status_code);
}));
s.connect()?;
// 读
let dv = s.read("ns=2;s=Temperature")?;
println!("T = {} °C", dv.variant().try_get_f64().unwrap_or(0.0));
// 写
let mut v = Variant::new();
v.set_f64(42.0);
let st = s.write("ns=2;s=Setpoint", &v)?;
println!("Write status = {}", st);
// 订阅
let sub = s.create_subscription(500.0)?;
sub.add_node("ns=2;s=Counter", |args| {
println!("{:?} = {:?} ({})",
args.node_id, args.value_string, args.status);
})?;
// 方法
let mut a = Variant::new(); a.set_i32(3);
let mut b = Variant::new(); b.set_i32(4);
let outputs = s.call("ns=2;s=Calc", "ns=2;s=Calc.Add", &[a, b])?;
for v in &outputs {
println!("sum = {}", v.try_get_i32().unwrap_or(0));
}
std::thread::sleep(std::time::Duration::from_secs(60));
Ok(()) // s / sub Drop 时自动释放
}