feat(debugview): DV-2 emit placeholder rows for quiet native alarm bindings
InstanceActor.BuildAlarmStatesSnapshot now adds an IsConfiguredPlaceholder row per configured native source binding that currently has no live condition, so the Debug View tree can show the binding node even when quiet. A binding is "quiet" when no retained AlarmStateChanged carries its NativeSourceCanonicalName (DV-1). Kind derivation: reuses the exact nativeKind value already computed via ResolveNativeKind(nativeSource.ConnectionName) at the NativeAlarmActor creation site and stored in a new _nativeAlarmKinds dictionary -- the accurate per-binding kind (NativeOpcUa vs NativeMxAccess), not the NativeOpcUa default. Tests: Snapshot_QuietNativeBinding_EmitsPlaceholder, Snapshot_NativeBindingWithLiveCondition_NoPlaceholder.
This commit is contained in:
@@ -53,6 +53,13 @@ public class InstanceActor : ReceiveActor
|
||||
private readonly Dictionary<string, IActorRef> _alarmActors = new();
|
||||
private readonly Dictionary<string, IActorRef> _nativeAlarmActors = new();
|
||||
/// <summary>
|
||||
/// Native alarm kind per source-binding canonical name (the same value handed
|
||||
/// to each <see cref="NativeAlarmActor"/>'s <c>_nativeKind</c>). Used to stamp
|
||||
/// the cosmetic kind badge on placeholder rows for quiet bindings in the
|
||||
/// DebugView snapshot.
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, AlarmKind> _nativeAlarmKinds = new();
|
||||
/// <summary>
|
||||
/// Latest enriched <see cref="AlarmStateChanged"/> per alarm name (computed and
|
||||
/// native), so the DebugView snapshot carries the unified condition + native
|
||||
/// metadata rather than a bare State/Priority projection.
|
||||
@@ -1110,6 +1117,27 @@ public class InstanceActor : ReceiveActor
|
||||
_alarmTimestamps.GetValueOrDefault(name, DateTimeOffset.UtcNow)));
|
||||
}
|
||||
|
||||
// Native source bindings with no live condition: emit a placeholder so the
|
||||
// Debug View tree shows the configured binding node even when quiet. A binding
|
||||
// is "quiet" when no retained event carries its canonical name.
|
||||
var liveBindings = _latestAlarmEvents.Values
|
||||
.Where(e => !string.IsNullOrEmpty(e.NativeSourceCanonicalName))
|
||||
.Select(e => e.NativeSourceCanonicalName)
|
||||
.ToHashSet();
|
||||
|
||||
foreach (var binding in _nativeAlarmActors.Keys)
|
||||
{
|
||||
if (liveBindings.Contains(binding)) continue;
|
||||
|
||||
states.Add(new AlarmStateChanged(
|
||||
_instanceUniqueName, binding, AlarmState.Normal, 0, DateTimeOffset.UtcNow)
|
||||
{
|
||||
Kind = _nativeAlarmKinds.GetValueOrDefault(binding, AlarmKind.NativeOpcUa),
|
||||
NativeSourceCanonicalName = binding,
|
||||
IsConfiguredPlaceholder = true
|
||||
});
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
@@ -1468,6 +1496,9 @@ public class InstanceActor : ReceiveActor
|
||||
|
||||
var actorRef = Context.ActorOf(props, $"native-alarm-{nativeSource.CanonicalName}");
|
||||
_nativeAlarmActors[nativeSource.CanonicalName] = actorRef;
|
||||
// Same kind handed to the NativeAlarmActor — used to stamp the
|
||||
// (cosmetic) kind badge on placeholder rows for quiet bindings.
|
||||
_nativeAlarmKinds[nativeSource.CanonicalName] = nativeKind;
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
|
||||
Reference in New Issue
Block a user