🚧 Add feature requests
This commit is contained in:
@@ -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
@@ -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`
|
||||||
|
|||||||
Reference in New Issue
Block a user