worker: AlarmClientConsumer + transition mapper (PR A.5) #116

Merged
dohertj2 merged 1 commits from track-a5-alarm-consumer-wiring into main 2026-04-30 22:44:52 -04:00
Owner

Summary

Wires the worker-side consumer for AVEVA alarm transitions over the aaAlarmManagedClient API discovered in the foundation PR.

  • IAlarmMgrDataProvider.dll referenced — exposes AlarmRecord + eAlmTransitions / eQueryType / eSortFlags / eAlarmFilterState. Both DLLs load in the worker's existing net48 x86 process; no new bitness boundary.
  • IMxAccessAlarmConsumer abstraction — Subscribe / AcknowledgeByGuid / SnapshotActiveAlarms / AlarmRecordReceived event. Test seam.
  • AlarmClientConsumer production wrapper — RegisterConsumer + Subscribe + AlarmAckByGUID + GetStatistics-based active-alarm walk, all delegated to AlarmClient. Uses AVEVA's managed event surface (GetAlarmChangesCompleted on IAlarmMgrDataProvider) so no Windows message pump is required.
  • AlarmRecordTransitionMapper — pure-function helpers:
    • MapTransitionKind(eAlmTransitions): ALM→Raise, ACK→Acknowledge, RTN→Clear, others (SUB/ENB/DIS/SUP/REL/REMOVE)→Unspecified.
    • ComposeFullReference(provider, group, name): Provider!Group.Name format matching AVEVA's standard syntax.

Pinned during dev-rig validation

  1. Confirm RegisterConsumer accepts hWnd=0 — if it requires a real hwnd, the worker creates a hidden message-only window. The managed event surface should make this irrelevant.
  2. Wire AlarmClientConsumer.AlarmRecordReceived: the AVEVA IAlarmMgrDataProvider.GetAlarmChangesCompleted event needs to be hooked from inside the AlarmClient — find the proper accessor.
  3. AlarmRecord field-by-field translation into the proto event uses MxAccessAlarmEventSink.EnqueueTransition (existing plumbing). Field names (ar_OrigTime, AlarmName, AckOperatorFullName, AckComment) pinned in the preserved discovery dump.

Test plan

  • 127 tests pass (4 new ComposeFullReference cases + 1 Skip-gated discovery probe)
  • Worker builds clean (net48 x86) with the new reference
  • Transition-kind enum mapping is dev-rig-validated rather than unit-tested because the AVEVA assembly is Private=false and isn't copied to the test bin directory.
## Summary Wires the worker-side consumer for AVEVA alarm transitions over the `aaAlarmManagedClient` API discovered in the foundation PR. - **`IAlarmMgrDataProvider.dll` referenced** — exposes `AlarmRecord` + `eAlmTransitions` / `eQueryType` / `eSortFlags` / `eAlarmFilterState`. Both DLLs load in the worker's existing net48 x86 process; no new bitness boundary. - **`IMxAccessAlarmConsumer`** abstraction — `Subscribe` / `AcknowledgeByGuid` / `SnapshotActiveAlarms` / `AlarmRecordReceived` event. Test seam. - **`AlarmClientConsumer`** production wrapper — `RegisterConsumer` + `Subscribe` + `AlarmAckByGUID` + `GetStatistics`-based active-alarm walk, all delegated to `AlarmClient`. Uses AVEVA's managed event surface (`GetAlarmChangesCompleted` on `IAlarmMgrDataProvider`) so **no Windows message pump is required**. - **`AlarmRecordTransitionMapper`** — pure-function helpers: - `MapTransitionKind(eAlmTransitions)`: ALM→Raise, ACK→Acknowledge, RTN→Clear, others (SUB/ENB/DIS/SUP/REL/REMOVE)→Unspecified. - `ComposeFullReference(provider, group, name)`: `Provider!Group.Name` format matching AVEVA's standard syntax. ## Pinned during dev-rig validation 1. Confirm `RegisterConsumer` accepts `hWnd=0` — if it requires a real hwnd, the worker creates a hidden message-only window. The managed event surface should make this irrelevant. 2. Wire `AlarmClientConsumer.AlarmRecordReceived`: the AVEVA `IAlarmMgrDataProvider.GetAlarmChangesCompleted` event needs to be hooked from inside the `AlarmClient` — find the proper accessor. 3. AlarmRecord field-by-field translation into the proto event uses `MxAccessAlarmEventSink.EnqueueTransition` (existing plumbing). Field names (ar_OrigTime, AlarmName, AckOperatorFullName, AckComment) pinned in the preserved discovery dump. ## Test plan - [x] 127 tests pass (4 new `ComposeFullReference` cases + 1 Skip-gated discovery probe) - [x] Worker builds clean (net48 x86) with the new reference - [x] Transition-kind enum mapping is dev-rig-validated rather than unit-tested because the AVEVA assembly is `Private=false` and isn't copied to the test bin directory.
dohertj2 added 1 commit 2026-04-30 22:44:50 -04:00
Wires the worker-side consumer for AVEVA alarm transitions over the
aaAlarmManagedClient API discovered in the prior foundation PR.

