Files
lmxopcua/docs/DriverClis.md
Joseph Doherty 21e0fdd4cd Docs audit — fill gaps so the top-level docs/ reference matches shipped code
Audit of docs/ against src/ surfaced shipped features without current-reference
coverage (FOCAS CLI, Core.Scripting+VirtualTags, Core.ScriptedAlarms,
Core.AlarmHistorian), an out-of-date driver count + capability matrix, ADR-002's
virtual-tag dispatch not reflected in data-path docs, broken cross-references,
and OpcUaServerReqs declaring OPC-020..022 that were never scoped. This commit
closes all of those so operators + integrators can stay inside docs/ without
falling back to v2/implementation/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:42:42 -04:00

96 lines
4.8 KiB
Markdown

# 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](Driver.Modbus.Cli.md) |
| `otopcua-abcip-cli` | CIP / EtherNet-IP (Logix symbolic) | [Driver.AbCip.Cli.md](Driver.AbCip.Cli.md) |
| `otopcua-ablegacy-cli` | PCCC (SLC / MicroLogix / PLC-5) | [Driver.AbLegacy.Cli.md](Driver.AbLegacy.Cli.md) |
| `otopcua-s7-cli` | S7comm / ISO-on-TCP | [Driver.S7.Cli.md](Driver.S7.Cli.md) |
| `otopcua-twincat-cli` | Beckhoff ADS | [Driver.TwinCAT.Cli.md](Driver.TwinCAT.Cli.md) |
| `otopcua-focas-cli` | Fanuc FOCAS/2 (CNC) | [Driver.FOCAS.Cli.md](Driver.FOCAS.Cli.md) |
The OPC UA client CLI lives separately and predates this suite —
see [Client.CLI.md](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, FOCAS).
## Shared infrastructure
All six 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 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** — `probe` 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 bug** — `subscribe` 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 write** — `write` + `read` back. If the server's
write path would have done anything different, the CLI would have too.
- **Byte-order / word-swap debugging** — `read` with 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 surface
`0x803D0000` against 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](Driver.S7.Cli.md).
- **TwinCAT AMS router** must be reachable (local XAR, standalone Router
NuGet, or authorised remote route). See
[Driver.TwinCAT.Cli.md](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 — no CLI-level test
project (hardware-gated). 122 unit tests cumulative across the first five
(16 shared-lib + 106 CLI-specific) — run
`dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common.Tests` +
`tests/ZB.MOM.WW.OtOpcUa.Driver.*.Cli.Tests` to re-verify.