Galaxy native alarm authored by the AdminUI picker (attributeRef tag.Attr) never activates: feed reports Galaxy!Area.tag.Attr #895
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found during the #615 G6 live gate (windev test Galaxy
DEV, mxaccessgw447070a5, 2026-11-12).Symptom. A Galaxy native alarm authored the way the AdminUI Galaxy picker authors it never goes active in OPC UA. The tag
TestMachine_015.TestAlarm003was authored withTagConfig = {"attributeRef":"TestMachine_015.TestAlarm003","alarm":{"alarmType":"OffNormalAlarm","severity":700}}. The alarm was raised in Galaxy and the gateway feed reported itALARM_CONDITION_STATE_ACTIVE. The OPC UA conditionns=2;s=galaxy-windev/dev/TestArea/TestMachine_015/TestAlarm003stayedInactive, Acknowledged, including after a ConditionRefresh.Cause. The gateway alarm feed names an alarm by its provider-qualified reference,
alarmFullReference = "Galaxy!TestArea.TestMachine_015.TestAlarm003", withsourceObjectReference = "TestMachine_015.TestAlarm003".GalaxyDriver.OnAlarmFeedTransitionreverse-mapped onlyAlarmFullReferencethrough the authored attributeRef table (ToRawPath). The picker writes the plaintag.Attrform (RawBrowseCommitMapper:attributeRef= the discovered full name), so the lookup missed, the identity fallback produced a ConditionId that matches no condition, and every transition was dropped. The ack path had the mirror problem: it dialledToAttributeRef(rawPath)=tag.Attr, which the gateway'sAcknowledgeAlarmrefuses as a non-provider reference.The only form that worked was hand-authoring
attributeRef = "Galaxy!<Area>.<tag>.<Attr>"(what the H6 gates did). That form gives up the value read for the same attribute.The unit test
Alarm_ConditionIdIsRawPath_AndAckRoundTripsToAttributeReffed the bare attributeRef asAlarmFullReference, which the real gateway never sends, so CI never exercised the mismatch.Fix (
e113faf5onmaster).ResolveAlarmRawPathmatches the full reference first, thenSourceObjectReference, then the full reference with itsProvider!Area.prefix stripped. A fallback match records the full reference per RawPath.AcknowledgeAsyncdials that learned reference, so the gateway accepts the ack and the #869 confirmation watch matches the feed. Three unit tests were added; the main one fails with the fix reverted.Live re-check after the fix (same run): ConditionRefresh showed
TestAlarm003asActive, Unacknowledged, Severity 750. The OPC UAAcknowledgedialledGalaxy!TestArea.TestMachine_015.TestAlarm003; afterwards Galaxy.Ackedwas True and.AckMsgwas"OtOpcUa #615 G6 gate picker-form (#895) [OPC UA: g6gate, key …]". The clear then arrived asInactive, Acknowledged,Retain=False.Fixed on
masterine113faf5, pushed together with the G6 recordd9b23812.Live-verified on the windev test Galaxy:
TestMachine_015.TestAlarm003wentActive, Unacknowledged.Galaxy!TestArea.TestMachine_015.TestAlarm003..Acked=True.Evidence:
docs/drivers/evidence/galaxy-g6-e2e-2026-11-12.md, Step 6. Left open for the owner to close after review.Independent review of
e113faf5: the fix holds for the case it targets, and I've fixed three gaps in follow-upd5288388(pushed tomaster).What holds
tag.Attr): resolves throughSourceObjectReference, and the ack dials the learnedGalaxy!Area.tag.Attr. I re-checked the mutation: with the call sites reverted toToRawPath/ToAttributeRef,Alarm_PickerAuthoredAttributeRef_…fails.Galaxy!Area.tag.Attrin the current area: matches directly, and the ack sends the authored reference..after!(GatewayAlarmMonitor.TryParseAlarmReference). An area name has no dots, soStripProviderAndAreaagrees with the gateway.GatewayGalaxyAlarmFeed.DispatchSnapshotEntryraises snapshot entries through the sameOnAlarmTransition→OnAlarmFeedTransition→ResolveAlarmRawPathpath. The driver has no separateQueryActiveAlarmsmapping.ConcurrentDictionarykeyed by authored RawPath, so it is bounded by the number of tags. A redeploy that changes the tags builds a new driver instance, which starts with fresh tables.Gaps found and fixed in
d5288388Galaxy!Area1.tag.Attrdropped every transition once Galaxy moved the object, because the feed then namesGalaxy!Area2…and no fallback looked at the authored provider form. Provider-form attributeRefs are now also indexed by their area-freetag.Attr, and the ack dials the new full reference.Galaxy!tag.Attr(AlarmWatchListResolver.ComposeFullReference). Its subtag provider sends only the object (tag) as the source reference. Stripping the area then removedtag.and missed. The part after the!is now tried too.Tests
GalaxyDriverRawPathKeyingTests: re-area for both forms, subtag shapes (area / empty area / null source), H6-style refs (Galaxy!CVDAisle_1.TableAlarms_008.RuntimeAlert, dottedTank1.Level.HiHi), unmatched and malformed refs (no throw, nothing learned), the collision, learning before the subscription is registered, and the #869 confirmation of an unconfirmed picker-form ack by the feed's Acknowledge transition.e113faf5'sGalaxyDriver.cs: 4 fail (re-area hand form, two empty-area shapes, pre-subscription learning).docs/drivers/Galaxy.mdhas been updated.Out of scope: #904. An ack of a picker-form alarm before this driver instance has seen any transition for it still dials the bare
tag.Attr, which the gateway refuses. This can happen right after the host restores conditions from LocalDb and before the feed snapshot arrives. The refusal is visible and the host reverts the ack.No live re-check was run. The change only widens the reverse-map fallbacks, and the live-verified picker path takes the same branch as before.
Closing.