5.1 KiB
Driver test-client CLIs
Six 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 |
otopcua-focas-cli |
Fanuc FOCAS/2 (CNC) | Driver.FOCAS.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--typeusing invariant culture. Booleans accepttrue/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, FOCAS).
The TwinCAT CLI adds a fifth verb, browse — it walks the controller's
symbol table via the driver's DiscoverAsync path and prints every symbol the
atomic-type mapper recognises. No other driver CLI ships browse.
Shared infrastructure
All six CLIs depend on src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/:
DriverCommandBase—--verbose+ Serilog configuration + the abstractTimeoutsurface 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 as0xXXXXXXXX (Name)with a shortlist forGood/Bad*/Uncertain; unknown codes fall back to hex.
Writing a seventh CLI (hypothetical Galaxy / OPC UA Client) 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 device —
probefirst, thenreada 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 bug —
subscribeto 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 write —
write+readback. If the server's write path would have done anything different, the CLI would have too. - Byte-order / word-swap debugging —
readwith one--byte-order, then the other. The plausible result identifies the correct setting for that device family. (Modbus, S7.)
Known gaps
- AB Legacy cip-path quirk — libplctag's ab_server requires a
non-empty CIP routing path before forwarding to the PCCC dispatcher.
Pass
--gateway "ab://127.0.0.1:44818/1,0"against the Docker fixture; real SLC / MicroLogix / PLC-5 hardware accepts an empty path (ab://host:44818/). Bit-file writes (B3:0/5) still surface0x803D0000against ab_server — route operator-critical bit writes to real hardware until upstream fixes this. - 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 original five. The FOCAS CLI followed
alongside the Tier-C isolation work on task #220. Every CLI — FOCAS included —
ships its own unit-test project under tests/Drivers/Cli/, alongside the shared
tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common.Tests. Re-verify with
dotnet test tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common.Tests and
each per-family tests/Drivers/Cli/...Cli.Tests project.