feat(commons): native alarm core types (AlarmConditionState, NativeAlarmTransition, enums)

This commit is contained in:
Joseph Doherty
2026-05-29 15:39:20 -04:00
parent 09e19db4e9
commit 696da92c3a
6 changed files with 147 additions and 0 deletions
@@ -0,0 +1,24 @@
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms;
/// <summary>
/// Unified, read-only alarm condition state. The OPC UA Part 9 sub-conditions
/// are orthogonal, and MxAccess's ACTIVE / ACTIVE_ACKED / INACTIVE map cleanly
/// onto them, so they are modeled as independent flags plus a 01000 severity.
/// Computed alarms populate this from State + Priority; native alarms mirror it
/// from the source.
/// </summary>
/// <param name="Active">Active vs Inactive.</param>
/// <param name="Acknowledged">Acked vs Unacked.</param>
/// <param name="Confirmed">Confirmed vs Unconfirmed; null when the condition is not confirmable.</param>
/// <param name="Shelve">Shelving sub-state.</param>
/// <param name="Suppressed">Whether the source has suppressed the condition.</param>
/// <param name="Severity">Severity on the unified 01000 scale.</param>
public record AlarmConditionState(
bool Active,
bool Acknowledged,
bool? Confirmed,
AlarmShelveState Shelve,
bool Suppressed,
int Severity);
@@ -0,0 +1,39 @@
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms;
/// <summary>
/// Protocol-neutral alarm transition emitted by an
/// <c>IAlarmSubscribableConnection</c> adapter (OPC UA A&amp;C or MxGateway).
/// Keyed by <see cref="SourceReference"/>; routed to instances by
/// <see cref="SourceObjectReference"/>.
/// </summary>
/// <param name="SourceReference">Stable per-condition key (e.g. "Tank01.Level.HiHi").</param>
/// <param name="SourceObjectReference">Owning source object used for instance routing (e.g. "Tank01").</param>
/// <param name="AlarmTypeName">Source alarm type (e.g. "AnalogLimitAlarm.HiHi").</param>
/// <param name="Kind">Transition classification, incl. snapshot replay sentinels.</param>
/// <param name="Condition">Mirrored condition state.</param>
/// <param name="Category">Source taxonomy/category.</param>
/// <param name="Description">Human-readable description from the source template.</param>
/// <param name="Message">Event message text.</param>
/// <param name="OperatorUser">Operator principal on ack transitions (display-only).</param>
/// <param name="OperatorComment">Operator comment on ack transitions (display-only).</param>
/// <param name="OriginalRaiseTime">When the condition originally became active, if known.</param>
/// <param name="TransitionTime">When this transition occurred.</param>
/// <param name="CurrentValue">Current source value (display-only).</param>
/// <param name="LimitValue">Limit/threshold value for limit alarms (display-only).</param>
public record NativeAlarmTransition(
string SourceReference,
string SourceObjectReference,
string AlarmTypeName,
AlarmTransitionKind Kind,
AlarmConditionState Condition,
string Category,
string Description,
string Message,
string OperatorUser,
string OperatorComment,
DateTimeOffset? OriginalRaiseTime,
DateTimeOffset TransitionTime,
string CurrentValue,
string LimitValue);
@@ -0,0 +1,17 @@
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
/// <summary>
/// Distinguishes how an alarm's state is produced: computed at the site from
/// attribute triggers, or mirrored read-only from a native source.
/// </summary>
public enum AlarmKind
{
/// <summary>Evaluated at the site by an AlarmActor from attribute triggers.</summary>
Computed,
/// <summary>Mirrored from an OPC UA Alarms &amp; Conditions server.</summary>
NativeOpcUa,
/// <summary>Mirrored from the MxAccess Gateway alarm feed.</summary>
NativeMxAccess
}
@@ -0,0 +1,13 @@
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
/// <summary>
/// OPC UA Part 9 shelving sub-state of an alarm condition. Mirrored read-only
/// from the source; computed alarms are always <see cref="Unshelved"/>.
/// </summary>
public enum AlarmShelveState
{
Unshelved,
OneShotShelved,
TimedShelved,
PermanentShelved
}
@@ -0,0 +1,18 @@
namespace ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
/// <summary>
/// Classifies a <c>NativeAlarmTransition</c> emitted by an
/// <c>IAlarmSubscribableConnection</c> adapter. <see cref="Snapshot"/> and
/// <see cref="SnapshotComplete"/> carry the initial active-condition replay
/// produced on every (re)subscribe so consumers can re-seed state.
/// </summary>
public enum AlarmTransitionKind
{
Snapshot,
SnapshotComplete,
Raise,
Acknowledge,
Clear,
Retrigger,
StateChange
}
@@ -0,0 +1,36 @@
using ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
namespace ZB.MOM.WW.ScadaBridge.Commons.Tests.Types.Alarms;
public class AlarmConditionStateTests
{
[Fact]
public void AlarmConditionState_DefaultsAreNormalUnshelved()
{
var s = new AlarmConditionState(
Active: false, Acknowledged: true, Confirmed: null,
Shelve: AlarmShelveState.Unshelved, Suppressed: false, Severity: 0);
Assert.False(s.Active);
Assert.Equal(AlarmShelveState.Unshelved, s.Shelve);
Assert.Equal(0, s.Severity);
}
[Fact]
public void NativeAlarmTransition_CarriesSourceAndCondition()
{
var t = new NativeAlarmTransition(
SourceReference: "Tank01.Level.HiHi", SourceObjectReference: "Tank01",
AlarmTypeName: "AnalogLimitAlarm.HiHi", Kind: AlarmTransitionKind.Raise,
Condition: new AlarmConditionState(true, false, null, AlarmShelveState.Unshelved, false, 800),
Category: "Process", Description: "High level", Message: "level high",
OperatorUser: "", OperatorComment: "",
OriginalRaiseTime: null, TransitionTime: DateTimeOffset.UnixEpoch,
CurrentValue: "92.1", LimitValue: "90");
Assert.Equal("Tank01", t.SourceObjectReference);
Assert.Equal(800, t.Condition.Severity);
Assert.Equal(AlarmTransitionKind.Raise, t.Kind);
}
}