Task #251 — S7 + TwinCAT test-client CLIs (driver CLI suite complete) #205

Merged
dohertj2 merged 1 commits from task-251-s7-twincat-cli into v2 2026-04-21 08:47:05 -04:00
Owner

Final two of the five driver test clients. Closes out the #249#250#251 track.

otopcua-s7-cli

S7comm / ISO-on-TCP 102 against S7-300/400/1200/1500. All S7 data types incl. DateTime round-trip + bit/word/dword DB addressing. Documents the PUT/GET-must-be-enabled gotcha.

otopcua-twincat-cli

ADS against TwinCAT 2/3 runtimes. Full IEC 61131-3 atomic type set including WString + the four Time/Date variants. --poll-only toggles UseNativeNotifications=false. Subscribe banner announces mechanism (ADS notification vs polling).

Tests

49 new (22 S7 + 27 TwinCAT); 122 cumulative driver-CLI tests across #249 + #250 + #251.

Suite complete

5 CLIs shipped: otopcua-{modbus,abcip,ablegacy,s7,twincat}-cli. Every driver family has a shell-level ad-hoc validation tool.

Test plan

Full-solution build clean. Both --help outputs verified.

Final two of the five driver test clients. Closes out the #249 → #250 → #251 track. ## otopcua-s7-cli S7comm / ISO-on-TCP 102 against S7-300/400/1200/1500. All S7 data types incl. DateTime round-trip + bit/word/dword DB addressing. Documents the PUT/GET-must-be-enabled gotcha. ## otopcua-twincat-cli ADS against TwinCAT 2/3 runtimes. Full IEC 61131-3 atomic type set including WString + the four Time/Date variants. `--poll-only` toggles `UseNativeNotifications=false`. Subscribe banner announces mechanism (ADS notification vs polling). ## Tests 49 new (22 S7 + 27 TwinCAT); 122 cumulative driver-CLI tests across #249 + #250 + #251. ## Suite complete 5 CLIs shipped: otopcua-{modbus,abcip,ablegacy,s7,twincat}-cli. Every driver family has a shell-level ad-hoc validation tool. ## Test plan Full-solution build clean. Both `--help` outputs verified.
dohertj2 added 1 commit 2026-04-21 08:46:52 -04:00
Final two of the five driver test clients. Pattern carried forward from
#249 (Modbus) + #250 (AB CIP, AB Legacy) — each CLI inherits Driver.Cli.Common
for DriverCommandBase + SnapshotFormatter and adds a protocol-specific
CommandBase + 4 commands (probe / read / write / subscribe).

New projects:
  - src/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/ — otopcua-s7-cli.
    S7CommandBase carries host/port/cpu/rack/slot/timeout. Handles all S7
    atomic types (Bool, Byte, Int16..UInt64, Float32/64, String, DateTime).
    DateTime parses via RoundtripKind so "2026-04-21T12:34:56Z" works.
  - src/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/ — otopcua-twincat-cli.
    TwinCATCommandBase carries ams-net-id + ams-port + --poll-only toggle
    (flips UseNativeNotifications=false). Covers the full IEC 61131-3
    atomic set: Bool, SInt/USInt, Int/UInt, DInt/UDInt, LInt/ULInt, Real,
    LReal, String, WString, Time/Date/DateTime/TimeOfDay. Structure writes
    refused as out-of-scope (same as AB CIP). IEC time/date variants marshal
    as UDINT on the wire per IEC spec. Subscribe banner announces "ADS
    notification" vs "polling" so the mechanism is obvious in bug reports.

Tests (49 new, 122 cumulative driver-CLI):
  - S7: 22 tests. Every S7DataType has a happy-path + bounds case. DateTime
    round-trips an ISO-8601 string. Tag-name synthesis round-trips every
    S7 address form (DB / M / I / Q, bit/word/dword, strings).
  - TwinCAT: 27 tests. Full IEC type matrix including WString UTF-8 pass-
    through + the four IEC time/date variants landing on UDINT. Structure
    rejection case. Tag-name synthesis for Program scope, GVL scope, nested
    UDT members, and array elements.

