2026-10-03 12:05:38 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 12:05:38 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 09:46:11 +02:00
2026-10-03 12:05:38 +02:00

wago-modbustcp-simulator-py

WAGO 750-362 Modbus TCP bus coupler simulator for autonomous PLC FAT testing.

The simulator replaces a physical WAGO I/O node during Factory Acceptance Tests: the PLC under test connects via Modbus TCP and talks to a virtual node whose I/O behavior is driven by scripted scenarios.

Features

  • Faithful WAGO 750-362 register map (manual §11.2.4): process image words/bits with the exact mapped/unmapped areas and exception behavior, read-back mirrors (+0x0200 / +0x1000), configuration registers 0x1000–0x2FFF, constants 0x2000–0x2008 (byte-order check 0x1234).
  • Function codes FC1, FC2, FC3, FC4, FC5, FC6, FC11, FC15, FC16, FC22, FC23 with the device limits (2000/800 bits, 125/100 registers).
  • Modbus watchdog (0x1000–0x100B), statistics block (0x1029), response-delay injection (0x1037), module diagnosis (0x1050).
  • Virtual node built from a YAML module list (WAGO 750 catalog subset, extensible).
  • Scenario engine: YAML scenarios with aliases, macros, ramps, pulses, waits, and PASS/FAIL assertions with timeouts; state machines and Python action plugins for complex plant models.
  • Two I/O addressing schemes for aliases: module-based — { type: di, module: 2, channel: 1 } = DI2.1 (module slot and channel both 0-based) — and pool-based — { type: di, channel: 3 } (1-based index across the node's DI pool). Both may be mixed.
  • Bench mode (requested, planned — spec §9): run the simulator without a scenario (wago-sim serve --node ... already works); planned additions: --set DI0.1=ON startup seeding, an interactive console monitor with live I/O table, and runtime set/pulse/watch commands.
  • Web UI (requested, planned — spec §10): browser front-end to overlook and manipulate the virtual node's I/O — live channel tables with DI0.1-style addresses, toggle/force/pulse/ramp actions, watchdog/statistics/diagnostics views with fault injection, and multi-client consistency for collaborative FAT benches.
  • Runtime device configuration (requested, planned — spec §11): WBM/DIP-switch parity — module "plug/unplug" at runtime with process-image rebuild (SAVE CONFIG / KBUS 0x102B semantics), address-selection DIP-switch emulation (host ID 1–254, 0 = stored config, 255 = DHCP), WBM-equivalent pages (Port/Ethernet, Modbus settings, Modbus Mapping, I/O Config), and device-state persistence with factory reset.
  • Long-duration (continuous) simulation (requested, planned — see docs/spec/software-spec.md §8): endurance/soak testing over days or weeks of simulated time. Designated inputs are driven from streaming CSV datasets (historian exports, demand/operator profiles, seamless repeat, time_factor acceleration), while degradation models age plant parameters (e.g., pump capacity) from wear counters — exercising the PLC's compensation, maintenance-alarm and service-recovery logic. Continuous invariants and rate_limits produce bounded, episode-based reports for unattended runs.
  • ≤ 15 concurrent Modbus TCP connections, idle-timeout handling.

Install (dev)

pip install -e .[dev]

Usage

Run the Modbus TCP server against a node configuration:

wago-sim serve --node config/pump_node.yaml --port 502

Validate a scenario:

wago-sim validate --scenario scenarios/pump_station_fat.yaml

Run a scenario headless and write reports:

wago-sim run --node config/pump_node.yaml \
  --scenario scenarios/pump_station_fat.yaml \
  --report-jsonl out/report.jsonl --report-csv out/report.csv

Documentation

  • docs/spec/software-spec.md — the software specification (requirements, architecture, scenario DSL, acceptance criteria, and the long-duration simulation feature request in §8).
  • docs/m07500362_xxxxxxxx_0en.pdf — WAGO 750-362 reference manual.

Testing

pytest

TODO

Work remaining, tracked against the software specification (docs/spec/software-spec.md). Completed items are checked and grouped first; open items follow, grouped by spec phase, with the spec section or requirement ID for each item in parentheses.

Completed — framework phase (spec §3 + §4 core, 124 tests passing)

  • MBAP + PDU codecs: function codes FC1, FC2, FC3, FC4, FC5, FC6, FC11, FC15, FC16, FC22, FC23 with the 750-362 device limits (2000/800 bits, 125/100 registers) and exception codes (§3.2).
  • WAGO register map (§3.3): word/bit process-image areas with the exact mapped/unmapped ranges, illegal-address exceptions, output read-back mirrors (+0x0200 / +0x1000), digital channel-number bit addressing, constants 0x2000–0x2008 (incl. byte-order check 0x2002 = 0x1234).
  • Configuration/diagnostic/firmware registers (§3.5): image sizes 0x1022–0x1025, statistics 0x1029, connections 0x102A, idle timeout 0x1030, MAC-ID 0x1031, response delay 0x1037, module diagnosis 0x1050, LED error 0x1020/0x1021.
  • Modbus watchdog (§3.4): registers 0x1000–0x100B, Standard and Alternative modes, trigger/masks/stop sequences, expiry clears outputs, address-aware 0x04 lock in Standard mode, optional TCP close on timeout.
  • Fault-injection paths (§3.6): response-delay injection, connection refusal beyond 15, illegal-address probing responses, diagnosis/LED registers scriptable.
  • Virtual node built from a YAML module list (13-module WAGO 750 catalog subset; complex-first, bit-byte-packed image layout per manual §7.3.2.1).
  • Scenario DSL (§4): named aliases with scale/offset, macros with parameters (inline expansion, blocking waits inside macros), sequence steps set / reset / toggle / pulse / ramp / wait / assert / report, rising-edge detection on all aliases.
  • Two I/O addressing schemes for scenario aliases (FR-4.3.11): module-based ({ type: di, module: 2, channel: 1 } = DI2.1, module slot and channel 0-based) and pool-based (channel: = 1-based index within the node's kind pool); kind/module/channel validation with clear errors; both verified by tests.
  • Assertions with within: timeouts → PASS/FAIL verdicts with sim-time stamps (FR-4.3.5).
  • Python action/plant-model plugins: per-tick models and step actions (FR-4.3.8), e.g. plugins/pump_plant.py.
  • Deterministic tick-driven engine: sim-time decoupled from wall-clock (FR-4.3.9 core).
  • CLI: wago-sim serve / run / validate.
  • Reports: console verdict summary, JSONL and CSV export (--report-jsonl / --report-csv).
  • asyncio Modbus TCP server: ≤ 15 concurrent connections, idle connection reaper, response-delay task.
  • Test suite: 124 tests incl. real-socket server tests and pymodbus interop; spec §7 acceptance criteria 1–7 covered.

Framework gaps (spec §4 — Scenario & Macro Engine)

  • State machines: states: with entry actions, transitions on input/output edges or conditions, and guards (FR-4.3.2) — currently only the time-ordered sequence: is implemented.
  • Actions noise, sin, hold on simulated inputs (FR-4.3.4) — set/reset/pulse/toggle/ramp are done.
  • wait_edge step is accepted but not yet blocking — implement edge-wait semantics in the engine loop.
  • Assertions on statistics registers, e.g. "watchdog expired", "BadAddress counter > 0" (FR-4.3.6).
  • Determinism guard: seed/record plugin RNG state so identical runs produce identical reports (FR-4.3.9, NFR-6.3) — needed once noise/sin or randomizing plugins exist.
  • Multi-node scenarios — several couplers in one scenario (FR-4.3.10).

Phase 2 — Module catalog expansion & bench mode (spec §9)

  • Analog module variants, counter, pulse-width, SSI, incremental encoder, serial interface, DALI/DSI modules with their process-data layouts (spec §12.2 of the WAGO manual).
  • Mailbox parameterization traffic beyond process data.
  • Bench mode tooling (§9): --set DI0.1=ON startup seeding, interactive console monitor (--monitor) with live channel table and change highlighting (FR-9.2.2–9.2.3).
  • Console runtime manipulation commands: set, pulse, watch, reset stats (FR-9.2.4).
  • serve --scenario optional combination + passive-node hint (FR-9.2.5). (Plain serve without a scenario already works — see Completed above.)

Phase 3 — Long-duration (continuous) simulation (spec §8)

The soak-testing feature requested 2026-10-03 — specified in §8, not yet implemented. Datasets are optional: signal logic (plugins, scheduled steps, degradation) runs in parallel with CSV streaming, or entirely without it.

  • scenario/datasets.py — streaming CSV playback for designated inputs (OPTIONAL driver): header-driven time column, interpolation: linear|hold, repeat with seamless seams, time_factor acceleration, until limits, bounded memory, ERROR verdict with file/line on malformed data (FR-8.2.1–8.2.11).
  • Parallel logic pipeline — fixed per-tick order: datasets → edge detection → plant plugins → degradation → invariants/rate limits → scheduled steps → snapshots; plugins may read dataset-driven and logic-driven aliases in the same tick (FR-8.2.12).
  • Logic-only continuous runs — no datasets: needed: demand profiles generated inside plugins, top-level until: bounds the run; degradation/invariants/rate limits/snapshots apply identically (FR-8.2.13).
  • Continuous-mode run-end + validation rules: run ends when all drivers exhausted; scenario with no datasets, no scheduled steps and no until: rejected (FR-8.2.1).
  • scenario/degradation.py — wear counters (runtime hours, start cycles, load-hours) and degradation models (linear, exponential, staircase, plugin shapes) computing plant parameters such as pump_capacity (FR-8.3.1–8.3.2).
  • Degradation hooks in plant plugins: engine.parameter() accessor used in loop physics, e.g. actual flow = nominal × capacity (FR-8.3.3).
  • maintenance_at thresholds: diagnosis injection via register 0x1050, maintenance-alarm assertions, maintenance_reset action restoring capacity and clearing diagnoses (FR-8.3.4–8.3.5, FR-8.3.8).
  • scenario/invariants.py — per-tick invariants with bounded episode aggregation and rate_limits over sliding one-hour windows (FR-8.4.1–8.4.2).
  • snapshot_every periodic dumps of aliases, wear counters, and degradation parameters (FR-8.4.3).
  • Continuous-mode verdict rules and bounded reporting for unattended multi-day runs (FR-8.4.4–8.4.5).
  • Scheduled sequence steps via at: <duration> interleaved with datasets on the sim-time axis (FR-8.4.6).
  • Acceptance tests per spec §8.8 (streaming 100k-row CSV, interpolation checks, repeat determinism, time_factor math, alias-ownership validation, degradation/recovery round-trip, episode recording, full 28-day soak, logic-only run, mixed dataset+logic tick-order run).

Phase 4 — Reporting (spec §11)

  • FAT report generator (HTML/PDF) from scenario results and Modbus traces (console/JSONL/CSV export is done — see Completed above).
  • Scenario comparison (run-vs-run diff) and template library per project type.

Phase 5 — Multi-node orchestration & protocol variants (spec §11)

  • Several couplers in one FAT bench (ties into FR-4.3.10).
  • Modbus UDP variant.
  • WBM (web-based management) simulation pages.
  • Web UI (§10): browser front-end for overlooking and manipulating I/O — node/module/channel tables with DI0.1-style and Modbus addresses (FR-10.2.2), live value updates from all sources (FR-10.2.3), toggle/force/pulse/ramp manipulation through Modbus-consistent paths (FR-10.2.4), diagnostics views with fault injection and statistics reset (FR-10.2.5), scenario/run view (FR-10.2.6), multi-client consistency (FR-10.2.7), optional read-only/access control (FR-10.2.8), alias-ownership protection during scenario runs (FR-10.2.9).
  • Runtime device configuration (§11): module hot-configuration (plug/unplug at slot positions) with process-image rebuild per KBUS/SAVE-CONFIG semantics and updated 0x1022–0x1025 / 0x2030+ registers (FR-11.2.1–11.2.2); alias revalidation after rebuilds with position-stable module addressing (FR-11.2.3); rejection during running scenarios (FR-11.2.4); address-selection DIP-switch emulation with the manual's exact coding (1–254 host ID, 0 = stored config, 255 = DHCP, restart-to-apply) (FR-11.3.1–11.3.4); WBM-equivalent pages — Port/Ethernet, Modbus settings, Modbus Mapping, I/O Config with SAVE CONFIG (FR-11.4.1–11.4.4); device-state persistence and factory reset via 0x2043 (FR-11.5.1–11.5.2).

Phase 6 — CI integration (spec §11)

  • Headless scenario execution in CI pipelines.
  • JUnit XML export of verdicts for test dashboards.

Operational hardening (spec §6 — NFRs)

  • Per-transaction Modbus trace log with sim-time + wall-time stamps and PDU hex (NFR-6.4).
  • Performance budget validation: ≥ 500 requests/s, ≤ 10 ms added latency (NFR-6.1).
S
Description
No description provided
Readme
10 MiB
Languages
Python 88.9%
JavaScript 6.6%
CSS 2.7%
HTML 1.4%
Dockerfile 0.4%