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] 区间内全部原始数据点.
前置 / 配套
- 高频数据点过多时改用 ReadProcessed 聚合.
- 想要含修改记录请用 ReadModified.
参数
| 参数 | 类型 | 说明 |
|---|---|---|
node_id | &str | 目标 NodeId |
start_utc | SystemTime | 区间起 (UTC) |
end_utc | SystemTime | 区间止 (UTC) |
max_values | u32 | 单次返回上限, 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_ARGUMENT | node_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;
}