diff --git a/docs/AlarmProbeFindings.md b/docs/AlarmProbeFindings.md index 26f74d9..91afcb9 100644 --- a/docs/AlarmProbeFindings.md +++ b/docs/AlarmProbeFindings.md @@ -186,8 +186,14 @@ after-reraise TAG=TestMachine_001.TestAlarm001 GUID=2394FEAA94774154AAA97C3AC Two facts, one confirming and one new. The `ALM → RTN` leg holds its GUID, reconfirming the 2026-05-01 capture against a write-driven rather than script-driven transition. The re-raise -does not: the returned record keeps the old GUID and the new active condition arrives as a -separate record under a fresh one. +does not: the record comes back under a GUID that has never been seen before. + +The two records do **not** coexist — the snapshot carries one record per tag, and the +re-raise replaces the returned record rather than joining it. Both fetches above are the +full `cap=1024` reply, byte-identical in length (1613) at `@COUNT=3`/`elementCount=3`, the +three records being one per `TestMachine_00{1,2,3}`; `72B84A6E…` is simply absent from the +later one. So a single poll spanning the re-raise sees the old GUID disappear and the new +one appear together. That is the correct reading for `ComputeTransitions` rather than a problem for it. The old GUID leaving the active set is a real Clear and the new GUID is a real Raise, because they diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs index 072916a..94e51f7 100644 --- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs +++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs @@ -194,11 +194,13 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer ?? throw new ObjectDisposedException(nameof(WnWrapAlarmConsumer)); // Use the IwwAlarmConsumer (v1) prefix-named methods for the - // lifecycle. Empirically (live dev-rig 2026-05-01) this is the - // only path that lets AlarmAckByName succeed afterwards. The - // v2 Initialize/Register/Subscribe methods on the class - // succeed (return 0) but acks against that consumer state - // return -55. + // lifecycle. Empirically (live dev-rig 2026-05-01, reconfirmed + // 2026-08-18) this is the only path that lets AlarmAckByName + // return rc=0 afterwards. The v2 Initialize/Register/Subscribe + // methods on the class succeed (return 0) but acks against that + // consumer state return -55. Note rc=0 means the call was + // accepted, not that an acknowledgement was applied — see + // AcknowledgeByName below and docs/AlarmProbeFindings.md. int init = com.IwwAlarmConsumer_InitializeConsumer(DefaultApplicationName); if (init != 0) { @@ -345,8 +347,18 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer // Empirically (live dev-rig 2026-05-01): the IwwAlarmConsumer2 // 8-arg AlarmAckByName returns -55 on this AVEVA build (looks like - // a stub). The legacy 6-arg IwwAlarmConsumer.AlarmAckByName works - // and reaches the alarm-history path correctly. Operator-domain + // a stub) and the legacy 6-arg IwwAlarmConsumer.AlarmAckByName + // returns 0, which is why the 6-arg overload is the one called here. + // A zero return is NOT evidence the acknowledgement was applied: the + // 2026-08-18 probe acked a real, freshly raised alarm six ways and + // watched the snapshot stay UNACK_ALM, OPERATOR_NAME stay empty, and + // the alarm extension's own .Acked attribute stay False for 16 s after + // each call. On that rig the ack is accepted and then inert, and the + // -55 tracks the consumer rather than the overload — both overloads + // return -55 against a SetXmlAlarmQuery-applied consumer and 0 against + // the ack-only one. Whether any wnwrap ack reaches the alarm-history + // path is therefore unverified; see docs/AlarmProbeFindings.md. + // Operator-domain // and operator-full-name fields are accepted by the proto contract // for forward-compat but are not propagated to AVEVA today — // wrapped in the 6-arg call so domain/full-name go to the