Files
lmxopcua/docs/DriverClis.md
Joseph Doherty adce4e7727 Task #252 — docs/ index + parent doc for the driver CLI suite
Per-CLI runbooks (Driver.{Modbus,AbCip,AbLegacy,S7,TwinCAT}.Cli.md) shipped
with #249-#251 but docs/README.md's Client tooling table never grew entries
for them and there was no parent doc pulling the suite together.

Adds:
  - docs/DriverClis.md — short parent. Index table, shared-commands callout
    (probe / read / write / subscribe), Driver.Cli.Common infrastructure
    note (what's shared, marginal cost of adding a sixth CLI), typical
    cross-CLI workflows (commissioning, bug reproduction, recipe-write
    validation, byte-order debugging), known gaps that cross-ref the
    per-CLI docs (AB Legacy ab_server upstream gap, S7 PUT/GET enable,
    TwinCAT AMS router, UDT-write refusal), tracking pointer to #249-251.
  - docs/README.md — Client tooling table grows 6 rows (DriverClis parent
    + 5 per-CLI). Also corrects the Client.CLI.md row: it's otopcua-cli,
    not lmxopcua-cli (renamed in #208).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 08:55:17 -04:00

4.4 KiB

Driver test-client CLIs

Five shell-level ad-hoc validation tools, one per native-protocol driver family. Each mirrors the v1 otopcua-cli shape (probe / read / write / subscribe) against the same driver the OtOpcUa server uses — so "does the CLI see it?" and "does the server see it?" are the same question.

CLI Protocol Docs
otopcua-modbus-cli Modbus-TCP Driver.Modbus.Cli.md
otopcua-abcip-cli CIP / EtherNet-IP (Logix symbolic) Driver.AbCip.Cli.md
otopcua-ablegacy-cli PCCC (SLC / MicroLogix / PLC-5) Driver.AbLegacy.Cli.md
otopcua-s7-cli S7comm / ISO-on-TCP Driver.S7.Cli.md
otopcua-twincat-cli Beckhoff ADS Driver.TwinCAT.Cli.md

The OPC UA client CLI lives separately and predates this suite — see Client.CLI.md for otopcua-cli.

Shared commands

Every driver CLI exposes the same four verbs:

  • probe — open a session, read one sentinel tag, print driver health. Fastest "is the device talking?" check.
  • read — synthesise a one-tag driver config from --type / --address (or --tag / --symbol) flags, read once, print the snapshot. No extra config file needed.
  • write — same shape plus --value. Values parse per --type using invariant culture. Booleans accept true / false / 1 / 0 / yes / no / on / off. Writes are non-idempotent by default — a timeout after the device already applied the write will not auto-retry (plan decisions #44, #45).
  • subscribe — long-running data-change stream until Ctrl+C. Uses native push where available (TwinCAT ADS notifications) and falls back to polling (PollGroupEngine) where the protocol has no push (Modbus, AB, S7).

Shared infrastructure

All five CLIs depend on src/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/:

  • DriverCommandBase--verbose + Serilog configuration + the abstract Timeout surface every protocol-specific base overrides with its own default.
  • SnapshotFormatter — consistent output across every CLI: tag / value / status / source-time / server-time for single reads, a 4-column table for batches, Write <tag>: 0x... (Name) for writes, and one line per change event for subscriptions. OPC UA status codes render as 0xXXXXXXXX (Name) with a shortlist for Good / Bad* / Uncertain; unknown codes fall back to hex.

Writing a sixth CLI (hypothetical Galaxy / FOCAS) costs roughly 150 lines: a {Family}CommandBase + four thin command classes that hand their flag values to the already-shipped driver.

Typical cross-CLI workflows

  • Commissioning a new deviceprobe first, then read a known-good tag. If the device is up + talking the protocol, both pass; if the tag is wrong you'll see the read fail with a protocol-specific error.
  • Reproducing a production bugsubscribe to the tag the bug report names, then have the operator run the scenario. You get an HH:mm:ss.fff timeline of exactly when each value changed.
  • Validating a recipe writewrite + read back. If the server's write path would have done anything different, the CLI would have too.
  • Byte-order / word-swap debuggingread with one --byte-order, then the other. The plausible result identifies the correct setting for that device family. (Modbus, S7.)

Known gaps

  • AB Legacy PCCC wire-level against the ab_server Docker simulator is upstream-broken — see the "Known limitations" section in Driver.AbLegacy.Cli.md. Pointing the CLI at real SLC / MicroLogix / PLC-5 hardware or a RSEmulate 500 golden-box works as expected.
  • S7 PUT/GET communication must be enabled in TIA Portal for any S7-1200/1500. See Driver.S7.Cli.md.
  • TwinCAT AMS router must be reachable (local XAR, standalone Router NuGet, or authorised remote route). See Driver.TwinCAT.Cli.md.
  • Structure / UDT writes are refused by the AB CIP + TwinCAT CLIs — whole-UDT writes need a declared member layout that belongs in a real driver config, not a one-shot flag.

Tracking

Tasks #249 / #250 / #251 shipped the suite. 122 unit tests cumulative (16 shared-lib + 106 across the five CLIs) — run dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common.Tests + tests/ZB.MOM.WW.OtOpcUa.Driver.*.Cli.Tests to re-verify.