using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
///
/// Derives a full Part 9 from each native
/// delta, tracking per-condition-NodeId prior state. Owned by the
/// single-threaded DriverHostActor (no locking). Native alarms carry only a transition
/// , not a full state machine, so this is the translation the
/// scripted-alarm engine does internally.
///
public sealed class NativeAlarmProjector
{
private readonly Dictionary _prior = new(StringComparer.Ordinal);
/// Project an alarm transition onto the full condition snapshot for .
/// The materialised condition node's id (the projection's state key).
/// The native alarm transition.
/// The full Part 9 condition snapshot to write to the node.
public AlarmConditionSnapshot Project(string nodeId, AlarmEventArgs e)
{
var prev = _prior.TryGetValue(nodeId, out var p) ? p : (Active: false, Acked: true);
var sev = MapSeverity(e.Severity);
var (active, acked) = e.Kind switch
{
AlarmTransitionKind.Raise or AlarmTransitionKind.Retrigger => (true, false),
AlarmTransitionKind.Acknowledge => (prev.Active, true),
AlarmTransitionKind.Clear => (false, prev.Acked),
_ => (prev.Active, prev.Acked),
};
_prior[nodeId] = (active, acked);
return new AlarmConditionSnapshot(
Active: active, Acknowledged: acked, Confirmed: true, Enabled: true,
Shelving: AlarmShelvingKind.Unshelved, Severity: sev, Message: e.Message);
}
/// Clears all tracked per-node state (call on address-space rebuild).
public void Clear() => _prior.Clear();
private static ushort MapSeverity(AlarmSeverity s) => s switch
{
AlarmSeverity.Low => 200,
AlarmSeverity.Medium => 500,
AlarmSeverity.High => 700,
AlarmSeverity.Critical => 900,
_ => 500,
};
}