- Driver.TwinCAT.Cli-001: TwinCATCommandBase.Validate rejects
non-positive TimeoutMs / IntervalMs and AmsPort outside 1..65535;
ExecuteAsync calls it first.
- Driver.TwinCAT.Cli-002: SubscribeCommand serialises every WriteLine
through a writeLock to remove the notification-callback vs banner
interleave risk.
- Driver.TwinCAT.Cli-003: SubscribeCommand.DescribeMechanism derives
the banner label from the returned ISubscriptionHandle.DiagnosticId
so it can't disagree with what the driver actually did.
- Driver.TwinCAT.Cli-004: introduced TwinCATTagCommandBase carrying
--poll-only + BuildOptions; BrowseCommand stays on the slimmer
TwinCATCommandBase so --poll-only no longer surfaces in browse --help.
- Driver.TwinCAT.Cli-005: ProbeCommand --type now carries the 't' short
alias to match the other commands.
- Driver.TwinCAT.Cli-006: 35 new tests covering Gateway / AmsAddress
parse / BuildOptions / PollOnly / browse-helpers / probe-alias /
mechanism derivation.
- Driver.TwinCAT.Cli-007: replaced the empty-init <inheritdoc/> with an
explicit summary warning future maintainers about the no-op init.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Driver.S7.Cli-004: 'await using var driver' is the sole driver
disposal path; dropped the redundant explicit await ShutdownAsync from
each command's finally.
- Driver.S7.Cli-005: deleted the stale empty
tests/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli.Tests/ directory (the real test
project lives under tests/Drivers/Cli/).
- Driver.S7.Cli-006: S7CommandBaseBuildOptionsTests cover the probe
toggle, timeout mapping, host/port/CPU/rack/slot wiring, and tag list
passthrough.
- Driver.S7.Cli-007: re-added the SubscribeCommand handler comment
explaining the CliFx IConsole.Output usage and that the poll-thread
raises events.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Driver.AbLegacy.Cli-002: WriteCommand.Value description lists the full
true/false, 1/0, on/off, yes/no alias set.
- Driver.AbLegacy.Cli-003: SubscribeCommand serialises every WriteLine
via a per-execution consoleGate lock so the poll-thread OnDataChange
handler can't interleave with the banner.
- Driver.AbLegacy.Cli-004: dropped 'await using var driver' in favour of
a plain 'var driver' + explicit await ShutdownAsync in finally; the
driver is no longer shut down twice.
- Driver.AbLegacy.Cli-005: SubscribeCommand.IntervalMs description
carries the PollGroupEngine 250ms-floor caveat; docs/Driver.AbLegacy.Cli.md
spells out the same.
- Driver.AbLegacy.Cli-006: ProbeCommand --type now carries the short
alias 't' to match the other commands.
- Driver.AbLegacy.Cli-007: BuildOptionsTests cover the probe-disabled,
device-shape, tag-passthrough, timeout-propagation, and empty-tag-list
paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Driver.AbCip.Cli-003: SubscribeCommand prints the 'Subscribed' banner
BEFORE wiring OnDataChange so the main thread can't interleave its
write with the poll-thread handler.
- Driver.AbCip.Cli-004: AbCipCommandBase.Timeout and SubscribeCommand
validate TimeoutMs / IntervalMs and throw CommandException on
non-positive values.
- Driver.AbCip.Cli-005: every command now calls FlushLogging() in its
finally block.
- Driver.AbCip.Cli-006: Timeout init throws NotSupportedException with a
pointer at TimeoutMs instead of silently swallowing assignments.
- Driver.AbCip.Cli-007: added AbCipCommandBaseTests covering BuildOptions
shape, probe / controller-browse / alarm toggles, host address, family
selection, tag list passthrough.
- Driver.AbCip.Cli-008: rewrote the opening paragraph in
docs/Driver.AbCip.Cli.md to credit the six-CLI roster with a pointer
at docs/DriverClis.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the InitializeAsync + ReadAsync body in a try/catch so an unreachable PLC
(refused TCP connect, wrong slot) still prints the structured Host:/CPU:/Health:/
Last error: report from driver.GetHealth() instead of crashing with a stack trace.
OperationCanceledException re-throws so Ctrl+C during connect exits cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trim the --type help text on read and subscribe to the implemented set
(Bool/Byte/Int16/UInt16/Int32/UInt32/Float32) and append a one-line caveat that
Int64, UInt64, Float64, String, and DateTime are not yet implemented and will
return BadNotSupported — so the CLI does not advertise options that cannot succeed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap all numeric/DateTime BCL parses in ParseValue with try/catch(FormatException)
and try/catch(OverflowException) that re-throw as CommandException, matching the
existing Bool path. Update ParseValue_non_numeric_for_numeric_types_throws to assert
CommandException (not FormatException), and add an overflow-edge test (Byte value 256).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reject --region Coils combined with any non-boolean --type with a CommandException
that names the constraint: coils carry a single bit, so only --type Bool is valid.
Without this check a write like "--region Coils --type UInt16 --value 42" would
silently coerce to a coil ON with no diagnostic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add --bit-index, --string-length, and --string-byte-order options to
SubscribeCommand, mirroring ReadCommand, and pass them into ModbusTagDefinition
so that BitInRegister and String type subscriptions use the correct bit index and
string length rather than silently defaulting to bit-0 / zero-length.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WriteCommand.ParseValue wraps FormatException/OverflowException as
CliFx CommandException so a bad --value yields a clean one-line CLI error
naming the value and target type instead of a raw .NET stack trace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Driver.AbCip.Cli-001: WriteCommand.ParseValue wraps FormatException/
OverflowException as CommandException so bad --value input yields a clean
CLI error instead of a raw stack trace.
Driver.AbCip.Cli-002: probe/read/subscribe commands reject Structure types
up front (RejectStructure helper), matching the write guard.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ConfigureLogging is now idempotent via a _loggingConfigured guard field so
repeated calls from subclasses do not abandon and leak the previous logger.
The previous Log.Logger is disposed before overwriting to release its
console-sink resources cleanly.
A new protected static FlushLogging() helper calls Log.CloseAndFlush() so
commands can guarantee buffered output is flushed in their finally blocks
before the process exits — important for the long-running subscribe verb.
XML doc updated to reflect call-once semantics and document FlushLogging().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FormatStatus now matches named codes against code & 0xFFFF0000 (high-word
mask) rather than exact equality, so status codes carrying sub-code or flag
bits in the low 16 bits (e.g. 0x80050001) still resolve to their named class.
For codes not in the named shortlist a severity-class fallback using the top
2 bits always emits Good / Uncertain / Bad rather than bare hex.
Updated the stale FormatStatus_unknown_codes_fall_back_to_hex_only test (its
expectation became invalid once the severity-class fallback was added) and
added new Theory cases exercising both the high-word matching and the
severity-class fallback paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SnapshotFormatter.FormatStatus mapped four OPC UA status names to
incorrect numeric codes, mislabelling operator-facing CLI output. The
codes were corrected to their canonical OPC Foundation
Opc.Ua.StatusCodes values:
BadTimeout 0x80060000 -> 0x800A0000
BadNoCommunication 0x80070000 -> 0x80310000
BadWaitingForInitialData 0x80080000 -> 0x80320000
BadNodeIdInvalid 0x80350000 -> 0x80330000
The Cli.Common project does not reference the Opc.Ua package (only
Core.Abstractions / CliFx / Serilog), so the hex literals were
corrected in place with a sync note rather than adding a heavy new
dependency.
SnapshotFormatterTests was updated: the [Theory] expectations now use
the correct spec codes and assert the full rendered form, plus a new
regression [Theory] confirms the pre-fix wrong names no longer apply.
All 24 tests pass.
findings.md: Driver.Cli.Common-001 set to Resolved; open count 6 -> 5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Group all 69 projects into category subfolders under src/ and tests/ so the
Rider Solution Explorer mirrors the module structure. Folders: Core, Server,
Drivers (with a nested Driver CLIs subfolder), Client, Tooling.
- Move every project folder on disk with git mv (history preserved as renames).
- Recompute relative paths in 57 .csproj files: cross-category ProjectReferences,
the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external
mxaccessgw refs in Driver.Galaxy and its test project.
- Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders.
- Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL,
integration, install).
Build green (0 errors); unit tests pass. Docs left for a separate pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>