feat(client-cli): add ack/confirm/shelve alarm commands with service layer

Adds ConfirmAlarmAsync and ShelveAlarmAsync to IOpcUaClientService and
OpcUaClientService (mirroring the AcknowledgeAlarmAsync pattern: same
CallMethodAsync/ServiceResultException/StatusCode contract). Adds ShelveKind
enum (OneShot/Timed/Unshelve). Adds three new CLI commands — ack, confirm,
shelve — with hex EventId input and per-command argument validation.
Updates both fakes (CLI + UI) to implement the new interface members and
record calls. Adds 16 unit tests covering argument mapping, invalid-input
CommandException paths, bad-status output, and disconnect-in-finally.
This commit is contained in:
Joseph Doherty
2026-06-11 05:46:25 -04:00
parent a6fed85ac9
commit 1f172e55f7
11 changed files with 819 additions and 1 deletions
@@ -103,6 +103,36 @@ public interface IOpcUaClientService : IDisposable
/// </returns>
Task<StatusCode> AcknowledgeAlarmAsync(string conditionNodeId, byte[] eventId, string comment, CancellationToken ct = default);
/// <summary>
/// Confirms an acknowledged condition (Part 9 two-stage acknowledgment) using the event identifier returned by an alarm notification.
/// </summary>
/// <param name="conditionNodeId">The condition node associated with the alarm event being confirmed.</param>
/// <param name="eventId">The event identifier returned by the OPC UA server for the alarm event.</param>
/// <param name="comment">The operator confirmation comment to write with the method call.</param>
/// <param name="ct">The cancellation token that aborts the confirmation request.</param>
/// <returns>
/// <see cref="StatusCodes.Good"/> on success, or the server's bad <see cref="StatusCode"/>
/// (from the underlying <see cref="ServiceResultException"/>) when the confirm call
/// returns a bad result. Other transport-level failures still surface as exceptions.
/// </returns>
Task<StatusCode> ConfirmAlarmAsync(string conditionNodeId, byte[] eventId, string comment, CancellationToken ct = default);
/// <summary>
/// Shelves or unshelves an active alarm condition (OPC UA Part 9 ShelvedStateMachine).
/// </summary>
/// <param name="conditionNodeId">The condition node associated with the alarm being shelved.</param>
/// <param name="kind">The shelve operation: <c>OneShot</c>, <c>Timed</c>, or <c>Unshelve</c>.</param>
/// <param name="shelvingTimeSeconds">
/// For <c>Timed</c> shelving: the shelving duration in seconds. Ignored for <c>OneShot</c> and <c>Unshelve</c>.
/// </param>
/// <param name="ct">The cancellation token that aborts the shelve request.</param>
/// <returns>
/// <see cref="StatusCodes.Good"/> on success, or the server's bad <see cref="StatusCode"/>
/// (from the underlying <see cref="ServiceResultException"/>) when the shelve call
/// returns a bad result. Other transport-level failures still surface as exceptions.
/// </returns>
Task<StatusCode> ShelveAlarmAsync(string conditionNodeId, ShelveKind kind, double shelvingTimeSeconds = 0, CancellationToken ct = default);
/// <summary>
/// Reads raw historical samples for a historized node.
/// </summary>