using CliFx.Attributes; using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common; namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli; /// /// Base for every AB CIP CLI command. Carries the libplctag endpoint options /// (--gateway + --family) and exposes so each /// command can synthesise an from CLI flags + its own /// tag list. /// public abstract class AbCipCommandBase : DriverCommandBase { [CommandOption("gateway", 'g', Description = "Canonical AB CIP gateway: ab://host[:port]/cip-path. Port defaults to 44818 " + "(EtherNet/IP). cip-path is family-specific: ControlLogix / CompactLogix need " + "'1,0' to reach slot 0 of the CPU chassis; Micro800 takes an empty path; " + "GuardLogix typically '1,0' same as ControlLogix.", IsRequired = true)] public string Gateway { get; init; } = default!; [CommandOption("family", 'f', Description = "ControlLogix / CompactLogix / Micro800 / GuardLogix (default ControlLogix).")] public AbCipPlcFamily Family { get; init; } = AbCipPlcFamily.ControlLogix; [CommandOption("timeout-ms", Description = "Per-operation timeout in ms (default 5000).")] public int TimeoutMs { get; init; } = 5000; /// public override TimeSpan Timeout { get => TimeSpan.FromMilliseconds(TimeoutMs); init { /* driven by TimeoutMs */ } } /// /// Build an with the device + tag list a subclass /// supplies. Probe + alarm projection are disabled — CLI runs are one-shot; the /// probe loop would race the operator's own reads. /// protected AbCipDriverOptions BuildOptions(IReadOnlyList tags) => new() { Devices = [new AbCipDeviceOptions( HostAddress: Gateway, PlcFamily: Family, DeviceName: $"cli-{Family}")], Tags = tags, Timeout = Timeout, Probe = new AbCipProbeOptions { Enabled = false }, EnableControllerBrowse = false, EnableAlarmProjection = false, }; /// /// Short instance id used in Serilog output so operators running the CLI against /// multiple gateways in parallel can distinguish the logs. /// protected string DriverInstanceId => $"abcip-cli-{Gateway}"; }