From 30a12dd0fa653291a937eed8a5e375f6bad5d8af Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 12 Nov 2026 12:19:09 -0500 Subject: [PATCH] docs(otopcua-history): #887 Galaxy alarm Severity follows AVEVA priority bands, 1 = most urgent (b61f3e05), consumer impact + ScadaBridge#129 Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi --- .claude/skills/sister-project-history/otopcua.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.claude/skills/sister-project-history/otopcua.md b/.claude/skills/sister-project-history/otopcua.md index f1709c9..cff4efe 100644 --- a/.claude/skills/sister-project-history/otopcua.md +++ b/.claude/skills/sister-project-history/otopcua.md @@ -475,6 +475,14 @@ its Galaxy acks fail against mxaccessgw `2b13564e` did not apply to this box's d `docs/deploy/vd03-upgrade-b8b4c18f-to-master.md` §(h). **Close-out (same day):** `Security:Acl:Enabled` is off on vd03; vd03 ScadaBridge has **no** OPC UA data connection to OtOpcUa (only `MxGateway` → `localhost:5120`), so none of the FOCAS changes reach ScadaBridge there; rollback of `data\` is compatible (LocalDb 0.3.4 both sides, additive `alarm_condition_comment` table, 0 scripted-alarm rows). Record §(h) close-out bullet. +- **2026-11-12 master `b61f3e05` (#887, not deployed): Galaxy alarm Severity now ranks AVEVA priority 1 as the most urgent, live and in history.** `GalaxyAlarmPriority` is the one table used by both live Galaxy alarms (`MxAccessSeverityMapper`, which reads the priority mxaccessgw sends as `severity`) and AVEVA A&E history (`EventMapper`, #886). It used to rank a higher number as more severe. It now uses AVEVA's default ranges: **1–250 → 1000 (Critical), 251–500 → 750 (High), 501–750 → 500 (Medium), 751–999 → 250 (Low)**. Out-of-range values clamp: 0 or below reads Critical, above 999 reads Low. History rows with AVEVA `severity` 0 (`System.*`, `User.*`: not alarms) read **1**. + - **Live now matches history numerically.** `GalaxyDriver` sets `AlarmEventArgs.OpcUaSeverity`. Before, it passed only the bucket, so the host re-mapped it to 200/500/700/900 while history said 250/500/750/1000. + - **Evidence:** vd03 `Runtime.dbo.Events` (read-only SQL) shows priority 1/100 → AVEVA severity 1, 400/500 → 2, 600/700 → 3, and 999 non-alarms → 0. + - **Live #801/#886 harness re-run:** vd03 HistorianGateway `ea9f21c`, read-only, no WinRM. 224 of 233 cases are identical; the other 9 differ only in Severity (priority-700 rows 750 → 500, 19 system/user events 1000 → 1). Record: OtOpcUa `docs/plans/evidence/2026-11-10-opcua2/aveva-history-801.md` § "#887 re-run". + - **Client-visible:** every OPC UA client that ranks, filters or colours Galaxy alarms by Severity sees the order reversed, both live and in HistoryReadEvents. + - **ScadaBridge consumer impact: no code change needed for this fix.** ScadaBridge consumes Galaxy-via-OtOpcUa through `OpcUaAlarmMapper` and `NativeAlarmActor`. Its consumers already read a higher Severity as worse (`ErrorSeverityThreshold = 700`; Alarm Summary takes the max as worst and filters with `>= min`), so this fix makes that path right. Nothing depended on the inverted values. No deployed ScadaBridge reads Galaxy alarms via OtOpcUa: vd03 ScadaBridge has no OPC UA link to OtOpcUa, and vd03 OtOpcUa has no Galaxy driver. + - **ScadaBridge's own MxGateway adapter (which bypasses OtOpcUa) is not consistent.** `MxGatewayAlarmMapper` clamps the raw AVEVA **priority** into `Severity` (lower = more urgent), and computed alarms do the same with `PriorityLevel`, so those rows rank backwards in the higher-is-worse consumers. The native **MES 900–999 band** is set on the Galaxy priority, so it works only on that MxGateway path. Over OtOpcUa it never matched, before or after #887. It is also AVEVA's Low band. Filed as **ScadaBridge#129** (owner decision: one Severity direction, and where the native MES flag lives). + - **2026-11-12 master `b27b5b9c` (#881, not deployed): `HistoryServerCapabilities` Booleans now follow the wired historian backend.** Every flag used to read false (the SDK default), so a client that follows the spec skipped HistoryRead. Each backend now declares its capabilities: `IHistorianDataSource.ReadCapabilities` and `IHistorianDataUpdater.Capabilities` (a required member). The server advertises those declarations and also enforces them at dispatch. - **Gateway (default):** `AccessHistoryData`/`AccessHistoryEvents` true, everything else false. - **SqlServer / QuestDb:** those two plus `ServerTimestampSupported` and Insert/Replace/UpdateData, DeleteRaw and DeleteAtTime true (QuestDb deletes are tombstones).