🚧 Add environment maneuverability

This commit is contained in:
Jonas Bengtsson
2026-10-04 22:48:10 +02:00
parent 68d3c42d79
commit 647c209e89
15 changed files with 850 additions and 46 deletions
+60 -5
View File
@@ -620,14 +620,17 @@ unchanged whether or not CSV streaming is used.
to create and call — a subclass of `PlantEnv` overriding `model()`
(and optionally `is_done()`) in any importable module
(`--env myenvs.pump_station.PumpStationEnv`), or a module-level
factory function. Two runners: (a) `wago-sim serve --env ...` ticks
factory function. Three runners: (a) `wago-sim serve --env ...` ticks
the environment on a **wall-clock-paced** periodic task (10 ms tick
alongside the Modbus server, real-time behavior for a live PLC) and
runs **until manually stopped** (SIGINT/SIGTERM — the existing
graceful-shutdown path); (b) `wago-sim sim --node ... --env ...`
runs headless unpaced (as fast as determinism allows) until
`is_done()` or SIGINT. The scenario-continuous mode (FR-8.2.1-13)
remains a scripted layer on top of the same engine ticks.
graceful-shutdown path); the ticker itself is owned by an
`EnvRunner` on the app so the web UI can stop/pause/resume/reset/
restart it at runtime (FR-10.2.15); (b) `wago-sim sim --node ...
--env ...` runs headless unpaced (as fast as determinism allows)
until `is_done()` or SIGINT. The scenario-continuous mode
(FR-8.2.1-13) remains a scripted layer on top of the same engine
ticks.
### 8.3 Requirements — degradation models (plant logic over time)
@@ -1069,6 +1072,44 @@ Terminal monitors (§9) suffice for single engineers, but FAT benches are
default-fallback guesswork. Persistence (node YAML, config
export) stays **lean**: only explicit non-default entries are
written, so defaults survive a future DEFAULT_RANGE change.
- FR-10.2.15: **Plant environment control** (requested 2026-10-04):
the web UI can load/unload environments at runtime — the CLI's
`--env` becomes the startup default, not the only option. An
**environment card** shows the loaded ref, its state (running /
paused / done / none), sim-time, and tick ms; controls: **start**
(load + tick), **stop** (cancel the ticker, field freezes),
**pause/resume** (ticker cancelled or rescheduled, instance
kept — pause is a deliberate FAT fault: "plant stuck"),
**reset** (`env.reset()`, deterministic fresh episode,
NFR-8.7.3), **restart** (stop + start of the same ref, fresh
instance). Rules: exactly one environment at a time (one decision
source, FR-8.2.15); `is_done()` ends the ticker (state `done`, no
auto-restart); a module-list rebuild (SAVE CONFIG, FR-11.2.1)
**discards** the env — its bindings (channel bindings in the
model, sim state) belong to the old layout, exactly like values
are lost on a KBUS reset; starting a new env is refused while
one is loaded (stop first — explicit, no silent replacement);
readonly mode (FR-10.2.8) disables every mutating control.
- FR-10.2.16: **Environment file authoring** (requested 2026-10-04,
planned): create/modify/delete environment source files (e.g.
`envs/*.py`) through the web UI — an editor pane with the plain
PlantEnv subclass pattern (FR-8.2.17), plus upload/download.
Security note: the UI writing importable Python is remote code
execution **by design**; it requires the same trust boundary as
the bench network (auth, FR-10.2.8) and SHALL be disabled in
readonly mode; delete is refused while the env is loaded; the
on-disk directory must be explicit in configuration (today
`envs/` resolves from the working directory, not the installed
package). Status: planned, roadmap phase 5.
- FR-10.2.17: **Hot reload of environment code** (requested
2026-10-04, implemented same day as part of FR-10.2.15): Python
caches modules in `sys.modules`; a restart of an env whose
source changed on disk would silently reuse the old class.
`load_env(ref, reload=True)` — used by the UI's start/restart —
invalidates the cached module before import so a fresh instance
always picks up the edited code. The CLI's startup `--env` and
the headless `sim` runner do not reload (the process is new
anyway).
### 10.3 Implementation decisions (binding, 2026-10-03)
@@ -1131,6 +1172,10 @@ src/wago_sim/
| `GET/PUT /api/config/modules` | module list CRUD + process-image rebuild | §11 FR-11.2.1–11.2.4 |
| `GET /api/config/export` · `POST /api/config/import` | full configuration (modules + channel names + coupler) as JSON | 10.2.12 |
| `GET/PUT /api/config/channel-names` | read/write per-channel names | 10.2.11 |
| `GET/PUT /api/config/channel-ranges` | read/write analog display ranges | 10.2.14 |
| `GET /api/env` | environment status: ref, state, sim-time, tick ms | 10.2.15 |
| `POST /api/env/start` | load + start an env by ref (refuses while one is loaded) | 10.2.15 |
| `POST /api/env/stop` · `pause` · `resume` · `reset` · `restart` | ticker lifecycle; reset = deterministic fresh episode | 10.2.15 |
### 10.6 Milestones
@@ -1142,7 +1187,10 @@ src/wago_sim/
| M4 | Diagnostics — watchdog/statistics/diagnosis view, reset, fault injection |
| M5 | Configuration — coupler forms; module CRUD with image rebuild and persistence |
| M5a | Channel names (FR-10.2.11) + configuration import/export (FR-10.2.12) + split overview with channel list (FR-10.2.13) |
| M5b | Analog display ranges (FR-10.2.14) |
| M6 | (deferred) Scenario run view (FR-10.2.6) + alias-ownership rejection (FR-10.2.9) |
| M7 | Plant environment control (FR-10.2.15 + FR-10.2.17): runtime load/stop/pause/resume/reset/restart + hot reload |
| M8 | (planned) Environment file authoring (FR-10.2.16) |
### 10.7 Acceptance criteria
@@ -1158,6 +1206,13 @@ src/wago_sim/
with a visible message; the scenario continues unaffected.
6. Two simultaneous browsers stay consistent with each other and with
the Modbus image.
7. **Environment control** (FR-10.2.15): an env started from the UI ticks
paced (its field changes visible to a Modbus master and the overview);
pause freezes the field; reset returns to the initial state; a
module-list SAVE CONFIG discards the loaded env (status none); an
edit to the env source on disk + restart runs the new code (hot
reload); starting while loaded is refused; readonly blocks all
env mutations.
---