Task #249 — Driver test-client CLIs: shared lib + Modbus CLI first #203
Reference in New Issue
Block a user
Delete Branch "task-249-driver-cli-common-modbus"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Mirrors the v1
otopcua-clivalue prop (ad-hoc shell-level PLC validation) for the Modbus-TCP driver + lays down the shared scaffolding that AB CIP / AB Legacy / S7 / TwinCAT CLIs will inherit.New projects
src/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/—DriverCommandBase(verbose + Serilog) +SnapshotFormatter(single-tag / table / write-result renders).src/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/—otopcua-modbus-cliexe. Commands:probe,read,write,subscribe.Coverage
probe— single FC03 + health pretty-print.read— region × address × type synthesised into one driver tag; supports all Modbus data types incl. Float32/String/BCD + byte-order flags.write— same shape +--valueparsed per--type(invariant culture).subscribe— polled-subscription stream until Ctrl+C.Tests (38 total)
Next
Repeat pattern for AB CIP → AB Legacy → S7 → TwinCAT. Shared base stays as-is unless one exposes a gap.
Mirrors the v1 otopcua-cli value prop (ad-hoc shell-level PLC validation) for the Modbus-TCP driver, and lays down the shared scaffolding that AB CIP, AB Legacy, S7, and TwinCAT CLIs will build on. New projects: - src/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/ — DriverCommandBase (verbose flag + Serilog config) + SnapshotFormatter (single-tag + table + write-result renders with invariant-culture value formatting + OPC UA status-code shortnames + UTC-normalised timestamps). - src/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/ — otopcua-modbus-cli executable. Commands: probe, read, write, subscribe. ModbusCommandBase carries the host/port/unit-id flags + builds ModbusDriverOptions with Probe.Enabled =false (CLI runs are one-shot; driver-internal keep-alive would race). Commands + coverage: - probe single FC03 + GetHealth() + pretty-print - read region × address × type synth into one driver tag - write same shape + --value parsed per --type - subscribe polled-subscription stream until Ctrl+C Tests (38 total): - 16 SnapshotFormatterTests covering: status-code shortnames, unknown codes fall back to hex, null value + timestamp placeholders, bool lowercase, float invariant culture, string quoting, write-result shape, aligned table columns, mismatched-length rejection, UTC normalisation. - 22 Modbus CLI tests: · ReadCommandTests.SynthesiseTagName (5 theory cases) · WriteCommandParseValueTests (17 cases: bool aliases, unknown rejected, Int16 bounds, UInt16/Bcd16 type, Float32/64 invariant culture, String passthrough, BitInRegister, Int32 MinValue, non-numeric reject) Wiring: - ZB.MOM.WW.OtOpcUa.slnx grew 4 entries (2 src + 2 tests). - docs/Driver.Modbus.Cli.md — operator-facing runbook with examples per command + output format + typical workflows. Regression: full-solution build clean; shared-lib tests 16/0, Modbus CLI tests 22/0. Next up: repeat the pattern for AB CIP (shares ~40% more with Modbus via libplctag), then AB Legacy, S7, TwinCAT. The shared base stays as-is unless one of those exposes a gap the Modbus-first pass missed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>