update_history
往服务端 Historian 写入数据 (而不是当前 read / write 操作的"实时值"):
高敏感操作
HistoryUpdate 多数生产 Server 默认禁止, 需要管理员明确开启 + 合规审计. 详见服务端要求.
签名
pub fn Session::update_history(
&self,
node_id: &str,
update_type: HistoryUpdateType,
values: &[DataValue],
) -> Result<Vec<StatusCode>, OpcUaError>;
返回 Vec<StatusCode> — 每条值的写入状态, 顺序与 values 一致.
HistoryUpdateType
pub enum HistoryUpdateType {
Insert = 1, // 仅当时间点不存在才插入
Replace = 2, // 仅当时间点存在才替换
Update = 3, // Insert + Replace 任一适用 (推荐)
Remove = 4, // 按时间删 (用 DataValue.source_timestamp)
}
用法
补录历史数据
use darra_opcua::HistoryUpdateType;
// 大多数用户从历史 Read 拿到 DataValue 直接转 Update
let dvs = s.read_history(
"ns=2;s=Temperature_Backup",
yesterday, now, 1000,
)?;
let results = s.update_history("ns=2;s=Temperature", HistoryUpdateType::Update, &dvs)?;
for (i, st) in results.iter().enumerate() {
if !st.is_good() {
eprintln!("values[{}] failed: {}", i, st);
}
}
仅插入 (不覆盖已有)
let results = s.update_history("ns=2;s=Temperature", HistoryUpdateType::Insert, &dvs)?;
删除指定时间点
Remove 模式只看每个 DataValue 的 source_timestamp, value 字段被服务端忽略.
简单按区间删建议直接用 delete_history_range 更直观.
权限要求
- 节点
AccessLevelbit 8 (HistoryWrite) 必须置位 - 用户必须有 HistoryUpdate 权限
- 大多数生产 Server 默认禁止, 需要管理员明确开启
错误
| StatusCode | 原因 |
|---|---|
BAD_HISTORY_OPERATION_INVALID | 该节点不支持 HistoryUpdate |
BAD_USER_ACCESS_DENIED | 无权限 |
BAD_ENTRY_EXISTS (Insert 模式) | 该时间点已存在 |
BAD_NO_ENTRY_EXISTS (Replace / Remove 模式) | 该时间点不存在 |
构造 DataValue (高级)
当前 SDK Rust 接口未直接暴露 DataValue 的 public builder
(DataValue::from_raw / wrap_owned 是 crate 内部 API). 要手工构造历史值, 推荐方案:
- 从一个真实历史 Read 拿到
Vec<DataValue>模板, 修改时间戳后回写 - 或在 PLC / 设备侧产生数据, 通过
write实时写入, 让服务端 Historian 自动归档
如果业务必须从程序构造, 给 SDK 提 issue, 后续版本会扩展 DataValue::new(value, status, source_ts) 公共构造器.
错误处理
整体 RPC 失败返回 Err. 单条值失败通过 results[i] 判断:
let results = s.update_history(node_id, HistoryUpdateType::Update, &dvs)?;
let bad = results.iter().filter(|st| !st.is_good()).count();
if bad > 0 {
eprintln!("{}/{} values failed to write", bad, results.len());
}