9cad9ed0fc
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes project bookkeeping IDs (task/tracking refs) from shipped code comments, so the docs read cleanly and CommentChecker is quiet except for known false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc). Doc/comment-only; no logic changed; solution builds clean.
93 lines
4.1 KiB
C#
93 lines
4.1 KiB
C#
using System.Collections.Immutable;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms;
|
|
|
|
/// <summary>
|
|
/// Persistent per-alarm state tracked by the Part 9 state machine. Every field
|
|
/// carried here either participates in the state machine or contributes to the
|
|
/// audit trail required for GxP / 21 CFR Part 11 compliance.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// <see cref="Active"/> is re-derived from the predicate at startup — the engine
|
|
/// runs every alarm's predicate against current tag
|
|
/// values at <c>Load</c>, overriding whatever Active state is in the store.
|
|
/// Every other state field persists verbatim across server restarts so
|
|
/// operators don't re-ack active alarms after an outage + shelved alarms stay
|
|
/// shelved + audit history survives.
|
|
/// </para>
|
|
/// <para>
|
|
/// <see cref="Comments"/> is append-only; comments + ack/confirm user identities
|
|
/// are the audit surface regulators consume. The engine never rewrites past
|
|
/// entries. The runtime type is <see cref="ImmutableList{AlarmComment}"/> so
|
|
/// each append is O(log n) rather than the O(n) copy a plain
|
|
/// <c>IReadOnlyList<AlarmComment></c> would force on every audit-producing
|
|
/// transition.
|
|
/// </para>
|
|
/// </remarks>
|
|
public sealed record AlarmConditionState(
|
|
string AlarmId,
|
|
AlarmEnabledState Enabled,
|
|
AlarmActiveState Active,
|
|
AlarmAckedState Acked,
|
|
AlarmConfirmedState Confirmed,
|
|
ShelvingState Shelving,
|
|
DateTime LastTransitionUtc,
|
|
DateTime? LastActiveUtc,
|
|
DateTime? LastClearedUtc,
|
|
DateTime? LastAckUtc,
|
|
string? LastAckUser,
|
|
string? LastAckComment,
|
|
DateTime? LastConfirmUtc,
|
|
string? LastConfirmUser,
|
|
string? LastConfirmComment,
|
|
ImmutableList<AlarmComment> Comments)
|
|
{
|
|
/// <summary>Initial-load state for a newly registered alarm — everything in the "no-event" position.</summary>
|
|
/// <param name="alarmId">The unique identifier for the alarm.</param>
|
|
/// <param name="nowUtc">The current UTC timestamp.</param>
|
|
/// <returns>A fresh AlarmConditionState with all fields initialized to default/inactive values.</returns>
|
|
public static AlarmConditionState Fresh(string alarmId, DateTime nowUtc) => new(
|
|
AlarmId: alarmId,
|
|
Enabled: AlarmEnabledState.Enabled,
|
|
Active: AlarmActiveState.Inactive,
|
|
Acked: AlarmAckedState.Acknowledged,
|
|
Confirmed: AlarmConfirmedState.Confirmed,
|
|
Shelving: ShelvingState.Unshelved,
|
|
LastTransitionUtc: nowUtc,
|
|
LastActiveUtc: null,
|
|
LastClearedUtc: null,
|
|
LastAckUtc: null,
|
|
LastAckUser: null,
|
|
LastAckComment: null,
|
|
LastConfirmUtc: null,
|
|
LastConfirmUser: null,
|
|
LastConfirmComment: null,
|
|
Comments: ImmutableList<AlarmComment>.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shelving state — kind plus, for <see cref="ShelvingKind.Timed"/>, the UTC
|
|
/// timestamp at which the shelving auto-expires. The engine polls the timer on its
|
|
/// evaluation cadence; callers should not rely on millisecond-precision expiry.
|
|
/// </summary>
|
|
public sealed record ShelvingState(ShelvingKind Kind, DateTime? UnshelveAtUtc)
|
|
{
|
|
public static readonly ShelvingState Unshelved = new(ShelvingKind.Unshelved, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A single append-only audit record — acknowledgement / confirmation / explicit
|
|
/// comment / shelving action. Every entry carries a monotonic UTC timestamp plus the
|
|
/// user identity Phase 6.2 authenticated.
|
|
/// </summary>
|
|
/// <param name="TimestampUtc">When the action happened.</param>
|
|
/// <param name="User">OS / LDAP identity of the actor. For engine-internal events (shelving expiry, startup recovery) this is <c>"system"</c>.</param>
|
|
/// <param name="Kind">Human-readable classification — "Acknowledge", "Confirm", "ShelveOneShot", "ShelveTimed", "Unshelve", "AddComment", "Enable", "Disable", "AutoUnshelve".</param>
|
|
/// <param name="Text">Operator-supplied comment or engine-generated message.</param>
|
|
public sealed record AlarmComment(
|
|
DateTime TimestampUtc,
|
|
string User,
|
|
string Kind,
|
|
string Text);
|