64e3fbe035
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public members surfaced by commentchecker — resolves 5,847 of 5,869 issues (99.6%) across three /fixdocs passes.
97 lines
4.5 KiB
C#
97 lines
4.5 KiB
C#
using CliFx.Attributes;
|
|
using CliFx.Exceptions;
|
|
using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli;
|
|
|
|
/// <summary>
|
|
/// Base for every Modbus CLI command. Carries the Modbus-TCP endpoint options
|
|
/// (host / port / unit-id) on top of <see cref="DriverCommandBase"/>'s verbose + timeout
|
|
/// + logging helpers, and exposes <see cref="BuildOptions"/> so each command can turn its
|
|
/// parsed flags into a <see cref="ModbusDriverOptions"/> ready to hand to the driver ctor.
|
|
/// </summary>
|
|
public abstract class ModbusCommandBase : DriverCommandBase
|
|
{
|
|
/// <summary>Gets the Modbus-TCP server hostname or IP address.</summary>
|
|
[CommandOption("host", 'h', Description = "Modbus-TCP server hostname or IP", IsRequired = true)]
|
|
public string Host { get; init; } = default!;
|
|
|
|
/// <summary>Gets the Modbus-TCP port number.</summary>
|
|
[CommandOption("port", 'p', Description = "Modbus-TCP port (default 502)")]
|
|
public int Port { get; init; } = 502;
|
|
|
|
/// <summary>Gets the Modbus unit ID (slave ID).</summary>
|
|
[CommandOption("unit-id", 'U', Description = "Modbus unit / slave ID (1-247, default 1)")]
|
|
public byte UnitId { get; init; } = 1;
|
|
|
|
/// <summary>Gets the per-PDU timeout in milliseconds.</summary>
|
|
[CommandOption("timeout-ms", Description = "Per-PDU timeout in milliseconds (default 2000)")]
|
|
public int TimeoutMs { get; init; } = 2000;
|
|
|
|
/// <summary>Gets a value indicating whether to disable automatic reconnection.</summary>
|
|
[CommandOption("disable-reconnect", Description =
|
|
"Disable the built-in mid-transaction reconnect-and-retry. Matches the driver's " +
|
|
"AutoReconnect=false setting — use when diagnosing socket teardown behaviour.")]
|
|
public bool DisableAutoReconnect { get; init; }
|
|
|
|
/// <inheritdoc />
|
|
public override TimeSpan Timeout
|
|
{
|
|
get => TimeSpan.FromMilliseconds(TimeoutMs);
|
|
init { /* driven by TimeoutMs property; setter required to satisfy base's init contract */ }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a <see cref="ModbusDriverOptions"/> with the endpoint fields this base
|
|
/// collected + whatever <paramref name="tags"/> the subclass declares. Probe is
|
|
/// disabled — CLI runs are one-shot, the probe loop would race the operator's
|
|
/// command against its own keep-alive reads.
|
|
/// </summary>
|
|
/// <param name="tags">The tag definitions to include in the options.</param>
|
|
protected ModbusDriverOptions BuildOptions(IReadOnlyList<ModbusTagDefinition> tags) => new()
|
|
{
|
|
Host = Host,
|
|
Port = Port,
|
|
UnitId = UnitId,
|
|
Timeout = Timeout,
|
|
AutoReconnect = !DisableAutoReconnect,
|
|
Tags = tags,
|
|
Probe = new ModbusProbeOptions { Enabled = false },
|
|
};
|
|
|
|
/// <summary>
|
|
/// Short instance id used in Serilog output so operators running the CLI against
|
|
/// multiple endpoints in parallel can distinguish the logs.
|
|
/// </summary>
|
|
protected string DriverInstanceId => $"modbus-cli-{Host}:{Port}";
|
|
|
|
/// <summary>
|
|
/// Driver.Modbus.Cli-003: validate the endpoint flags at parse time so the operator
|
|
/// gets a clear CliFx error instead of an opaque socket / argument exception thrown
|
|
/// deep inside the driver. Ranges:
|
|
/// <list type="bullet">
|
|
/// <item><c>--port</c>: 1..65535 (IANA TCP port space, excludes the
|
|
/// "any" sentinel 0 and rejects negative / overflowed values).</item>
|
|
/// <item><c>--timeout-ms</c>: strictly positive — a non-positive
|
|
/// <see cref="TimeSpan"/> would propagate as an immediate-timeout into the
|
|
/// driver and surface as a confusing TimeoutException.</item>
|
|
/// <item><c>--unit-id</c>: 1..247 — the Modbus spec unicast unit-id range.
|
|
/// 0 is the broadcast address and not valid for read/write requests; 248-255
|
|
/// are reserved. (Documented in <c>docs/Driver.Modbus.Cli.md</c>.)</item>
|
|
/// </list>
|
|
/// </summary>
|
|
protected void ValidateEndpoint()
|
|
{
|
|
if (Port < 1 || Port > 65535)
|
|
throw new CommandException(
|
|
$"--port must be in 1..65535 (got {Port}).");
|
|
if (TimeoutMs <= 0)
|
|
throw new CommandException(
|
|
$"--timeout-ms must be strictly positive (got {TimeoutMs}).");
|
|
if (UnitId < 1 || UnitId > 247)
|
|
throw new CommandException(
|
|
$"--unit-id must be in 1..247 per the Modbus spec (got {UnitId}); " +
|
|
$"0 is the broadcast address, 248-255 are reserved.");
|
|
}
|
|
}
|