feat(alarms): exact OPC UA severity + per-condition quality on native alarm events (#626)
AlarmEventArgs gains optional OpcUaSeverity (supersedes the four-bucket mapping, clamped 1..1000) and QualityStatusCode (projected onto the condition's Quality). An Unspecified-kind event carrying a quality is a quality-only annotation: the host updates the condition but publishes no alerts row. Both default null, so every existing native source is unchanged. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -3,7 +3,8 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
/// <summary>
|
||||
/// Driver capability for alarm events. Optional — only drivers whose backends expose
|
||||
/// alarm conditions implement this. Currently: Galaxy (MxAccess alarms), FOCAS
|
||||
/// (CNC alarms), OPC UA Client (A&C events from upstream server).
|
||||
/// (CNC alarms), OPC UA Client (A&C events from upstream server), MTConnect
|
||||
/// (CONDITION data items, Gitea #626).
|
||||
/// </summary>
|
||||
public interface IAlarmSource
|
||||
{
|
||||
@@ -85,6 +86,22 @@ public sealed record AlarmAcknowledgeRequest(
|
||||
/// other fields. <see cref="AlarmTransitionKind.Unspecified"/> when the upstream
|
||||
/// path doesn't surface a distinct kind.
|
||||
/// </param>
|
||||
/// <param name="OpcUaSeverity">
|
||||
/// Optional exact OPC UA severity (1..1000) for a source whose own scale is finer than the four
|
||||
/// <see cref="AlarmSeverity"/> buckets (Gitea #626: MTConnect Warning = 500, Fault = 800). When set it
|
||||
/// supersedes the bucket on the projected Part 9 condition (clamped to 1..1000); <c>null</c> — every
|
||||
/// pre-#626 source — keeps the bucket mapping. <see cref="Severity"/> must still carry the nearest
|
||||
/// bucket for consumers that only read the bucket.
|
||||
/// </param>
|
||||
/// <param name="QualityStatusCode">
|
||||
/// Optional status code of the condition's SOURCE data (Part 9 <c>ConditionType.Quality</c>), for a
|
||||
/// source that can report "no value for this condition" per alarm rather than per connection (Gitea
|
||||
/// #626: MTConnect <c>Unavailable</c>). <c>null</c> keeps the pre-#626 behaviour (projected Good;
|
||||
/// driver-wide comms loss is annotated separately by the host). An event whose <see cref="Kind"/> is
|
||||
/// <see cref="AlarmTransitionKind.Unspecified"/> and which carries a quality is a
|
||||
/// <b>quality-only annotation</b> (<see cref="IsQualityOnly"/>): the host updates the condition's
|
||||
/// Quality without touching its Active/Acked state and publishes no <c>alerts</c> row for it.
|
||||
/// </param>
|
||||
public sealed record AlarmEventArgs(
|
||||
IAlarmSubscriptionHandle SubscriptionHandle,
|
||||
string SourceNodeId,
|
||||
@@ -96,7 +113,17 @@ public sealed record AlarmEventArgs(
|
||||
string? OperatorComment = null,
|
||||
DateTime? OriginalRaiseTimestampUtc = null,
|
||||
string? AlarmCategory = null,
|
||||
AlarmTransitionKind Kind = AlarmTransitionKind.Unspecified);
|
||||
AlarmTransitionKind Kind = AlarmTransitionKind.Unspecified,
|
||||
int? OpcUaSeverity = null,
|
||||
uint? QualityStatusCode = null)
|
||||
{
|
||||
/// <summary>
|
||||
/// True when this event only re-annotates the condition's source-data quality — a
|
||||
/// <see cref="QualityStatusCode"/> with an <see cref="AlarmTransitionKind.Unspecified"/> kind. No
|
||||
/// alarm-state change happened, so the host must not publish it as an alarm transition.
|
||||
/// </summary>
|
||||
public bool IsQualityOnly => Kind == AlarmTransitionKind.Unspecified && QualityStatusCode is not null;
|
||||
}
|
||||
|
||||
/// <summary>Mirrors the <c>NodePermissions</c> alarm-severity enum in <c>docs/v2/acl-design.md</c>.</summary>
|
||||
public enum AlarmSeverity { Low, Medium, High, Critical }
|
||||
|
||||
Reference in New Issue
Block a user