历史流式读
概述
IDE 趋势图拉历史时, 一次性把万点装进 std::vector 会让进程卡顿 + OOM。ReadHistoryStream 用 callback / coroutine 模式, 业务侧拿一条处理一条。
对应规范段: Part 11 §6.5。
API
| 方法 | 类别 | 读写 | 说明 |
|---|---|---|---|
| ua.ReadHistoryStream(nodeId, t0, t1, batch_size, on_value) | 历史 | 读 | 异步流式读, 每条调一次 callback |
代码示例
#include <darra/opcua.h>
using namespace darra::opcua;
using namespace std::chrono;
DarraOpcUa ua("opc.tcp://localhost:4840");
ua.Connect();
auto t1 = system_clock::now();
auto t0 = t1 - hours(24);
// 1) 边拉边渲染
ua.ReadHistoryStream("ns=2;s=Temp", t0, t1, /*batch_size=*/1000,
[&](const DataValue& dv) {
chartSeries->AddPoint(dv.source_timestamp, dv.value.AsDouble());
});
// 2) 取消支持 (返回 false 提前退出)
ua.ReadHistoryStream("ns=2;s=Temp", t0, t1, 1000,
[&](const DataValue& dv) -> bool {
if (cancel_requested.load()) return false;
Process(dv);
return true;
});
// 3) 计数坏值
size_t bad = 0;
ua.ReadHistoryStream("ns=2;s=Temp", t0, t1, 1000,
[&](const DataValue& dv) {
if (dv.status != StatusCode::Good) ++bad;
});
std::cout << "24h 内 " << bad << " 个坏值\n";
实现限制
- 当前底层 ReadHistory 不暴露 ContinuationPoint, 一次 RPC 返回区间内所有点 (受 batch_size 限)
- 大区间业务侧自行切片
- callback 返回 false 立即退出
最佳实践
- callback 内部不要做长操作 (>10 ms), 不然阻塞读取
- 区间 > 1 小时建议外层切片
- UI 渲染节流: 累积 100 条再 refresh
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| ReadHistoryStreamAsync | read_history_stream | readHistoryStream | ReadHistoryStream | read_history_stream | DarraUa_Session_ReadHistoryStream |