using CliFx.Attributes; using CliFx.Exceptions; using CliFx.Infrastructure; using Opc.Ua; using ZB.MOM.WW.OtOpcUa.Client.Shared; using ZB.MOM.WW.OtOpcUa.Client.Shared.Models; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Commands; [Command("shelve", Description = "Shelve or unshelve an active alarm condition (OPC UA Part 9 ShelvedStateMachine)")] public class ShelveCommand : CommandBase { /// /// Creates the shelve command used to shelve or unshelve an OPC UA alarm condition from the terminal. /// /// The factory that creates the shared client service for the command run. public ShelveCommand(IOpcUaClientServiceFactory factory) : base(factory) { } /// /// Gets the condition node ID of the alarm to shelve or unshelve. /// [CommandOption("node", 'n', Description = "Condition node ID of the alarm to shelve/unshelve", IsRequired = true)] public string NodeId { get; init; } = default!; /// /// Gets the shelve operation kind: OneShot, Timed, or Unshelve. /// [CommandOption("kind", 'k', Description = "Shelve operation: OneShot | Timed | Unshelve", IsRequired = true)] public string Kind { get; init; } = default!; /// /// Gets the shelving duration in seconds for Timed shelving (must be > 0; ignored for OneShot and Unshelve). /// The value is passed in seconds by the operator and converted to milliseconds for the OPC UA TimedShelve call. /// [CommandOption("duration", 'd', Description = "Shelving duration in seconds (must be > 0; in seconds, converted to milliseconds for the OPC UA call; required for --kind Timed)")] public double DurationSeconds { get; init; } /// /// Connects to the server and shelves or unshelves the specified alarm condition. /// /// The CLI console used for output and cancellation handling. public override async ValueTask ExecuteAsync(IConsole console) { ConfigureLogging(); if (!Enum.TryParse(Kind, ignoreCase: true, out var shelveKind)) throw new CommandException( $"Invalid --kind value '{Kind}'. Expected one of: OneShot, Timed, Unshelve."); if (shelveKind == ShelveKind.Timed && DurationSeconds <= 0) throw new CommandException( "--duration must be greater than 0 when --kind is Timed."); IOpcUaClientService? service = null; try { var ct = console.RegisterCancellationHandler(); (service, _) = await CreateServiceAndConnectAsync(ct); var statusCode = await service.ShelveAlarmAsync(NodeId, shelveKind, DurationSeconds, ct); if (StatusCode.IsGood(statusCode)) await console.Output.WriteLineAsync($"{shelveKind} successful: {NodeId}"); else await console.Output.WriteLineAsync($"{shelveKind} failed: {statusCode}"); } finally { if (service != null) { await service.DisconnectAsync(); service.Dispose(); } } } }