fix(alarms): Severity runs one direction, higher = more urgent; raw priority kept (#129)
AlarmConditionState.Severity mixed two conventions: OPC UA rows carried Part 9 Severity (higher = more severe) while MxGateway native alarms and computed alarms carried a raw AVEVA-style priority (1 = most urgent). Every consumer ranks higher as worse, so Worst Severity, the severity filter/sort and the site event-log Error threshold picked the LEAST urgent MxGateway/computed alarms. - AlarmPriorityBands: the OtOpcUa GalaxyAlarmPriority table (lmxopcua#887, b61f3e05), value for value: 1-250 -> 1000, 251-500 -> 750, 501-750 -> 500, 751-999 -> 250; <= 0 clamps to Critical, > 999 to Low. - MxGatewayAlarmMapper bands the gateway severity (= AVEVA priority); AlarmConditionStateFactory.ForComputed bands PriorityLevel. OPC UA unchanged. - AlarmConditionState gains trailing Priority (int?): the raw source number, exactly the pre-#129 Severity. AlarmStateChanged.Priority and the wire AlarmStateUpdate.priority keep that meaning (no proto change); central derives Severity by kind (SeverityFromPriority), so an older site decodes correctly. - ScriptAlarm gains trailing Priority. The native MES 900-999 band and the MES API Severity/MinSeverity/MaxSeverity key off Priority; rig seed scripts moved from a.Severity to a.Priority, so MES output is unchanged. - AlarmActor raise logs Error when the banded severity >= 700 (same threshold as NativeAlarmActor): priority 1-500 Error, 501+ Warning (was raw >= 700). - NativeAlarmActor upgrades pre-#129 native_alarm_state rows on rehydrate. - Debug snapshot decode restores Condition.Priority from the row's priority. - Docs: Commons, DCL, SiteRuntime, Communication, CentralUI, InboundAPI, HighLevelReqs, MES alarm-status plan, CLAUDE.md. Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
@@ -7,6 +7,7 @@ using ProtoTransitionKind = ZB.MOM.WW.MxGateway.Contracts.Proto.AlarmTransitionK
|
||||
// against the colliding gateway proto enums above.
|
||||
using NativeAlarmTransition = ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms.NativeAlarmTransition;
|
||||
using AlarmConditionState = ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms.AlarmConditionState;
|
||||
using AlarmPriorityBands = ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms.AlarmPriorityBands;
|
||||
using AlarmTransitionKind = ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AlarmTransitionKind;
|
||||
using AlarmShelveState = ZB.MOM.WW.ScadaBridge.Commons.Types.Enums.AlarmShelveState;
|
||||
|
||||
@@ -20,14 +21,35 @@ namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
|
||||
/// </summary>
|
||||
public static class MxGatewayAlarmMapper
|
||||
{
|
||||
/// <summary>Clamps the gateway severity onto the unified 0–1000 scale.</summary>
|
||||
/// <param name="severity">Raw gateway severity value to clamp.</param>
|
||||
/// <returns>The severity clamped to the range [0, 1000].</returns>
|
||||
public static int NormalizeSeverity(int severity) => Math.Clamp(severity, 0, 1000);
|
||||
/// <summary>
|
||||
/// The raw priority kept on <see cref="AlarmConditionState.Priority"/>: the gateway's
|
||||
/// <c>severity</c> field — which mxaccessgw fills from the AVEVA alarm <b>priority</b>
|
||||
/// (1 = most urgent … 999 = least) — clamped to 0–1000, i.e. exactly the value that
|
||||
/// <see cref="AlarmConditionState.Severity"/> carried before Gitea #129. The native MES
|
||||
/// 900–999 band keys off this value, so it must keep selecting the same alarms.
|
||||
/// </summary>
|
||||
/// <param name="rawPriority">The gateway's raw <c>severity</c> field (the AVEVA priority).</param>
|
||||
/// <returns>The priority clamped to the range [0, 1000].</returns>
|
||||
public static int NormalizePriority(int rawPriority) => Math.Clamp(rawPriority, 0, 1000);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the gateway's raw <c>severity</c> field (the AVEVA priority, lower = more urgent) onto the
|
||||
/// unified <see cref="AlarmConditionState.Severity"/> (higher = more urgent) through
|
||||
/// <see cref="AlarmPriorityBands"/> — the same table OtOpcUa applies to the same alarms
|
||||
/// (lmxopcua#887), so the MxGateway and OPC UA paths agree (Gitea #129).
|
||||
/// </summary>
|
||||
/// <param name="rawPriority">The gateway's raw <c>severity</c> field (the AVEVA priority).</param>
|
||||
/// <returns>The banded severity: 1000, 750, 500 or 250.</returns>
|
||||
public static int MapSeverity(int rawPriority) => AlarmPriorityBands.ToSeverity(rawPriority);
|
||||
|
||||
/// <summary>Builds the condition for one gateway alarm: banded Severity + verbatim Priority.</summary>
|
||||
private static AlarmConditionState BuildCondition(bool active, bool acked, int rawPriority) =>
|
||||
new(active, acked, Confirmed: null, Shelve: AlarmShelveState.Unshelved, Suppressed: false,
|
||||
Severity: MapSeverity(rawPriority), Priority: NormalizePriority(rawPriority));
|
||||
|
||||
/// <summary>Maps a gateway condition-state + severity to the unified condition.</summary>
|
||||
/// <param name="state">Gateway proto condition state to map.</param>
|
||||
/// <param name="severity">Raw gateway severity value; normalized to 0–1000.</param>
|
||||
/// <param name="severity">The gateway's raw <c>severity</c> field (the AVEVA priority); banded onto Severity, kept on Priority.</param>
|
||||
/// <returns>The protocol-neutral <see cref="AlarmConditionState"/> equivalent.</returns>
|
||||
public static AlarmConditionState MapConditionState(ProtoConditionState state, int severity)
|
||||
{
|
||||
@@ -38,8 +60,7 @@ public static class MxGatewayAlarmMapper
|
||||
ProtoConditionState.Inactive => (false, true),
|
||||
_ => (false, true)
|
||||
};
|
||||
return new AlarmConditionState(active, acked, Confirmed: null,
|
||||
Shelve: AlarmShelveState.Unshelved, Suppressed: false, Severity: NormalizeSeverity(severity));
|
||||
return BuildCondition(active, acked, severity);
|
||||
}
|
||||
|
||||
/// <summary>Maps a gateway transition kind to the unified transition kind.</summary>
|
||||
@@ -65,8 +86,7 @@ public static class MxGatewayAlarmMapper
|
||||
ProtoTransitionKind.Clear => (false, true),
|
||||
_ => (false, true)
|
||||
};
|
||||
return new AlarmConditionState(active, acked, Confirmed: null,
|
||||
Shelve: AlarmShelveState.Unshelved, Suppressed: false, Severity: NormalizeSeverity(severity));
|
||||
return BuildCondition(active, acked, severity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user