Gateway historian: raw HistoryRead returns AVEVA synthetic boundary row as a stored sample #687

Closed
opened 2026-10-12 14:20:50 -04:00 by dohertj2 · 1 comment
Owner

Found by the live AVEVA gate (2026-10-12). Pre-existing.

GatewayHistorianDataSource.cs:88-95 / SampleMapper.ToSnapshots map every wire row, including AVEVA's start-boundary row (Quality=133, stamped at the query start, carrying the prior sample's value) and the no-data NULL row (Quality=1, value 0, Bad).

Evidence:

  • Raw [18:06:21, 18:06:39] (no stored sample in the window) returned 18:06:21 v=30 Good (no Interpolated bit) — a value never stored at that time.
  • Raw [18:05:00, 18:05:30] (before the tag's first sample) returned 18:05:00 v=0 Bad instead of an empty result (GoodNoData).
  • A start-only read returns the fabricated row first.

Part 11 Raw with ReturnBounds=false expects stored values only; the boundary row may also skew #669 paging (counted toward the page). Fix: drop the boundary/NULL rows (AVEVA Quality 133 at the query start / Quality 1 no-data — the #681 raw-aggregate reader already distinguishes them) unless ReturnBounds=true, where a boundary value should carry the bound semantics instead. Verify on the VPN.

Found by the live AVEVA gate (2026-10-12). Pre-existing. `GatewayHistorianDataSource.cs:88-95` / `SampleMapper.ToSnapshots` map every wire row, including AVEVA's start-boundary row (`Quality=133`, stamped at the query start, carrying the prior sample's value) and the no-data NULL row (`Quality=1`, value 0, Bad). Evidence: - Raw `[18:06:21, 18:06:39]` (no stored sample in the window) returned `18:06:21 v=30 Good` (no Interpolated bit) — a value never stored at that time. - Raw `[18:05:00, 18:05:30]` (before the tag's first sample) returned `18:05:00 v=0 Bad` instead of an empty result (GoodNoData). - A start-only read returns the fabricated row first. Part 11 Raw with `ReturnBounds=false` expects stored values only; the boundary row may also skew #669 paging (counted toward the page). Fix: drop the boundary/NULL rows (AVEVA `Quality` 133 at the query start / `Quality` 1 no-data — the #681 raw-aggregate reader already distinguishes them) unless `ReturnBounds=true`, where a boundary value should carry the bound semantics instead. Verify on the VPN.
Author
Owner

Fixed on master 1f5d3100 (merge of fix/685-687-688-gateway-mapping).

Raw reads request start − 1 ms (floored at the epoch) and keep only rows in [start, end) (a start == end point read stays inclusive); rows at/before the epoch are never stored samples. Shared helpers with RawAggregateReader (RequestStartFor, IsWindowSample). Budget = N + 16; if pre-window rows use it up, one bounded unclamped re-read. Streams always drained. ⚠️ Client-visible: Gateway forward raw reads now exclude a sample exactly at EndTime (matches the contract and SQL backends).

Live AVEVA gate PASS: no Quality 133 / Quality 1 rows in any raw result; a stored NULL in the window still Bad; start exactly on a sample includes it; EndTime exclusive; StartTime = epoch clean. Follow-ups: #690 (stored NULL returned as value 0), #691 (ReturnBounds).

Fixed on master `1f5d3100` (merge of `fix/685-687-688-gateway-mapping`). Raw reads request `start − 1 ms` (floored at the epoch) and keep only rows in `[start, end)` (a `start == end` point read stays inclusive); rows at/before the epoch are never stored samples. Shared helpers with `RawAggregateReader` (`RequestStartFor`, `IsWindowSample`). Budget = N + 16; if pre-window rows use it up, one bounded unclamped re-read. Streams always drained. ⚠️ Client-visible: Gateway forward raw reads now exclude a sample exactly at EndTime (matches the contract and SQL backends). **Live AVEVA gate PASS:** no Quality 133 / Quality 1 rows in any raw result; a stored NULL in the window still Bad; start exactly on a sample includes it; EndTime exclusive; StartTime = epoch clean. Follow-ups: #690 (stored NULL returned as value 0), #691 (ReturnBounds).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#687