Propagate alarm events up the full notifier chain so subscribers at any ancestor see them

Previously alarms were only reported to the immediate parent node and the Server node.
Now ReportEventUpNotifierChain walks the full parent chain so clients subscribed at
TestArea see alarms from TestMachine_001, and EventNotifier is set on all ancestors
of alarm-containing nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-28 20:25:55 -04:00
parent d9463d6998
commit 50b9603465
3 changed files with 56 additions and 34 deletions

View File

@@ -67,19 +67,16 @@ After alarm condition nodes are created, `SubscribeAlarmTags` opens MXAccess sub
These subscriptions are opened unconditionally (not ref-counted) because they serve the server's own alarm tracking, not client-initiated monitoring. Tags that do not have corresponding variable nodes in `_tagToVariableNode` are skipped.
## EventNotifier on Parent Nodes
## EventNotifier Propagation
When a Galaxy object contains at least one alarm attribute, its OPC UA node is updated to include `EventNotifiers.SubscribeToEvents`:
When a Galaxy object contains at least one alarm attribute, `EventNotifiers.SubscribeToEvents` is set on the object node **and all its ancestors** up to the root. This allows OPC UA clients to subscribe to events at any level in the hierarchy and receive alarm notifications from all descendants:
```csharp
if (hasAlarms && _nodeMap.TryGetValue(obj.GobjectId, out var objNode))
{
if (objNode is BaseObjectState objState)
objState.EventNotifier = EventNotifiers.SubscribeToEvents;
}
EnableEventNotifierUpChain(objNode);
```
This allows OPC UA clients to subscribe to events on the parent object node and receive alarm notifications for all child attributes. The root `ZB` folder also has `EventNotifiers.SubscribeToEvents` enabled during initial construction.
For example, an alarm on `TestMachine_001.SubObject.Temperature` will be visible to clients subscribed on `SubObject`, `TestMachine_001`, or the root `ZB` folder. The root `ZB` folder also has `EventNotifiers.SubscribeToEvents` enabled during initial construction.
## InAlarm Transition Detection in DispatchLoop
@@ -125,9 +122,7 @@ Key behaviors:
- **Retain** -- `true` while the alarm is active or unacknowledged. This keeps the condition visible in condition refresh responses.
- **Acknowledged state** -- Reset to `false` when the alarm activates, requiring explicit client acknowledgment.
The event is reported through two paths:
1. **Parent node** -- `sourceVar.Parent.ReportEvent` propagates the event to clients subscribed on the parent Galaxy object.
2. **Server node** -- `Server.ReportEvent` ensures clients subscribed at the server level also receive the event.
The event is reported by walking up the notifier chain from the source variable's parent through all ancestor nodes. Each ancestor with `EventNotifier` set receives the event via `ReportEvent`, so clients subscribed at any level in the Galaxy hierarchy see alarm transitions from descendant objects.
## Condition Refresh Override