using CliFx.Attributes;
using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common;
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli;
///
/// Base for every FOCAS CLI command. Carries the CNC endpoint options
/// (host / port / series) + exposes so each command
/// can synthesise a with one device + one tag.
///
public abstract class FocasCommandBase : DriverCommandBase
{
[CommandOption("cnc-host", 'h', Description =
"CNC IP address or hostname. FOCAS-over-EIP listens on port 8193 by default.",
IsRequired = true)]
public string CncHost { get; init; } = default!;
[CommandOption("cnc-port", 'p', Description = "FOCAS TCP port (default 8193).")]
public int CncPort { get; init; } = 8193;
[CommandOption("series", 's', Description =
"CNC series: Unknown / Zero_i_D / Zero_i_F / Zero_i_MF / Zero_i_TF / Sixteen_i / " +
"Thirty_i / ThirtyOne_i / ThirtyTwo_i / PowerMotion_i (default Unknown).")]
public FocasCncSeries Series { get; init; } = FocasCncSeries.Unknown;
[CommandOption("timeout-ms", Description = "Per-operation timeout in ms (default 2000).")]
public int TimeoutMs { get; init; } = 2000;
///
/// Plan PR F4-d (issue #271) — optional CNC connection-level password emitted
/// via cnc_wrunlockparam on connect. Required only by controllers that
/// gate cnc_wrparam + selected reads behind a password switch.
/// PASSWORD INVARIANT: never logged. The CLI's Serilog config does not
/// include this option in any console / file destructure; the redaction is
/// enforced at the layer (record's
/// overridden ToString).
///
[CommandOption("cnc-password", Description =
"Optional CNC connection password emitted via cnc_wrunlockparam on connect. " +
"Required by controllers that gate parameter writes behind a password switch.")]
public string? CncPassword { get; init; }
///
public override TimeSpan Timeout
{
get => TimeSpan.FromMilliseconds(TimeoutMs);
init { /* driven by TimeoutMs */ }
}
/// Canonical FOCAS host-address string, shape focas://host:port.
protected string HostAddress => $"focas://{CncHost}:{CncPort}";
///
/// Build a with the CNC target this base collected
/// + the tag list a subclass supplies. Probe disabled; the default
/// attempts Fwlib32.dll P/Invoke, which
/// throws at first call when the DLL is absent —
/// surfaced through the driver as BadCommunicationError. Pass
/// = true to bypass the F4-a driver-level
/// write gate for the lifetime of this CLI invocation (issue #268).
///
protected FocasDriverOptions BuildOptions(
IReadOnlyList tags, bool writesEnabled = false) => new()
{
Devices = [new FocasDeviceOptions(
HostAddress: HostAddress,
DeviceName: $"cli-{CncHost}:{CncPort}",
Series: Series,
OverrideParameters: null,
// PR F4-d (issue #271) — thread the CLI's --cnc-password through to
// the driver. Null when the operator didn't supply the flag — the
// driver short-circuits the unlock call in that case.
Password: CncPassword)],
Tags = tags,
Timeout = Timeout,
Probe = new FocasProbeOptions { Enabled = false },
Writes = new FocasWritesOptions { Enabled = writesEnabled },
};
protected string DriverInstanceId => $"focas-cli-{CncHost}:{CncPort}";
}