- IAlarmMgrDataProvider.dll referenced — exposes AlarmRecord +
  eAlmTransitions / eQueryType / eSortFlags / eAlarmFilterState.
  Both DLLs (aaAlarmManagedClient + IAlarmMgrDataProvider) load in
  the worker's existing net48 x86 process; no new bitness boundary.
- IMxAccessAlarmConsumer abstraction — Subscribe / AcknowledgeByGuid
  / SnapshotActiveAlarms / AlarmRecordReceived event. Test seam.
- AlarmClientConsumer production wrapper — RegisterConsumer +
  Subscribe + AlarmAckByGUID + GetStatistics-based active-alarm
  walk, all delegated to AlarmClient. Uses AVEVA's managed event
  surface (GetAlarmChangesCompleted on IAlarmMgrDataProvider) so
  no Windows message pump is required — plain .NET events arrive
  on the alarm-client's internal callback thread.
- AlarmRecordTransitionMapper — pure-function helpers:
    MapTransitionKind(eAlmTransitions): ALM→Raise, ACK→Acknowledge,
        RTN→Clear, others (SUB/ENB/DIS/SUP/REL/REMOVE)→Unspecified
        so EventPump's decoding-failure counter records them.
    ComposeFullReference(provider, group, name): Provider!Group.Name
        format matching AVEVA's standard alarm-reference syntax.

Pinned during dev-rig validation (subsequent commits):

1. Confirm RegisterConsumer accepts hWnd=0 — if it requires a real
   hwnd, the worker creates a hidden message-only window and
   passes that handle. The managed event surface should make
   this irrelevant but the AVEVA API is older than its managed
   wrapper.
2. Wire AlarmClientConsumer.AlarmRecordReceived: the AVEVA
   IAlarmMgrDataProvider.GetAlarmChangesCompleted event needs to
   be hooked from inside the AlarmClient — find the proper
   accessor (likely a property exposing the inner provider).
3. AlarmRecord field-by-field translation into the proto event
   uses MxAccessAlarmEventSink.EnqueueTransition (existing
   plumbing). The AlarmRecord field names (ar_OrigTime,
   AlarmName, AckOperatorFullName, AckComment, etc.) are
   pinned in the discovery dump preserved in
   AlarmClientDiscoveryTests.

Tests: 127 pass (4 new ComposeFullReference cases + 1 Skip-gated
discovery probe). Transition-kind enum mapping is dev-rig-validated
rather than unit-tested because the AVEVA assembly is Private=false
on the reference and isn't copied to the test bin directory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit c7d5b83390 into main 2026-04-30 22:44:52 -04:00
dohertj2 deleted branch track-a5-alarm-consumer-wiring 2026-04-30 22:44:53 -04:00
Sign in to join this conversation.