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>
96 lines
4.8 KiB
Markdown
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.
|