Files
lmxopcua/docs/Driver.S7.Cli.md
Joseph Doherty 4dc685a365 Task #251 — S7 + TwinCAT test-client CLIs (driver CLI suite complete)
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>
2026-04-21 08:44:53 -04:00

2.7 KiB

otopcua-s7-cli — Siemens S7 test client

Ad-hoc probe / read / write / subscribe tool for Siemens S7-300 / S7-400 / S7-1200 / S7-1500 (and compatible soft-PLCs) over S7comm / ISO-on-TCP port 102. Uses the same S7Driver the OtOpcUa server does (S7.Net under the hood).

Fourth of four driver test-client CLIs.

Build + run

dotnet run --project src/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli -- --help

Common flags

Flag Default Purpose
-h / --host required PLC IP or hostname
-p / --port 102 ISO-on-TCP port (rarely changes)
-c / --cpu S71500 S7200 / S7200Smart / S7300 / S7400 / S71200 / S71500
--rack 0 Hardware rack (S7-400 distributed setups only)
--slot 0 CPU slot (S7-300 = 2, S7-400 = 2 or 3, S7-1200/1500 = 0)
--timeout-ms 5000 Per-operation timeout
--verbose off Serilog debug output

PUT/GET must be enabled

S7-1200 / S7-1500 ship with PUT/GET communication disabled by default. Enable it in TIA Portal: Device config → Protection & Security → Connection mechanisms → "Permit access with PUT/GET communication from remote partner". Without it the CLI's first read will surface BadNotSupported.

S7 address grammar cheat sheet

Form Meaning
DB1.DBW0 DB number 1, word offset 0
DB1.DBD4 DB number 1, dword offset 4
DB1.DBX2.3 DB number 1, byte 2, bit 3
DB10.STRING[0] DB 10 string starting at offset 0
M0.0 Merker bit 0.0
MW0 / MD4 Merker word / dword
IW4 Input word 4
QD8 Output dword 8

Commands

probe

# S7-1500 — default probe MW0
otopcua-s7-cli probe -h 192.168.1.30

# S7-300 (slot 2)
otopcua-s7-cli probe -h 192.168.1.31 -c S7300 --slot 2 -a DB1.DBW0

read

# DB word
otopcua-s7-cli read -h 192.168.1.30 -a DB1.DBW0 -t Int16

# Float32 from DB dword
otopcua-s7-cli read -h 192.168.1.30 -a DB1.DBD4 -t Float32

# Merker bit
otopcua-s7-cli read -h 192.168.1.30 -a M0.0 -t Bool

# 80-char S7 string
otopcua-s7-cli read -h 192.168.1.30 -a DB10.STRING[0] -t String --string-length 80

write

otopcua-s7-cli write -h 192.168.1.30 -a DB1.DBW0 -t Int16 -v 42
otopcua-s7-cli write -h 192.168.1.30 -a DB1.DBD4 -t Float32 -v 3.14
otopcua-s7-cli write -h 192.168.1.30 -a M0.0 -t Bool -v true

Writes to M / Q are real — they drive the PLC program. Be careful what you flip on a running machine.

subscribe

otopcua-s7-cli subscribe -h 192.168.1.30 -a DB1.DBW0 -t Int16 -i 500

S7comm has no native push — the CLI polls through PollGroupEngine just like Modbus / AB.