From 8ac6642bf81bec0ab8c55c930e0934a2c120b163 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 1 May 2026 07:53:26 -0400 Subject: [PATCH] =?UTF-8?q?probe:=20subscribe-parameter=20sweep=20?= =?UTF-8?q?=E2=80=94=20alarms=20still=20absent,=20producer-side=20blocked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tried every documented subscription knob with InitializeConsumer present + provider visible at status 100: - qtSummary AND qtHistory (the only eQueryType values). - Priority 1..999 AND 0..32767. - FilterMask/Spec asNone AND asAlarmActiveNow. eAlarmFilterState is single-state-valued (asNone=0, asAlarmActiveNow=1, asAlarmAcked=2, asShelved=3), not flag bits, so the filter surface is exhausted. GetStatistics continued to report total=0 active=0 codes=[7] for every poll across all combinations. User confirmation: the BoolAlarm extension on TestMachine_001.TestAlarm001 is evaluating (the $Alarm.InAlarm sub-attribute flips true/false in lockstep with the script writes, visible in aaObjectViewer). So the consumer chain is verified working end-to-end on our side. What's missing is producer-side publication into the aaAlarmManagedClient stream. Probable causes (config, not code): - BoolAlarm extension's "publish to alarm manager" / "Active" / "Enabled" flag may be off. - Alarm-vs-event mode setting may have it routing to events, not alarms. - Platform alarm area may not match the consumer's subscription scope. Resolution path: check the BoolAlarm extension's config in System Platform IDE; check aaObjectViewer's Active Alarms panel (not attribute panel) to see if the alarm appears there. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/AlarmClientDiscovery.md | 33 ++++++++++++++++++ .../AlarmClientWmProbeTests.cs | 34 ++++++++++++++++--- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/docs/AlarmClientDiscovery.md b/docs/AlarmClientDiscovery.md index 24045cd..74b87e5 100644 --- a/docs/AlarmClientDiscovery.md +++ b/docs/AlarmClientDiscovery.md @@ -236,6 +236,39 @@ omits `InitializeConsumer` entirely — that's a bug fix to apply even before A.2 lands, since without it the provider chain never becomes visible. +## Subscribe-parameter sweep — fifth probe run, 2026-05-01 + +Even with `InitializeConsumer` + provider visible at status 100, +no alarm transitions arrived during a 60s window with the user's +script flipping the test bool every 10s. Tried: + +- `qtSummary` and `qtHistory` (the only `eQueryType` values). +- Priority 1..999 and 0..32767. +- `eAlarmFilterState.asNone` and `asAlarmActiveNow` for both + `FilterMask` and `FilterSpecification`. + +`eAlarmFilterState` is single-state-valued (asNone=0, +asAlarmActiveNow=1, asAlarmAcked=2, asShelved=3), not flag bits. +None of these knobs surfaced any alarm activity. + +User confirmation 2026-05-01: the test bool does have a +`BoolAlarm` extension on it; in `aaObjectViewer` the +`$Alarm.InAlarm` sub-attribute flips true/false in lockstep with +the script's writes. So the alarm extension is **evaluating** +its condition, just not visibly producing transitions on the +`aaAlarmManagedClient` consumer stream. + +This isolates the unknown to the producer-side path — whether +the BoolAlarm extension's "publish to alarm manager" knob is on, +whether the platform is in an alarm area that matches the +consumer's subscription scope, or whether AVEVA has a separate +"events" path the BoolAlarm uses by default that this consumer +doesn't subscribe to. Resolving requires checking the BoolAlarm +extension's config in System Platform IDE (alarm priority, +category, "Active"/"Enabled" flags, alarm-vs-event mode) and +checking whether `aaObjectViewer`'s Active Alarms panel sees the +alarm fire. + ### Implications for A.2 implementation The A.2 PR's value is unmeasurable until at least one alarm diff --git a/src/MxGateway.Worker.Tests/AlarmClientWmProbeTests.cs b/src/MxGateway.Worker.Tests/AlarmClientWmProbeTests.cs index 39f1b04..d139583 100644 --- a/src/MxGateway.Worker.Tests/AlarmClientWmProbeTests.cs +++ b/src/MxGateway.Worker.Tests/AlarmClientWmProbeTests.cs @@ -257,14 +257,38 @@ public sealed class AlarmClientWmProbeTests : IDisposable LogProviders(client, "after Register"); + // Dump the eQueryType enum so we can see what alternatives exist + // beyond qtSummary, in case Summary aggregates and we need a + // List/Snapshot mode instead. + try + { + Type qt = typeof(eQueryType); + Log($"eQueryType enum values: " + + string.Join(", ", Enum.GetNames(qt).Select(n => + $"{n}=0x{Convert.ToInt32(Enum.Parse(qt, n)):X}"))); + Type af = typeof(eAlarmFilterState); + Log($"eAlarmFilterState enum values: " + + string.Join(", ", Enum.GetNames(af).Select(n => + $"{n}=0x{Convert.ToInt32(Enum.Parse(af, n)):X}"))); + } + catch (Exception ex) + { + Log($"Enum dump threw: {ex.Message}"); + } + + // qtHistory + state=ActiveNow: stream historical alarm transitions + // including active alarms. asNone for FilterMask/Spec might + // literally mean "match alarms in state 'none'" (i.e., nothing), + // since the eAlarmFilterState enum is 0/1/2/3 single-states not + // flag bits. Try ActiveNow explicitly. int subscribe = client.Subscribe( szSubscription: SubscriptionExpression, - wFromPri: 1, wToPri: 999, - QueryType: eQueryType.qtSummary, + wFromPri: 0, wToPri: short.MaxValue, + QueryType: eQueryType.qtHistory, SortFlags: eSortFlags.sfReturnNewestFirst, - FilterMask: eAlarmFilterState.asNone, - FilterSpecification: eAlarmFilterState.asNone); - Log($"Subscribe('{SubscriptionExpression}') -> {subscribe}"); + FilterMask: eAlarmFilterState.asAlarmActiveNow, + FilterSpecification: eAlarmFilterState.asAlarmActiveNow); + Log($"Subscribe('{SubscriptionExpression}', qtHistory, state=ActiveNow, pri=[0..32767]) -> {subscribe}"); LogProviders(client, "after Subscribe");