跳到主要内容

read_history (Raw)

pub fn Session::read_history(
&self,
node_id: &str,
start_utc: SystemTime,
end_utc: SystemTime,
max_values: u32,
) -> Result<Vec<DataValue>, OpcUaError>;

最常用的历史读, 返回 [start_utc, end_utc] 区间内全部原始数据点.

前置 / 配套

参数

参数类型说明
node_id&str目标 NodeId
start_utcSystemTime区间起 (UTC)
end_utcSystemTime区间止 (UTC)
max_valuesu32单次返回上限, 0 = 不限

用法

use std::time::{Duration, SystemTime};

let now = SystemTime::now();
let dvs = s.read_history(
"ns=2;s=Temperature",
now - Duration::from_secs(3600),
now,
1000,
)?;

for dv in &dvs {
println!("{:?}: {:?} ({})",
dv.source_timestamp(),
dv.variant().try_get_f64().unwrap_or(0.0),
dv.status());
}

错误

StatusCode含义
BAD_HISTORY_OPERATION_UNSUPPORTED服务端无 Historian
BAD_NOT_READABLE节点无 HistoryRead 权限
BAD_COMMUNICATION_ERROR网络故障
DARRA_INVALID_ARGUMENTnode_id 含 NUL

ContinuationPoint 处理 (内部)

如果数据量大, 服务端可能分多次返回 (ContinuationPoint). SDK 内部已自动循环 HistoryReadNext, 客户端拿到的是合并后的完整列表.


性能与最佳实践

  • 高频数据 (1000 Hz+) 拉一天 = 86 M+ 点 → 必须用 max_values 限制或改用 ReadProcessed 聚合
  • DataValue 实现 Drop, 离开作用域自动释放 native 内存, 不会泄漏
  • 时间戳一律 UTC, 不要传本地时间
{
let dvs = s.read_history("ns=2;s=T", t0, t1, 0)?;
for dv in &dvs {
// 用 dv ...
}
} // <- dvs Vec 离开作用域, 每个 DataValue Drop, native 内存全释放

大区间分批拉

避免一次性拉过多, 自己分小区间循环:

use std::time::{Duration, SystemTime};

let mut cur = start_time;
let chunk = Duration::from_secs(3600); // 1 小时一段
let mut all: Vec<darra_opcua::DataValue> = Vec::new();
while cur < end_time {
let end = (cur + chunk).min(end_time);
let mut batch = s.read_history("ns=2;s=Temperature", cur, end, 100_000)?;
all.append(&mut batch);
cur = end;
}

下一步