using CliFx.Attributes; using CliFx.Infrastructure; using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common; namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli.Commands; /// /// Probes an AB CIP gateway: initialises the driver (connects via libplctag), reads a /// single tag, and prints health + the read result. Fastest way to answer "is the PLC /// up + reachable + speaking CIP via this path?". /// [Command("probe", Description = "Verify the AB CIP gateway is reachable and a sample tag reads.")] public sealed class ProbeCommand : AbCipCommandBase { [CommandOption("tag", 't', Description = "Tag path to probe. ControlLogix default is '@raw_cpu_type' (the canonical libplctag " + "system tag); Micro800 takes a user-supplied global (e.g. '_SYSVA_CLOCK_HOUR').", IsRequired = true)] public string TagPath { get; init; } = default!; [CommandOption("type", Description = "Logix atomic type of the probe tag (default DInt).")] public AbCipDataType DataType { get; init; } = AbCipDataType.DInt; public override async ValueTask ExecuteAsync(IConsole console) { ConfigureLogging(); var ct = console.RegisterCancellationHandler(); var probeTag = new AbCipTagDefinition( Name: "__probe", DeviceHostAddress: Gateway, TagPath: TagPath, DataType: DataType, Writable: false); var options = BuildOptions([probeTag]); await using var driver = new AbCipDriver(options, DriverInstanceId); try { await driver.InitializeAsync("{}", ct); var snapshot = await driver.ReadAsync(["__probe"], ct); var health = driver.GetHealth(); await console.Output.WriteLineAsync($"Gateway: {Gateway}"); await console.Output.WriteLineAsync($"Family: {Family}"); await console.Output.WriteLineAsync($"Health: {health.State}"); if (health.LastError is { } err) await console.Output.WriteLineAsync($"Last error: {err}"); await console.Output.WriteLineAsync(); await console.Output.WriteLineAsync(SnapshotFormatter.Format(TagPath, snapshot[0])); } finally { await driver.ShutdownAsync(CancellationToken.None); } } }