diff --git a/docs/plans/alarms-over-gateway.md b/docs/plans/alarms-over-gateway.md index 74b77a7..293954a 100644 --- a/docs/plans/alarms-over-gateway.md +++ b/docs/plans/alarms-over-gateway.md @@ -1,32 +1,62 @@ # Plan — alarms over the mxaccessgw gateway -> ✅ **All 19 PRs merged 2026-04-30 — historical record.** -> A.1 / A.2 / A.3 / A.4 (gateway proto + handlers + worker scaffold), -> B.1 / B.2 / B.3 / B.4 / B.5 (driver, server, docs), C.1 / C.2 -> (sidecar alarm historian writer), D.1 (deploy script), -> E.1 / E.2 / E.3 / E.4 / E.5 / E.6 / E.7 (5 client SDKs + lmxopcua -> client surface). Public contract surface is live; client SDKs ship -> the new RPCs; the sub-attribute fallback path keeps Galaxy alarms -> functional today. +> **17 of 19 PRs merged. Public contract surface and the lmxopcua / +> sidecar consumers are live; four merged PRs ship as scaffolds +> pending worker-side wiring.** Status reconciled against the source +> tree on 2026-05-01. > -> ⚠️ **Worker-side native alarm subscription blocked on a dev-rig -> finding (2026-04-30):** the MXAccess COM Toolkit at -> `C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll` -> exposes no alarm-event family — only `OnDataChange`, -> `OnWriteComplete`, `OperationComplete`, `OnBufferedDataChange`. -> AVEVA's `aaAlarmManagedClient` / `ArchestrAAlarmsAndEvents.SDK` -> assemblies are x64-only and incompatible with the worker's x86 -> bitness. **Operator decision needed before -> `MX_EVENT_FAMILY_ON_ALARM_TRANSITION` carries any events:** either -> accept the value-driven sub-attribute path as the production -> architecture (operator-comment fidelity is the only v1 regression) -> or add an x64 alarm-helper sub-process alongside the worker. See -> `src/MxGateway.Worker/MxAccess/MxAccessAlarmEventSink.cs` in the -> mxaccessgw repo for the architectural notes. Live -> `aahClientManaged` alarm-event write call site -> (`SdkAlarmHistorianWriteBackend` placeholder from PR C.1) and the -> D.1 smoke artifact ship once those decisions resolve. The -> remainder of this document is preserved as the design record. +> **Functional end-to-end today:** B.1 / B.2 / B.3 / B.4 / B.5 +> (EventPump branch, GalaxyDriver `IAlarmSource`, DriverNodeManager +> ack routing, `WonderwareHistorianClient : IAlarmHistorianWriter`, +> docs sweep), C.2 (sidecar wires the alarm-write slot), D.1 script +> (`scripts/install/Refresh-Services.ps1`), E.1 – E.7 (proto regen + +> .NET / Python / Go / Java / Rust SDK alarm methods + lmxopcua client +> surface). The value-driven sub-attribute fallback path keeps Galaxy +> alarms functional today. +> +> **Merged-but-inert scaffolds (gated on worker AlarmClient wiring):** +> +> - **A.2** — `MxAccessAlarmEventSink.Attach` is a no-op; the COM-side +> `aaAlarmManagedClient.AlarmClient` registration / subscription has +> not landed yet, so the gateway's +> `MX_EVENT_FAMILY_ON_ALARM_TRANSITION` is reserved on the wire but +> never emitted. +> - **A.3** AcknowledgeAlarm + **A.4** QueryActiveAlarms — public RPC +> handlers in `MxAccessGatewayService.cs` route through +> `NotWiredAlarmRpcDispatcher` (Ack returns OK with a `worker dispatch +> pending dev-rig wiring` diagnostic; Query yields an empty stream). +> - **C.1** sidecar — `AahClientManagedAlarmEventWriter` exists and the +> IPC slot is wired, but the production backend +> `SdkAlarmHistorianWriteBackend.WriteBatchAsync` returns +> `RetryPlease` for every event with a placeholder log — the live +> `aahClientManaged` SDK call site is pinned during the D.1 dev-rig +> smoke. Effect: scripted-alarm transitions queue locally in +> `SqliteStoreAndForwardSink` and the drain worker repeatedly retries. +> +> **Architectural decision RESOLVED 2026-04-30** (recorded in the +> mxaccessgw repo at `src/MxGateway.Worker/MxAccess/MxAccessAlarmEventSink.cs` +> xmldoc): the worker hosts `aaAlarmManagedClient.AlarmClient` (x86 +> .NET Framework 4.8 — same bitness as the existing MxAccess COM +> consumer) alongside the COM consumer, sharing the worker's STA + +> WM_APP message pump. The discovered API surface +> (`RegisterConsumer`, `Subscribe`, `GetStatistics`, +> `GetAlarmExtendedRec`, `AlarmAckByGUID`) is documented in that +> file's xmldoc. The earlier concern that AVEVA's alarm SDK was +> x64-only proved wrong against the deployed assemblies. What remains +> is wiring PRs in the worker — session-startup `RegisterConsumer` + +> `Subscribe`, an STA WM_APP handler that routes +> alarm-changed messages into `EnqueueTransition`, and the worker +> command path that calls `AlarmAckByGUID` from a gateway +> `AcknowledgeAlarm` RPC. +> +> **D.1 smoke artifact** +> (`docs/plans/artifacts/d1-rollout-YYYY-MM-DD.md`, called for in the +> Track D test plan below) not yet captured — gated on the worker +> AlarmClient wiring being live on the dev rig so the smoke can +> exercise the alarm scenarios end-to-end and pin the +> `SdkAlarmHistorianWriteBackend` SDK entry point. +> +> The remainder of this document is preserved as the design record. Coordinated epic across two repos: