using CliFx; using CliFx.Attributes; using CliFx.Infrastructure; using Opc.Ua; using Opc.Ua.Client; namespace OpcUaCli.Commands; [Command("redundancy", Description = "Read redundancy state from an OPC UA server")] public class RedundancyCommand : ICommand { [CommandOption("url", 'u', Description = "OPC UA server endpoint URL", IsRequired = true)] public string Url { get; init; } = default!; [CommandOption("username", 'U', Description = "Username for authentication")] public string? Username { get; init; } [CommandOption("password", 'P', Description = "Password for authentication")] public string? Password { get; init; } [CommandOption("security", 'S', Description = "Transport security: none, sign, encrypt (default: none)")] public string Security { get; init; } = "none"; [CommandOption("failover-urls", 'F', Description = "Comma-separated failover endpoint URLs for redundancy")] public string? FailoverUrls { get; init; } public async ValueTask ExecuteAsync(IConsole console) { var urls = FailoverUrlParser.Parse(Url, FailoverUrls); using var failover = new OpcUaFailoverHelper(urls, Username, Password, Security); using var session = await failover.ConnectAsync(); // Read RedundancySupport var redundancySupportValue = await session.ReadValueAsync(VariableIds.Server_ServerRedundancy_RedundancySupport); var redundancyMode = (RedundancySupport)(int)redundancySupportValue.Value; await console.Output.WriteLineAsync($"Redundancy Mode: {redundancyMode}"); // Read ServiceLevel var serviceLevelValue = await session.ReadValueAsync(VariableIds.Server_ServiceLevel); var serviceLevel = (byte)serviceLevelValue.Value; await console.Output.WriteLineAsync($"Service Level: {serviceLevel}"); // Read ServerUriArray (only present for non-transparent redundancy) try { var serverUriArrayValue = await session.ReadValueAsync(VariableIds.Server_ServerRedundancy_ServerUriArray); if (serverUriArrayValue.Value is string[] uris && uris.Length > 0) { await console.Output.WriteLineAsync("Server URIs:"); foreach (var uri in uris) { await console.Output.WriteLineAsync($" - {uri}"); } } } catch { // ServerUriArray may not be present when RedundancySupport is None } // Read ServerArray for the local server's ApplicationUri try { var serverArrayValue = await session.ReadValueAsync(VariableIds.Server_ServerArray); if (serverArrayValue.Value is string[] serverArray && serverArray.Length > 0) { await console.Output.WriteLineAsync($"Application URI: {serverArray[0]}"); } } catch { // Informational only } } }