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;
///
/// PR abcip-3.2 — pin the device's CIP addressing mode for this CLI invocation.
/// Auto / Symbolic / Logical. Defaults to (resolves
/// to Symbolic until a future PR plumbs auto-detection). Logical against an
/// unsupported family (Micro800) silently falls back to Symbolic with a logged
/// warning, so passing --addressing-mode Logical across a mixed-family
/// fleet is safe.
///
[CommandOption("addressing-mode", Description =
"CIP addressing mode: Auto / Symbolic / Logical (default Auto, resolves to " +
"Symbolic). Logical uses CIP Symbol Object instance IDs after a one-time @tags " +
"walk; unsupported on Micro800 (silent fallback to Symbolic with warning).")]
public AddressingMode AddressingMode { get; init; } = AddressingMode.Auto;
///
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}",
AddressingMode: AddressingMode)],
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}";
}