🚧 Add feature requests

This commit is contained in:
Jonas Bengtsson
2026-10-03 12:05:38 +02:00
parent 973d619cee
commit ba8df075c3
2 changed files with 269 additions and 26 deletions
+40 -6
View File
@@ -35,6 +35,13 @@ a virtual node whose I/O behavior is driven by scripted scenarios.
with `DI0.1`-style addresses, toggle/force/pulse/ramp actions, with `DI0.1`-style addresses, toggle/force/pulse/ramp actions,
watchdog/statistics/diagnostics views with fault injection, and watchdog/statistics/diagnostics views with fault injection, and
multi-client consistency for collaborative FAT benches. 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 - **Long-duration (continuous) simulation** *(requested, planned — see
`docs/spec/software-spec.md` §8)*: endurance/soak testing over days or `docs/spec/software-spec.md` §8)*: endurance/soak testing over days or
weeks of simulated time. Designated inputs are driven from streaming weeks of simulated time. Designated inputs are driven from streaming
@@ -176,13 +183,27 @@ requirement ID for each item in parentheses.
### Phase 3 — Long-duration (continuous) simulation (spec §8) ### Phase 3 — Long-duration (continuous) simulation (spec §8)
The soak-testing feature requested 2026-10-03 — specified in §8, The soak-testing feature requested 2026-10-03 — specified in §8,
not yet implemented: 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 - [ ] `scenario/datasets.py` — streaming CSV playback for designated
inputs: header-driven time column, `interpolation: linear|hold`, inputs (OPTIONAL driver): header-driven time column,
`repeat` with seamless seams, `time_factor` acceleration, `interpolation: linear|hold`, `repeat` with seamless seams,
`until` limits, bounded memory, ERROR verdict with file/line on `time_factor` acceleration, `until` limits, bounded memory, ERROR
malformed data (FR-8.2.1–8.2.11). 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 - [ ] `scenario/degradation.py` — wear counters (runtime hours, start
cycles, load-hours) and degradation models (`linear`, cycles, load-hours) and degradation models (`linear`,
`exponential`, `staircase`, plugin shapes) computing plant `exponential`, `staircase`, plugin shapes) computing plant
@@ -206,7 +227,8 @@ not yet implemented:
- [ ] Acceptance tests per spec §8.8 (streaming 100k-row CSV, - [ ] Acceptance tests per spec §8.8 (streaming 100k-row CSV,
interpolation checks, repeat determinism, time_factor math, interpolation checks, repeat determinism, time_factor math,
alias-ownership validation, degradation/recovery round-trip, alias-ownership validation, degradation/recovery round-trip,
episode recording, full 28-day soak). episode recording, full 28-day soak, logic-only run, mixed
dataset+logic tick-order run).
### Phase 4 — Reporting (spec §11) ### Phase 4 — Reporting (spec §11)
@@ -229,6 +251,18 @@ not yet implemented:
view (FR-10.2.6), multi-client consistency (FR-10.2.7), optional view (FR-10.2.6), multi-client consistency (FR-10.2.7), optional
read-only/access control (FR-10.2.8), alias-ownership protection read-only/access control (FR-10.2.8), alias-ownership protection
during scenario runs (FR-10.2.9). 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) ### Phase 6 — CI integration (spec §11)
+229 -20
View File
@@ -5,9 +5,9 @@
| | | | | |
|---|---| |---|---|
| Project | `wago-modbustcp-simulator-py` | | Project | `wago-modbustcp-simulator-py` |
| Version | 1.1 (Draft for review) | | Version | 1.2 (Draft for review) |
| Date | 2026-10-03 | | Date | 2026-10-03 |
| Status | Framework phase; module addressing implemented (FR-4.3.11); long-duration simulation (§8), bench mode (§9) and web UI (§10) requested | | Status | Framework phase; module addressing implemented (FR-4.3.11); long-duration simulation (§8), bench mode (§9), web UI (§10) and runtime device configuration (§11) requested |
| Target device simulated | WAGO 750-362 / 750-362/0000-0001 FC Modbus TCP (G4) bus coupler | | Target device simulated | WAGO 750-362 / 750-362/0000-0001 FC Modbus TCP (G4) bus coupler |
| Reference documents | `docs/m07500362_xxxxxxxx_0en.pdf` (750-362 Modbus TCP manual), Modbus TCP specification (modbus.org) | | Reference documents | `docs/m07500362_xxxxxxxx_0en.pdf` (750-362 Modbus TCP manual), Modbus TCP specification (modbus.org) |
@@ -471,24 +471,40 @@ additionally be proven **over long time**:
- **Clock edge cases**: midnight rollovers and (via absolute-timestamp datasets) DST transitions. - **Clock edge cases**: midnight rollovers and (via absolute-timestamp datasets) DST transitions.
Long runs cannot be hand-scripted step by step. Two mechanisms replace the Long runs cannot be hand-scripted step by step. Two mechanisms replace the
scripted `sequence`: scripted `sequence`, and both run **in parallel on the same sim-time axis**:
1. **Dataset playback** — designated inputs are driven from time-series files 1. **Dataset playback** *(optional)* — designated inputs are driven from
(e.g., CSV exported from a plant historian, or synthesized profiles). time-series files (e.g., CSV exported from a plant historian, or
2. **Degradation models** — plant-model parameters (e.g., pump capacity) synthesized profiles).
degrade as a function of runtime and cycles, exercising the PLC’s 2. **Signal logic** — plant-model plugins (FR-4.3.8) compute endogenous
signals and closed-loop physics in Python, scheduled sequence steps
(`at:`) perform discrete actions, and degradation models age plant
parameters (e.g., pump capacity) from wear, exercising the PLC’s
compensation and maintenance logic. compensation and maintenance logic.
Datasets are **not required**: a continuous run may be driven entirely by
logic (plugin-generated demand profiles, scheduled events, degradation),
entirely by datasets, or by any mix — some aliases fed from CSV while
others are computed by logic, in the same run. The signal logic works
unchanged whether or not CSV streaming is used.
### 8.2 Requirements — continuous mode & CSV dataset playback ### 8.2 Requirements — continuous mode & CSV dataset playback
- FR-8.2.1: A scenario may declare `mode: continuous`. The `sequence` becomes - FR-8.2.1: A scenario may declare `mode: continuous`. The `sequence` becomes
optional; the run continues until the dataset schedule (plus any `until:` optional. The run continues until **all active drivers are exhausted**:
duration) is exhausted. every dataset finished (or looped to its `repeat` limit), all scheduled
- FR-8.2.2: Input aliases (di/ai) may be driven from **datasets**. Output steps executed, and — if a top-level `until: <duration>` is given — the
aliases must not appear in datasets (validation error). An endogenous process duration elapsed. With no datasets, `until:` is the primary run-length
variable (e.g., tank level) may instead be computed by a plant-model plugin control. A continuous scenario with neither datasets, nor scheduled
(FR-4.3.8, closed loop). **Exactly one driver** may own an alias (dataset, steps, nor `until:` is a validation error (it would run forever).
plugin-declared variable, ramp, pulse, or step) — conflicts are validation errors. - FR-8.2.2: Input aliases (di/ai) may be driven from **datasets**, which are
entirely **optional**. Output aliases must not appear in datasets
(validation error). Aliases not owned by a dataset are **logic-driven**:
computed by a plant-model plugin (FR-4.3.8, closed loop), set by
scheduled steps, or left at their current value. An endogenous process
variable (e.g., tank level) is computed by the plant model. **Exactly one
driver** may own an alias (dataset, plugin-declared variable, ramp,
pulse, or step) — conflicts are validation errors.
- FR-8.2.3: CSV format: a header row with the time column (default `time`, - FR-8.2.3: CSV format: a header row with the time column (default `time`,
configurable via `time_column`) plus one column per alias. Time is elapsed configurable via `time_column`) plus one column per alias. Time is elapsed
seconds (default) or ISO-8601 absolute timestamps (`time_format: iso8601`). seconds (default) or ISO-8601 absolute timestamps (`time_format: iso8601`).
@@ -516,6 +532,24 @@ scripted `sequence`:
- FR-8.2.11: Malformed data (unknown column, unparsable time or value, - FR-8.2.11: Malformed data (unknown column, unparsable time or value,
non-monotonic timestamps) ends the run with verdict **ERROR**, citing file non-monotonic timestamps) ends the run with verdict **ERROR**, citing file
and line number. and line number.
- FR-8.2.12: **Parallel logic execution**: datasets and signal logic run in
the same deterministic tick pipeline, in a fixed order per tick:
(1) datasets apply their sampled/interpolated values to their aliases,
(2) alias edges are detected,
(3) plant-model plugins run — they may read dataset-driven AND
logic-driven aliases and compute endogenous variables in the same tick,
(4) degradation models update,
(5) invariants and rate limits evaluate,
(6) scheduled steps due at this tick execute,
(7) snapshots are taken if due.
This order is part of the specification and shall be covered by tests.
- FR-8.2.13: **Logic-only continuous runs**: with no `datasets:` block at
all, continuous mode shall work unchanged — demand profiles and other
exogenous signals may be generated *inside* plant-model plugins (e.g., a
daily sinusoid or a state-based profile computed in Python), with
top-level `until:` bounding the run. All §8.3–8.4 machinery (degradation,
invariants, rate limits, snapshots) applies identically, whether or not
any CSV streaming is configured.
### 8.3 Requirements — degradation models (plant logic over time) ### 8.3 Requirements — degradation models (plant logic over time)
@@ -653,20 +687,50 @@ time,start_button,em_stop_ok,inflow_valve
440000,OFF,ON,ON 440000,OFF,ON,ON
``` ```
**Variant without datasets** (logic-only, same soak): drop the
`datasets:` block entirely, keep everything else, and let the plant
plugin *also* generate the demand signal each tick:
```yaml
name: pump_station_soak_28d_logic
mode: continuous
until: 28d # no datasets: until bounds the run
inputs: ... # same aliases — none dataset-owned
outputs: ...
plugins: [plugins.pump_plant.pump_plant]
# plugin computes, per tick (FR-8.2.12 step 3):
# inflow_rate = 12 + 3*sin(2*pi*t/24h)
# d(level)/dt = inflow - pump_flow(speed, capacity)
degradation: ... # identical to the dataset version
invariants: ...
rate_limits: ...
report: { snapshot_every: 1h }
```
Both variants test the same PLC behavior; the CSV version replays recorded
demand, the logic version synthesizes it. Mixing is equally valid — e.g.
`inflow_rate` from a dataset while `start_button` is toggled by scheduled
`at:` steps, with the plant plugin reading both (FR-8.2.12).
### 8.6 Architecture impact (planned modules) ### 8.6 Architecture impact (planned modules)
``` ```
src/wago_sim/scenario/ src/wago_sim/scenario/
├── datasets.py # CsvDataset: streaming reader, interpolation, repeat, time_factor ├── datasets.py # CsvDataset: streaming reader, interpolation, repeat,
│ # time_factor — OPTIONAL driver in continuous mode
├── degradation.py # WearCounters, DegradationModel registry, maintenance actions ├── degradation.py # WearCounters, DegradationModel registry, maintenance actions
├── invariants.py # invariant & rate-limit evaluation, episode aggregation ├── invariants.py # invariant & rate-limit evaluation, episode aggregation
└── engine.py # mode: continuous, parameter() accessor, snapshot scheduler └── engine.py # mode: continuous, parameter() accessor, snapshot
# scheduler; fixed tick pipeline per FR-8.2.12:
# datasets -> edges -> plugins -> degradation ->
# invariants -> scheduled steps -> snapshots
``` ```
```mermaid ```mermaid
erDiagram erDiagram
ContinuousScenario ||--|{ Dataset : datasets ContinuousScenario ||--o{ Dataset : "datasets (optional)"
Dataset ||--|{ ColumnMapping : "alias columns" Dataset ||--|{ ColumnMapping : "alias columns"
ContinuousScenario ||--|{ PlantPlugin : "signal logic (always runs)"
ContinuousScenario ||--|{ DegradationModel : degradation ContinuousScenario ||--|{ DegradationModel : degradation
DegradationModel ||--|{ WearCounter : counts DegradationModel ||--|{ WearCounter : counts
WearCounter }o--|| Alias : observes WearCounter }o--|| Alias : observes
@@ -675,6 +739,7 @@ erDiagram
ContinuousScenario ||--|{ RateLimit : rate_limits ContinuousScenario ||--|{ RateLimit : rate_limits
ContinuousScenario ||--o{ Snapshot : "periodic dumps" ContinuousScenario ||--o{ Snapshot : "periodic dumps"
PlantPlugin }o--|| DegradationModel : "reads parameters" PlantPlugin }o--|| DegradationModel : "reads parameters"
PlantPlugin }o--o{ Alias : "reads dataset-driven + computes logic-driven"
``` ```
### 8.7 Non-functional requirements (long-duration) ### 8.7 Non-functional requirements (long-duration)
@@ -711,6 +776,15 @@ erDiagram
regardless of duration; a rate-limit breach fails the run. regardless of duration; a rate-limit breach fails the run.
8. A full 28-sim-day soak completes headless with a bounded report and a 8. A full 28-sim-day soak completes headless with a bounded report and a
correct PASS/FAIL/ERROR verdict. correct PASS/FAIL/ERROR verdict.
9. A continuous run with **no datasets** (plugin-generated demand,
top-level `until:`) completes with degradation, invariants, rate limits
and snapshots all active, and a correct verdict (FR-8.2.13).
10. A **mixed run** — one alias driven by a dataset, another computed by a
plugin in the same run — is supported; the plugin observes the dataset
value applied earlier in the same tick (FR-8.2.12 order), verified by a
tick-order test.
11. A continuous scenario with no datasets, no scheduled steps, and no
`until:` is rejected at validation time (FR-8.2.1).
--- ---
@@ -824,6 +898,10 @@ Terminal monitors (§9) suffice for single engineers, but FAT benches are
- FR-10.2.9: The UI must not disturb deterministic scenario runs: when a - FR-10.2.9: The UI must not disturb deterministic scenario runs: when a
scenario owns an alias, UI writes to it are rejected with a clear scenario owns an alias, UI writes to it are rejected with a clear
message (alias-ownership rules of §8 FR-8.2.2 apply). message (alias-ownership rules of §8 FR-8.2.2 apply).
- FR-10.2.10: The UI's **configuration** pages (Ethernet/port settings,
Modbus watchdog settings, I/O Config with SAVE CONFIG, Modbus Mapping
overview, address-selection DIP switch) are specified in §11; §10 covers
value/state oversight and manipulation.
### 10.3 Architecture sketch (planned) ### 10.3 Architecture sketch (planned)
@@ -856,19 +934,150 @@ server, so a UI write and a Modbus read never race on the datastore.
--- ---
## 11. Roadmap (post-framework) ## 11. Feature Request — Runtime Device Configuration (WBM/DIP-Switch Parity)
> **Status: requested 2026-10-03, planned (roadmap phase 5), not yet
> implemented.** Mirrors the real 750-362's configuration mechanisms so
> the FAT bench can commission the node the way a real one is
> commissioned.
### 11.1 Motivation
On the real coupler the *node* is configured through two mechanisms
(manual §4.4.2, §8.3, §9.11–9.18):
1. **Web-Based Management (WBM)** pages: Ethernet/port settings (IP
address, subnet, gateway, DHCP/BootP/EEPROM source, base IP), Modbus
settings (connection idle timeout, Modbus watchdog type/timeout/trigger
masks, keepalive), Modbus Mapping (per-module register/coil address map,
read-only), and I/O Config (connected module list + **SAVE CONFIG**,
which re-reads the terminal bus).
2. **Address-selection DIP switch** (8-pole): binary host ID 1–254 = last
IP octet (base network 192.168.1.0/24 in delivery state); 0 = use the
stored WBM port configuration; 255 = DHCP. Changing it requires a
restart to take effect.
The I/O modules themselves are **not** configured via WBM or DIP switch —
they are physically plugged/unplugged, and the coupler re-reads the
terminal bus (SAVE CONFIG / KBUS reset, register `0x102B`), rebuilding
the process image. The simulator equivalent of "plugging" a module is a
**runtime module-list change with image rebuild**.
Today the simulator freezes all of this at startup: module list from
YAML, watchdog only via Modbus registers, no DIP switch, no WBM pages.
This feature request closes that gap.
### 11.2 Requirements — runtime module configuration ("plug/unplug")
- FR-11.2.1: The node's module list shall be **mutable at runtime** via
the web UI (§10), the console monitor (§9), and a programmatic API:
insert/remove modules at slot positions, replicating physical
plug/unplug on the local bus.
- FR-11.2.2: After every change the process image is **rebuilt exactly
like the real device after a KBUS reset** (`0x102B` or WBM SAVE
CONFIG): word modules first in physical order, then bit modules
byte-packed (§7.3.2.1); image sizes updated in `0x1022–0x1025`;
module descriptions updated in `0x2030+` so a polling master sees the
new configuration.
- FR-11.2.3: Scenario aliases are **revalidated** after a rebuild.
Module-based addresses (FR-4.3.11) are position-stable — `DI2.1` stays
on module 2 when earlier slots change — while pool-based indexes may
shift; aliases orphaned by a removal are reported as configuration
errors. This difference shall be documented and covered by tests.
- FR-11.2.4: While a scenario is running, module reconfiguration is
rejected with a clear message (consistent with FR-10.2.9) — deterministic
runs must not be disturbed. In bench mode (§9) it is always allowed.
- FR-11.2.5: A reconfiguration event is logged (sim-time, change
description, new image sizes) and visible in the web UI's I/O Config
page, mirroring the WBM SAVE CONFIG flow.
### 11.3 Requirements — address-selection DIP switch emulation
- FR-11.3.1: An 8-pole address-selection switch shall be emulated per node
with the manual's exact coding (§4.4.2/§8.3.1): DIP 1 = LSB … DIP 8 =
MSB; **1–254** = host ID appended to the base network (default
192.168.1.0/24, changeable); **0** = use the stored port configuration
(WBM port settings); **255** = DHCP (virtual: an address from the
configured DHCP pool is reported).
- FR-11.3.2: The switch shall be visual and operable in the web UI
(toggle poles) and settable in the console/config; the **derived virtual
IP address** is displayed and introspectable via the API.
- FR-11.3.3: **Apply semantics match the device**: a switch change marks
the node "restart required"; on apply (explicit restart command or
`serve` restart) the simulator rebinds its listen address to the
derived IP when running in dedicated-IP mode, or updates the virtual
IP model in shared-IP mode. Outputs and connections behave like a
device restart.
- FR-11.3.4: The stored port configuration (base network, static IP for
switch position 0, DHCP pool) is part of the device state (FR-11.5.1).
### 11.4 Requirements — WBM-equivalent configuration pages (web UI)
- FR-11.4.1: **Port/Ethernet page**: virtual IP settings — configuration
source (static/EEPROM, DHCP, BootP), IP/subnet/gateway, base network for
DIP addressing — persisted as device state and reported alongside the
DIP-derived address.
- FR-11.4.2: **Modbus settings page**: connection idle timeout
(`0x1030`), Modbus watchdog fields (type Standard/Alternative, timeout,
trigger masks FC1–16/FC17–32, close-socket-on-timeout) — the same
fields the real WBM exposes (manual §9.16), mapped 1:1 onto registers
`0x1000–0x100B`. Writes obey the register rules (e.g., timeout not
changeable while the watchdog is active).
- FR-11.4.3: **Modbus Mapping page**: per-module address map generated
from the node layout — word addresses (input RO, output WO, read-back
RW) and bit addresses (input, output, read-back) in the WBM's
`<SR>[.<SO>]`–`<ER>[.<EO>]` notation (manual §9.17), plus the general
area overview of §3.3. Read-only; auto-updates after FR-11.2.2 rebuilds.
- FR-11.4.4: **I/O Config page**: module list (position, article, type,
channel count) + **SAVE CONFIG** button = re-read/rebuild per
FR-11.2.2, mirroring WBM §9.18.
### 11.5 Requirements — persistence & reset
- FR-11.5.1: Device state (module list changes, DIP switch position,
port configuration, watchdog settings written as remanent per `0x100B`)
persists to a device-state file and is reloaded on start — the
simulator's equivalent of the device's EEPROM.
- FR-11.5.2: **Factory reset** (register `0x2043` write, CLI flag, web UI
button): restores delivery state — module list from the node YAML, DIP
switch to 0, watchdog defaults, cleared statistics — and persists that
as the new device state.
### 11.6 Acceptance criteria
1. Removing a module and issuing SAVE CONFIG (or `0x102B`) rebuilds the
image: `0x1022–0x1025` and `0x2030+` reflect the change and a pymodbus
master reading process data sees the new layout.
2. Inserting a module before existing ones leaves module-addressed
aliases (`DI2.1`) pointing at the same module, while pool-indexed
aliases shift by the inserted channel count — asserted by tests.
3. Aliases orphaned by a module removal are reported as errors, not
silently misaddressed.
4. Reconfiguration during a running scenario is rejected; in bench mode
it succeeds and is logged.
5. DIP switch 00001001 (33) derives virtual IP 192.168.1.33; switch 0
shows the stored port configuration; 255 reports a DHCP-pool address;
changing the switch shows "restart required" until applied.
6. Watchdog fields edited on the web settings page behave identically to
register writes (same validation, same statistics).
7. Device state survives a simulator restart; factory reset restores
delivery defaults.
---
## 12. Roadmap (post-framework)
| Phase | Feature | | Phase | Feature |
|---|---| |---|---|
| 2 | Module catalog expansion (analog, counter, SSI, DALI/DSI, serial modules), mailbox parameters; **bench mode tooling (§9)**: `--set` seeding, console monitor, runtime manipulation commands | | 2 | Module catalog expansion (analog, counter, SSI, DALI/DSI, serial modules), mailbox parameters; **bench mode tooling (§9)**: `--set` seeding, console monitor, runtime manipulation commands |
| 3 | **Long-duration simulation (§8)**: CSV dataset playback, degradation models, invariants, soak-test reporting | | 3 | **Long-duration simulation (§8)**: CSV dataset playback, degradation models, invariants, soak-test reporting |
| 4 | FAT report generator (HTML/PDF), scenario comparison, template library per project type | | 4 | FAT report generator (HTML/PDF), scenario comparison, template library per project type |
| 5 | Multi-node orchestration (several couplers in one FAT bench), UDP variant, WBM simulation; **web UI (§10)** | | 5 | Multi-node orchestration (several couplers in one FAT bench), UDP variant, WBM simulation; **web UI (§10)**; **runtime device configuration (§11)**: module hot-configuration with image rebuild, DIP-switch emulation, WBM-equivalent pages, device-state persistence |
| 6 | CI integration: run scenarios headless, export JUnit XML | | 6 | CI integration: run scenarios headless, export JUnit XML |
--- ---
## 12. References ## 13. References
- WAGO 750-362 manual `m07500362_xxxxxxxx_0en.pdf`, sections 7.2–7.3 (process image), 11.2 (Modbus), 12.2 (module data architecture) - WAGO 750-362 manual `m07500362_xxxxxxxx_0en.pdf`, sections 7.2–7.3 (process image), 11.2 (Modbus), 12.2 (module data architecture)
- WAGO I/O System 750 system description `m075xxxxx_xxxxxxxx_0en.pdf` - WAGO I/O System 750 system description `m075xxxxx_xxxxxxxx_0en.pdf`