178 lines
6.8 KiB
Markdown
178 lines
6.8 KiB
Markdown
# `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
|
|
|
|
```powershell
|
|
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 |
|
|
| `--tsap-mode` | `Auto` | ISO-on-TCP connection class: `Auto` / `Pg` / `Op` / `S7Basic` / `Other`. Hardened S7-1500 / ET 200SP CPUs may require `Op` or `S7Basic`. See [s7.md TSAP / Connection Type](v2/s7.md#tsap--connection-type). |
|
|
| `--local-tsap` | (unset) | Optional 16-bit local TSAP override (e.g. `0x0200`). Required when `--tsap-mode Other`; wins over class default under Pg/Op/S7Basic. |
|
|
| `--remote-tsap` | (unset) | Optional 16-bit remote TSAP override. Required when `--tsap-mode Other`; wins over class default under Pg/Op/S7Basic. |
|
|
| `--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`.
|
|
|
|
### Pre-flight PUT/GET enablement (PR-S7-C5)
|
|
|
|
The driver issues a tiny 2-byte read against `Probe.ProbeAddress` (default
|
|
`MW0`) immediately after `OpenAsync` and **fails `InitializeAsync` with a
|
|
typed `S7PutGetDisabledException`** when the PLC rejects the read with the
|
|
wire-level "function not allowed" response. The exception message names the
|
|
exact TIA Portal toggle to flip — operators see the configuration fix at
|
|
init time, not after the first per-tag read produces `BadDeviceFailure`.
|
|
|
|
Two opt-out knobs on the JSON `Probe` block:
|
|
|
|
- `ProbeAddress` — set to `""` (empty string) to skip the pre-flight read
|
|
entirely. Useful when no fingerprint address has been wired.
|
|
- `SkipPreflight` — set to `true` to defer the check to runtime while
|
|
keeping the background liveness loop. Per-tag reads still surface
|
|
`BadDeviceFailure` until PUT/GET is enabled, but Init succeeds and the
|
|
driver becomes visible in the Admin UI.
|
|
|
|
See [s7.md "Pre-flight PUT/GET enablement"](v2/s7.md#pre-flight-putget-enablement)
|
|
for the full rationale, classifier behaviour, and the wire-level
|
|
`ErrorCode` matching.
|
|
|
|
## 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`
|
|
|
|
```powershell
|
|
# 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`
|
|
|
|
```powershell
|
|
# 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`
|
|
|
|
```powershell
|
|
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.
|
|
|
|
### Hardened CPU — forcing OP-class TSAP
|
|
|
|
```powershell
|
|
# Probe a hardened S7-1500 that rejects PG class but accepts OP.
|
|
otopcua-s7-cli probe -h 10.50.12.30 --tsap-mode Op
|
|
|
|
# Read against the same CPU.
|
|
otopcua-s7-cli read -h 10.50.12.30 --tsap-mode Op -a DB1.DBW0 -t Int16
|
|
|
|
# Manual TSAP override (e.g. site with a fixed proprietary TSAP gateway).
|
|
otopcua-s7-cli probe -h 10.50.12.30 --tsap-mode Other --local-tsap 0x4D57 --remote-tsap 0x4D58
|
|
```
|
|
|
|
Without `--tsap-mode`, the CLI uses S7netplus's CpuType-derived default (PG
|
|
class for almost everything). The same connection-refused failure shape that a
|
|
wrong `--slot` produces also shows up when the CPU rejects PG class — try
|
|
`--tsap-mode Op` first when the handshake is failing on otherwise-correct
|
|
endpoint config. See [s7.md TSAP / Connection Type](v2/s7.md#tsap--connection-type)
|
|
for the byte table and motivation.
|
|
|
|
### `subscribe`
|
|
|
|
```powershell
|
|
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.
|
|
|
|
### `import-symbols`
|
|
|
|
PR-S7-D1 / [#299](https://github.com/dohertj2/lmxopcua/issues/299) — read a TIA
|
|
Portal CSV ("Show all tags" export) or STEP 7 Classic `.AWL` file and emit a
|
|
JSON tag fragment for `appsettings.json`, or a one-line summary. Mirrors the
|
|
AB Legacy `import-rslogix` CLI in shape.
|
|
|
|
```powershell
|
|
# TIA Portal CSV — emit JSON fragment to stdout
|
|
otopcua-s7-cli import-symbols --file plc-export.csv --format tia
|
|
|
|
# STEP 7 Classic AWL — emit summary line
|
|
otopcua-s7-cli import-symbols --file classic.awl --format awl --emit summary
|
|
|
|
# DE-locale CSV — auto-detected; output to file
|
|
otopcua-s7-cli import-symbols `
|
|
--file plc-de.csv `
|
|
--format tia `
|
|
--emit appsettings-fragment `
|
|
--output tags.json
|
|
|
|
# Strict mode — fail-fast on the first malformed row (CI lint)
|
|
otopcua-s7-cli import-symbols --file plc.csv --format tia --strict
|
|
```
|
|
|
|
| Flag | Default | Purpose |
|
|
|---|---|---|
|
|
| `-f` / `--file` | **required** | Path to the TIA CSV or `.AWL` file |
|
|
| `--format` | `tia` | `tia` (CSV) or `awl` (STEP 7 Classic) |
|
|
| `-d` / `--device` | none | Optional documentation tag (held for symmetry with `import-rslogix`) |
|
|
| `--emit` | `appsettings-fragment` | `appsettings-fragment` (JSON) or `summary` (one-line counter) |
|
|
| `-o` / `--output` | stdout | Optional path; when set the JSON fragment is written there + summary line goes to stdout |
|
|
| `--max-rows` | unlimited | Defensive cap on rows imported |
|
|
| `--strict` | off | Fail-fast on the first malformed row (default permissive: skip + log) |
|
|
|
|
UDT-typed rows import as placeholder tags (data type forced to `Byte`); see
|
|
[S7-TIA-Import.md](drivers/S7-TIA-Import.md) for the full format reference,
|
|
locale auto-detection, and AWL position-based addressing rules.
|