Files
lmxopcua/scripts/validation/aveva-history-801/README.md
T
Joseph Doherty f607ee7502 test(historian): #801 real-AVEVA history gate over the SDK wire (env-gated)
AvevaGatewayHistoryLiveGateTests boots the server in-process, wires the production
Gateway backend (HistorianBackendRegistry -> GatewayHistorianDataSource) to a real
HistorianGateway and drives HistoryRead over a real SDK session: raw (all, paged,
reverse, bounds), modified, the ten served aggregates and seven refused ones, AtTime,
events (all, 1-event pages, reverse), a missing tag, HistoryServerCapabilities and
node metadata, and a HistoryUpdate that must be refused (sandbox-bound node only).
Every wire answer is compared with the backend's direct answer; the run is dumped as
JSON for cross-SDK and SQL comparison. Skips unless HISTGW_GATEWAY_ENDPOINT and
HISTGW_GATEWAY_APIKEY are set; read-only by construction.

scripts/validation/aveva-history-801: run/compare instructions, the SDK 1.5.378
baseline port patch (API spelling only), and the diff / SQL / aggregate / histgw-cli
comparison scripts.

Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
2026-11-12 10:02:21 -05:00

45 lines
2.7 KiB
Markdown

# #801 real-AVEVA history gate (SDK 2.0.1 vs 1.5.378.182)
Harness: `tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/AvevaGatewayHistoryLiveGateTests.cs`.
It boots the OtOpcUa server in-process (`ServerEventRig`), wires the **production** Gateway backend
(`HistorianBackendRegistry` → `GatewayHistorianDataSource`) to a real HistorianGateway, and drives HistoryRead /
HistoryUpdate over a real SDK client session. It skips unless `HISTGW_GATEWAY_ENDPOINT` and `HISTGW_GATEWAY_APIKEY`
are set. It is read-only: the Gateway backend has no updater, and the only HistoryUpdate goes to a node bound to
`HISTGW_WRITE_SANDBOX_TAG` and is refused by the server before any backend call.
Record of the 2026-11-12 run: [`docs/plans/evidence/2026-11-10-opcua2/aveva-history-801.md`](../../../docs/plans/evidence/2026-11-10-opcua2/aveva-history-801.md).
## Run (SDK 2, this tree)
```bash
export HISTGW_GATEWAY_ENDPOINT=http://wonder-app-vd03.zmr.zimmer.com:5221
export HISTGW_GATEWAY_APIKEY="$(cat /path/to/key-file)" # never on the command line
export HISTGW_WRITE_SANDBOX_TAG=HistGW.LiveTest.Sandbox
export OTOPCUA_AVEVA_GATE_OUT=/tmp/aveva-gate OTOPCUA_AVEVA_GATE_LABEL=sdk2-$(git rev-parse --short HEAD)
dotnet test tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests -c Release \
--filter "FullyQualifiedName~AvevaGatewayHistoryLiveGate"
```
## Baseline (SDK 1.5.378.182)
```bash
git worktree add --detach ../otopcua-sdk1 efb9197a # master's first parent before the SDK 2 merge b36e688f
cp tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/AvevaGatewayHistoryLiveGateTests.cs \
../otopcua-sdk1/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/
(cd ../otopcua-sdk1 && patch -p1 < "$OLDPWD/scripts/validation/aveva-history-801/sdk1-baseline-port.patch")
# then the same dotnet test command in ../otopcua-sdk1 with OTOPCUA_AVEVA_GATE_LABEL=sdk1-efb9197a
```
`sdk1-baseline-port.patch` changes only SDK API spelling: collections in place of `ArrayOf`, `byte[]` in place of `ByteString`,
`DataValue.Value` in place of `ClrValue()`. The queries, windows and comparisons are unchanged.
## Compare
```bash
python3 -I diff_runs.py $OUT/aveva-gate-sdk2-*.json $OUT/aveva-gate-sdk1-efb9197a.json # every case, row and event
python3 -I sql_raw_check.py $OUT/aveva-gate-sdk2-*.json # raw rows vs Runtime.dbo.History (Full, UTC); needs
# HISTORIAN_SQL_USER / HISTORIAN_SQL_PASSWORD, read-only
python3 -I aggregate_recompute.py $OUT/aveva-gate-sdk2-*.json # simple aggregates recomputed from the raw rows
python3 -I hgcli_raw_check.py $OUT/aveva-gate-sdk2-*.json $OUT # vs histgw-cli read-raw output (hgcli-<tag>-<date>.jsonl)
```