🚧 Implement continous simulation
This commit is contained in:
+22
-20
@@ -7,7 +7,7 @@
|
||||
| Project | `wago-modbustcp-simulator-py` |
|
||||
| Version | 1.4 (Draft for review) |
|
||||
| Date | 2026-10-03 |
|
||||
| Status | Framework phase; module addressing implemented (FR-4.3.11); service/container deployment implemented (§12); plain-text request tracing implemented (NFR-6.4); clean CLI error handling implemented (NFR-6.5 CLI part); web UI §10 in implementation (M1–M5a done: auth, overview, manipulation, diagnostics, configuration, channel names, import/export, split overview; M6 scenario view open); long-duration simulation (§8), bench mode (§9), runtime device configuration (§11 — coupler/module/channel-name subset now covered by web UI M5/M5a), multi-vendor device profiles (§13) and additional fieldbus protocols PROFINET/COMLI (§14) requested |
|
||||
| Status | Framework phase; module addressing implemented (FR-4.3.11 v1.5 per-type numbering); service/container deployment implemented (§12); plain-text request tracing implemented (NFR-6.4); clean CLI error handling implemented (NFR-6.5 CLI part); web UI §10 in implementation (M1–M5a done: auth, overview, manipulation, diagnostics, configuration, channel names, import/export, split overview; M6 scenario view open); long-duration simulation (§8) implemented 2026-10-04 incl. PlantEnv (FR-8.2.14–16), datasets, degradation, invariants, snapshots; bench mode (§9), runtime device configuration (§11 — coupler/module/channel-name subset covered by web UI M5/M5a), multi-vendor device profiles (§13) and additional fieldbus protocols PROFINET/COMLI (§14) requested |
|
||||
| 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) |
|
||||
|
||||
@@ -478,8 +478,8 @@ stateDiagram-v2
|
||||
|
||||
## 8. Feature Request — Long-Duration (Continuous) Simulation
|
||||
|
||||
> **Status: requested 2026-10-03, planned (roadmap phase 3), not yet implemented.**
|
||||
> Extends the scenario engine (§4) with a `continuous` mode for endurance
|
||||
> **Status: implemented 2026-10-04** (roadmap phase 3 complete). Extends
|
||||
> the scenario engine (§4) with a `continuous` mode for endurance
|
||||
> (“soak”) testing: the facility runs for hours, days or weeks of simulated
|
||||
> time against evolving inputs and an aging plant.
|
||||
|
||||
@@ -626,8 +626,11 @@ unchanged whether or not CSV streaming is used.
|
||||
load-hours (integral of the analog value). Counters are deterministic state.
|
||||
- FR-8.3.2: A **degradation model** computes a named plant parameter (e.g.
|
||||
`pump_capacity`, range 0…1) from wear counters and sim-time. Built-in
|
||||
shapes: `linear` (per runtime hour, per start cycle), `exponential`,
|
||||
`staircase` (threshold table); custom shapes via Python plugin.
|
||||
shapes: `linear` (per runtime hour via `rate:`, or per start cycle with
|
||||
`per: cycles`), `exponential`, `staircase` (`staircase:` level table).
|
||||
A model is configured with `observes:` naming the alias whose wear
|
||||
counts feed it (NB: the key is `observes` — a YAML `on` key would be
|
||||
parsed as boolean True by YAML 1.1).
|
||||
- FR-8.3.3: Plant-model plugins read degraded parameters via
|
||||
`engine.parameter("pump_capacity")` and shall use them in the loop physics
|
||||
(e.g., actual pump flow = nominal flow × capacity), so the PLC must
|
||||
@@ -702,31 +705,30 @@ datasets:
|
||||
repeat: 4
|
||||
|
||||
degradation:
|
||||
pump_wear:
|
||||
pump_capacity:
|
||||
observes: pump_relay # wear counts from this alias
|
||||
model: linear
|
||||
parameter: pump_capacity # consumed by the plant model
|
||||
per_runtime_hour: 0.0004 # 0.04 %/h → ~10 % after ~10.4 sim-days
|
||||
per_start_cycle: 0.0002 # 0.02 % per start
|
||||
floor: 0.80
|
||||
maintenance_at: 0.90
|
||||
on_threshold: # fires when capacity crosses 90 %
|
||||
- inject_diagnosis: { module: 4, channel: 1, bits: [user_overrange] }
|
||||
- assert: { label: "maintenance alarm raised",
|
||||
conditions: { maintenance_alarm: ON }, within: 60s }
|
||||
on_reset: # after maintenance_reset
|
||||
- clear_diagnosis: { module: 4 }
|
||||
rate: 0.0004 # -0.04 %/h runtime → ~10 % after ~10.4 sim-days
|
||||
from: 1.0
|
||||
maintenance_at: 0.90 # threshold crossing injects diagnosis
|
||||
diagnosis: { module: 4, channel: 1, value: 0x0001 }
|
||||
# the PLC raises maintenance_alarm; the scenario asserts it:
|
||||
|
||||
sequence: # scheduled events (sim-time)
|
||||
- at: 12d
|
||||
maintenance_reset: pump_wear # service visit: capacity restored
|
||||
maintenance_reset: true # service visit: capacity restored
|
||||
- at: 12d
|
||||
assert: { label: "maintenance alarm raised",
|
||||
conditions: { maintenance_alarm: ON }, within: 60s }
|
||||
|
||||
plugins: [plugins.pump_plant.pump_plant] # loop: d(level)/dt = inflow − pump_flow(speed, capacity)
|
||||
|
||||
invariants:
|
||||
- { alias: level_sensor, min: 200, max: 9000, label: "tank level bounds" }
|
||||
- { alias: level_sensor, condition: '>= 200', label: "tank level floor" }
|
||||
- { alias: level_sensor, condition: '<= 9000', label: "tank level brim" }
|
||||
|
||||
rate_limits:
|
||||
- { alias: pump_relay, edge: rising, max_per_hour: 6, label: "pump start cycles" }
|
||||
- { alias: speed_setpoint, max_per_hour: 3000 } # ramp-rate bound
|
||||
|
||||
report:
|
||||
snapshot_every: 1h
|
||||
|
||||
Reference in New Issue
Block a user