Gateway historian: native TimeAverage/Total rows — leading pre-window row passed through, Uncertain rows lose their value #685

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

Found by the live AVEVA gate (2026-10-12, VPN) for #681/#679/#677. Native TimeAverage/Total on the Gateway backend are also broken by gateway bug historiangw#27 (interval sent 10,000× too large); these two are OtOpcUa's own:

D1 — leading pre-window row. GatewayHistorianDataSource.cs:139-147 + SampleMapper.ToAggregateSnapshots (SampleMapper.cs:96-102) map every row. AVEVA always returns one extra row for the interval BEFORE the window, [start − interval, start). Since #681 stamps rows with the interval start, clients get N+1 values and the first is stamped before StartTime — with a real value when data exists before the window (TimeAverage [18:06:20, 18:07:20) ⇒ first value 18:06:00 22.5 Good), BadNoData otherwise. Part 11/13 expects one result per interval in [Start, End). Fix: drop rows whose interval start is outside the requested window (both directions).

D2 — Uncertain rows lose their value. SampleMapper.cs:85 hasData = OpcQuality >= 192. AVEVA marks an interval containing a NULL/Bad sample opc=64 (Uncertain) and still supplies a value (TWA 3, Integral 30). OtOpcUa maps it to BadNoData, null. Fix: >= 64 ⇒ value with Uncertain (+ Calculated) status.

Also record (docs): AVEVA's TimeWeightedAverage excludes NULL-gap time from numerator and denominator (interval 06:40: 3, Integral 30), while the SQL backends bridge the gap (6.08 Uncertain); extrapolation past the last sample is Good on AVEVA, Uncertain on SQL. Magnitude on all-Good spans matches the SQL backends exactly (sloped). Gate record evidence available on request.

Live re-check needs the VPN and the gateway fix.

Found by the live AVEVA gate (2026-10-12, VPN) for #681/#679/#677. Native `TimeAverage`/`Total` on the Gateway backend are also broken by gateway bug historiangw#27 (interval sent 10,000× too large); these two are OtOpcUa's own: **D1 — leading pre-window row.** `GatewayHistorianDataSource.cs:139-147` + `SampleMapper.ToAggregateSnapshots` (`SampleMapper.cs:96-102`) map every row. AVEVA always returns one extra row for the interval BEFORE the window, `[start − interval, start)`. Since #681 stamps rows with the interval start, clients get N+1 values and the first is stamped before StartTime — with a real value when data exists before the window (`TimeAverage [18:06:20, 18:07:20)` ⇒ first value `18:06:00 22.5 Good`), BadNoData otherwise. Part 11/13 expects one result per interval in `[Start, End)`. Fix: drop rows whose interval start is outside the requested window (both directions). **D2 — Uncertain rows lose their value.** `SampleMapper.cs:85` `hasData = OpcQuality >= 192`. AVEVA marks an interval containing a NULL/Bad sample `opc=64` (Uncertain) and still supplies a value (TWA 3, Integral 30). OtOpcUa maps it to `BadNoData`, null. Fix: `>= 64` ⇒ value with Uncertain (+ Calculated) status. **Also record (docs):** AVEVA's TimeWeightedAverage excludes NULL-gap time from numerator and denominator (interval 06:40: 3, Integral 30), while the SQL backends bridge the gap (6.08 Uncertain); extrapolation past the last sample is Good on AVEVA, Uncertain on SQL. Magnitude on all-Good spans matches the SQL backends exactly (sloped). Gate record evidence available on request. Live re-check needs the VPN and the gateway fix.
Author
Owner

Fixed on master 1f5d3100.

  • D1: native TimeAverage/Total rows whose interval lies outside [min(start,end), max) are dropped after draining the stream.
  • D2: OPC quality 64–191 keeps its value as Uncertain + Calculated (same sub-code as the SQL backends); < 64 stays no-data.
  • Docs: AVEVA's TWA excludes NULL-gap time and doesn't mark extrapolation Uncertain (SQL backends differ).

Live AVEVA gate PASS for both OtOpcUa fixes: pre-window row gone, Uncertain rows keep 13 / 650 (were BadNoData); an all-NULL interval arrives as quality 1 / value 0 ⇒ BadNoData. Per-interval values remain wrong end to end until historiangw#27 lands — re-check tracked in #691.

Fixed on master `1f5d3100`. - D1: native TimeAverage/Total rows whose interval lies outside `[min(start,end), max)` are dropped after draining the stream. - D2: OPC quality 64–191 keeps its value as Uncertain + Calculated (same sub-code as the SQL backends); < 64 stays no-data. - Docs: AVEVA's TWA excludes NULL-gap time and doesn't mark extrapolation Uncertain (SQL backends differ). **Live AVEVA gate PASS** for both OtOpcUa fixes: pre-window row gone, Uncertain rows keep 13 / 650 (were BadNoData); an all-NULL interval arrives as quality 1 / value 0 ⇒ BadNoData. Per-interval values remain wrong end to end until historiangw#27 lands — re-check tracked in #691.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#685