🚧 Web UI

This commit is contained in:
Jonas Bengtsson
2026-10-03 23:48:16 +02:00
parent 43c4c287a0
commit 87c1c8db7b
22 changed files with 2558 additions and 15 deletions
+69 -10
View File
@@ -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); long-duration simulation (§8), bench mode (§9), web UI (§10), runtime device configuration (§11), multi-vendor device profiles (§13) and additional fieldbus protocols PROFINET/COMLI (§14) requested |
| 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–M5 done: auth, overview, manipulation, diagnostics, configuration; M6 scenario view open); long-duration simulation (§8), bench mode (§9), runtime device configuration (§11 — coupler/module subset now covered by web UI M5), 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) |
@@ -865,9 +865,11 @@ at runtime without a scenario driving it.
## 10. Feature Request — Web UI (I/O Overview & Manipulation)
> **Status: requested 2026-10-03, planned (roadmap phase 5), not yet
> implemented.** A browser front-end overlooking and manipulating the
> simulated node's I/O values and states at runtime.
> **Status: in implementation (2026-10-03).** The implementation
> decisions below are binding; milestones M1–M4 are implemented and
> verified (M5 configuration and M6 scenario view remain). A browser
> front-end overlooking and manipulating the simulated node's I/O
> values and states at runtime.
### 10.1 Motivation
@@ -918,21 +920,78 @@ Terminal monitors (§9) suffice for single engineers, but FAT benches are
overview, address-selection DIP switch) are specified in §11; §10 covers
value/state oversight and manipulation.
### 10.3 Architecture sketch (planned)
### 10.3 Implementation decisions (binding, 2026-10-03)
- **Framework**: FastAPI (Starlette) + Uvicorn, embedded **in-process on
the same asyncio event loop** as the Modbus TCP server — a UI write and
a Modbus request never race on the datastore.
- **Front-end**: single-page vanilla HTML/CSS/JS (no build step) under
`src/wago_sim/webui/static/`; realistic node graphics (DIN-rail strip,
module bezels, glowing per-channel LEDs for DI/DO, bar/numeric
indicators for AI/AO) drawn with inline SVG/CSS.
- **Authentication** (user request 2026-10-03): session-cookie login with
in-memory token store; default credentials `admin` / `simu`,
overridable via env (`WAGO_SIM_WEB_USER` / `WAGO_SIM_WEB_PASSWORD`);
optional read-only mode via `WAGO_SIM_WEB_READONLY`. No third-party
auth/session dependencies (`hashlib.scrypt` hashing; sessions need not
survive restarts on a bench).
- **Backend data access** (user request 2026-10-03): the API **never uses
Modbus TCP**. It reads via the internal memory handler
(`WagoDatastore` getters, `VirtualNode` channel model,
`ConfigRegisterBank`, `ModbusWatchdog`, `ModbusStatistics`) and writes
via internal paths chosen by role: simulated-field writes go through
`set_digital_input_channel()` / `set_input_word()` (as the scenario
engine does); master-side forcing goes through the datastore's
internal `write_bits()` / `write_words()` dispatch (mirrors, watchdog
kicks, and statistics stay consistent, FR-9.2.6 semantics) — but
always as direct in-process calls, never via TCP.
- **Live updates**: WebSocket push (`/api/ws`) — datastore
`add_listener` for output changes plus a 10 Hz snapshot-difference
sweep for input-side changes.
- **Wiring**: `serve` starts the web UI by default (`--no-web` to
disable; `--web-port`, env `WAGO_SIM_WEB_PORT`; default port 8080).
### 10.4 Architecture sketch (as-built)
```
src/wago_sim/
├── webui/
│ ├── __init__.py
│ ├── app.py # HTTP + WebSocket server (asyncio, same loop as Modbus)
│ ├── api.py # REST endpoints: node layout, values, writes, diagnostics
│ ├── app.py # build_webui(app, ...) -> FastAPI; API + static
│ ├── auth.py # login/logout, scrypt hash, session dependency
│ ├── state.py # snapshot builder + change detection
│ ├── api.py # REST + WebSocket routes
│ └── static/ # single-page front-end (no build step)
```
The web server runs **in the same asyncio event loop** as the Modbus TCP
server, so a UI write and a Modbus read never race on the datastore.
### 10.5 API surface (as-built)
### 10.4 Acceptance criteria
| Method/Route | Purpose | FR |
|---|---|---|
| `POST /api/auth/login`, `POST /api/auth/logout` | session cookie (`HttpOnly`) | auth |
| `GET /api/node` | module list, channel tables with `DI0.1`-style and Modbus addresses | 10.2.2 |
| `GET /api/values` | full channel-value snapshot | 10.2.3 |
| `WS /api/ws` | live value/state deltas | 10.2.3, 10.2.7 |
| `POST /api/channels/{kind}/{module}/{channel}` | set/toggle/pulse/ramp a channel (field side) | 10.2.4 |
| `POST /api/force` | master-side force at a Modbus address (internal dispatch) | 10.2.4 |
| `GET /api/diagnostics` | watchdog status, statistics, module diagnosis, LED errors | 10.2.5 |
| `POST /api/diagnostics/reset-stats` | statistics reset (0x1029 semantics) | 10.2.5 |
| `POST /api/diagnostics/inject-fault`, `POST /api/diagnostics/clear-fault` | LED / module-diagnosis injection | 10.2.5 |
| `GET/PUT /api/config/coupler` | watchdog settings, response delay, idle timeout, MAC-ID | §11 subset |
| `GET/PUT /api/config/modules` | module list CRUD + process-image rebuild | §11 FR-11.2.1–11.2.4 |
### 10.6 Milestones
| # | Deliverable |
|---|---|
| M1 | WebUI skeleton, in-process FastAPI, CLI/env wiring, authentication (`admin`/`simu`), `GET /api/node` |
| M2 | Node overview page — DIN-rail graphics, LEDs, analog indicators, live values (WS) |
| M3 | Manipulation — toggle/pulse/ramp, AI engineering units, master-side force |
| M4 | Diagnostics — watchdog/statistics/diagnosis view, reset, fault injection |
| M5 | Configuration — coupler forms; module CRUD with image rebuild and persistence |
| M6 | (deferred) Scenario run view (FR-10.2.6) + alias-ownership rejection (FR-10.2.9) |
### 10.7 Acceptance criteria
1. Opening the UI shows the node's module list and channel table exactly
as configured, with `DI0.1`-style addresses and Modbus addresses.