probe: aaAlarmManagedClient receives no alarm data — full consumer chain verified
Sixth probe iteration with every consumer-side knob exhausted: - Subscriptions tried (all rc=0): \Galaxy!, \Galaxy!*, \Galaxy!, \Galaxy!TestArea, \.\Galaxy!. - Read channels polled at 500ms: GetStatistics, GetHighPriAlarm, SFCreateSnapshot + SFGetStatistics. - Filters: priority 0..32767, qtSummary + qtHistory both tried, asAlarmActiveNow. - AlarmRecord pre-init to FILETIME epoch to dodge marshaler bug on default(DateTime). Result: every read API returns empty for the entire 60s window even with TestMachine_001.TestAlarm001 firing every 10s and aaObjectViewer confirming InAlarm transitions. The aaAlarmManagedClient.AlarmClient is not the receive surface AVEVA's alarm pipeline routes to in this Galaxy configuration. The consumer chain is verified working end-to-end: Initialize + Register + Subscribe all succeed, GetProviders finds the provider, the WM 0xC275 heartbeat fires at 1Hz to AVEVA's internal hwnd. There is simply no alarm data flowing through this consumer surface. Next investigation is not consumer-side: either find the SDK aaObjectViewer's alarm panel uses, or query the historian event storage directly. If alarms only flow via the historian path on this customer's Galaxy, the worker's PR A.5 architecture is a dead-end and A.2 needs a different transport. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -258,16 +258,82 @@ 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.
|
||||
## Multi-channel + multi-subscription probe — sixth run, 2026-05-01
|
||||
|
||||
Extended the probe to try every consumer-side approach in
|
||||
parallel:
|
||||
|
||||
- **Subscription expressions** (sequential): `\Galaxy!`,
|
||||
`\Galaxy!*`, `\\Galaxy!`, `\Galaxy!TestArea`, `\\.\Galaxy!`.
|
||||
All Subscribe calls returned rc=0; the last one
|
||||
(`\\.\Galaxy!`) is reflected in `GetProviders` (count=1).
|
||||
- **Read channels** polled at 500ms cadence: `GetStatistics`,
|
||||
`GetHighPriAlarm`, `SFCreateSnapshot` + `SFGetStatistics`.
|
||||
- **Filter+sort**: priority 0..32767, `qtSummary`,
|
||||
state=`asAlarmActiveNow`, sort=`sfReturnNewestFirst`.
|
||||
- **AlarmRecord init** (worked around `Not a valid Win32
|
||||
FileTime` exception): all DateTime fields pre-set to FILETIME
|
||||
epoch (1601-01-01 UTC) before the call, since
|
||||
`default(DateTime)` is outside FILETIME range and trips the
|
||||
interop marshaler.
|
||||
|
||||
Result of the 60s run with `TestMachine_001.TestAlarm001` being
|
||||
flipped every 10s:
|
||||
|
||||
```
|
||||
Subscribe('\Galaxy!') -> 0
|
||||
Subscribe('\Galaxy!*') -> 0
|
||||
Subscribe('\\Galaxy!') -> 0
|
||||
Subscribe('\Galaxy!TestArea') -> 0
|
||||
Subscribe('\\.\Galaxy!') -> 0
|
||||
GetProviders [after Subscribe-multi] -> count=1 list=[ 0 \\.\Galaxy!]
|
||||
GetStatistics #1: total=0 active=0 changes=1 codes=[7] positions=[] handles=[]
|
||||
GetHighPriAlarm #1: rc=0 { }
|
||||
SF channel #1: SFCreate=0 numAlarms=0 SFStats=0 unackRet=0 unackAlm=0 ackAlm=0 others=0 events=0 idxNewest=-1
|
||||
```
|
||||
|
||||
**No further "(changed)" entries for the entire 60s window.**
|
||||
Every read API returned the same empty result on every poll.
|
||||
|
||||
User confirms the alarm IS firing — `aaObjectViewer` sees
|
||||
`$Alarm.InAlarm` flip in lockstep with the script. Historian
|
||||
records exist (per user — needs verification by querying the
|
||||
historian directly).
|
||||
|
||||
## Conclusion of consumer-side probing
|
||||
|
||||
`aaAlarmManagedClient.AlarmClient` is **not** the receive
|
||||
surface AVEVA's alarm pipeline routes to in this Galaxy
|
||||
configuration. The consumer chain is verified end-to-end:
|
||||
|
||||
- `InitializeConsumer` + `RegisterConsumer` + `Subscribe` all
|
||||
succeed (rc=0).
|
||||
- `GetProviders` finds `\Galaxy!` once Initialize is called.
|
||||
- All read APIs (`GetStatistics`, `GetHighPriAlarm`,
|
||||
`SFCreateSnapshot`/`SFGetStatistics`) return empty even with
|
||||
every documented filter combination.
|
||||
- The consumer's hWnd receives zero AVEVA messages between
|
||||
`WM_CREATE` and `WM_DESTROY`; AVEVA's traffic goes to its own
|
||||
internal hwnd.
|
||||
|
||||
The next investigation directions are not consumer-side:
|
||||
|
||||
1. **Inspect `aaObjectViewer`'s alarm SDK** to see what library
|
||||
it uses to read alarms. If different from
|
||||
`aaAlarmManagedClient`, switch the worker over.
|
||||
2. **Query the historian directly** (`aahEventStorage` /
|
||||
`aahEventSvc`) to confirm alarms are recorded — and use the
|
||||
same path for v2 alarm capture.
|
||||
3. **Inspect AVEVA's alarm-routing config** for this Galaxy in
|
||||
System Platform IDE — area assignments, alarm provider
|
||||
bindings, "publish alarm events to" settings on the platform.
|
||||
|
||||
For A.2 implementation: the `aaAlarmManagedClient` path the
|
||||
gateway-worker is currently architected around may be a
|
||||
dead-end on customer Galaxies configured this way. If the
|
||||
alarms truly only flow through the historian event-storage path,
|
||||
A.2 needs to consume from `aahEventStorage` instead — a
|
||||
fundamental architecture pivot.
|
||||
|
||||
### Implications for A.2 implementation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user