Docs:
  - docs/Driver.S7.Cli.md — address grammar cheat sheet + the PUT/GET-must-
    be-enabled gotcha every S7-1200/1500 operator hits.
  - docs/Driver.TwinCAT.Cli.md — AMS router prerequisite (XAR / standalone
    Router NuGet / remote AMS route) + per-command examples.

Wiring:
  - ZB.MOM.WW.OtOpcUa.slnx grew 4 entries (2 src + 2 tests).

Full-solution build clean. Both --help outputs verified end-to-end.

Driver CLI suite complete: 5 CLIs (otopcua-{modbus,abcip,ablegacy,s7,twincat}-cli)
sharing a common base + formatter. 122 CLI tests cumulative. Every driver family
shipped in v2 now has a shell-level ad-hoc validation tool.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 4446a3ce5b into v2 2026-04-21 08:47:05 -04:00
dohertj2 referenced this issue from a commit 2026-04-30 08:21:26 -04:00
Doc refresh (task #206) — Client.CLI + Client.UI brand flip + new top-level docs/README.md index. Client.CLI.md: replaced stale LmxOpcUa-OPC UA-server references with OtOpcUa throughout the overview + sample output + applicationUri examples (opc.tcp://localhost:4840/OtOpcUa, urn:localhost:OtOpcUa:instanceN); confirmed against src/ZB.MOM.WW.OtOpcUa.Server/Program.cs:69-71 which sets the live endpoint url + application uri to those exact values. Added a driver-agnostic note in the overview — the CLI is reachable against every shipped driver surface because the OPC UA endpoint abstracts them all. Kept the `lmxopcua-cli` executable name + the `{LocalAppData}/LmxOpcUaClient/pki/` PKI folder name AS-IS because those are real filesystem-level residuals the code still uses (Program.cs SetExecutableName + OpcUaClientService.cs:428) — flipping them requires migration shims so existing dev boxes don't lose their trusted-cert store; added explicit doc text explaining the residual + why it persists so future readers aren't confused. Fixed the sample connect-output "Server: LmxOpcUa" to "Server: OtOpcUa Server" matching the live ApplicationName in OpcUaServerOptions.cs:39. Client.UI.md: replaced the 4 LmxOpcUa references — overview one-liner, status-bar mock (now reads "OtOpcUa Server" matching the server's reported ApplicationName), endpoint-url example, settings persistence path. Same residual-explanation note added under the LmxOpcUaClient/settings.json path pointing at the Client.Shared session-factory literal at OpcUaClientService.cs:428. docs/README.md is new — a top-level index distinguishing the two documentation tiers (current reference at docs/*.md vs implementation history + design notes at docs/v2/*.md). Every current-reference doc gets a one-line role description in a section table (Architecture + data-path / Drivers / Operational / Client tooling / Requirements) so a new reader picking up the repo finds their way in without having to grep file names. Cross-link calls out that load-bearing references from top-level docs (plan.md decisions, admin-ui.md, acl-design.md, config-db-schema.md, driver-specs.md, dev-environment.md, test-data-sources.md) live under v2/. Notes up front that the project was renamed LmxOpcUa → OtOpcUa and that any remaining LmxOpcUa-string in paths is a deliberate residual with a migration follow-up, so readers don't chase phantom bugs. Four parallel doc-refresh agents currently working on the rest of docs/*.md (task #202 core architecture, #203 driver docs split, #204 operational, #205 requirements) — those commits will land on separate worktree branches + get folded in together once complete; this index already lists the docs they'll produce (drivers/README.md, drivers/Galaxy.md, drivers/Galaxy-Repository.md) so the final merge just has the content showing up where the index already points.
Sign in to join this conversation.