📝 Update README & specifications.
This commit is contained in:
@@ -44,6 +44,14 @@ a virtual node whose I/O behavior is driven by scripted scenarios.
|
|||||||
config, 255 = DHCP), WBM-equivalent pages (Port/Ethernet, Modbus
|
config, 255 = DHCP), WBM-equivalent pages (Port/Ethernet, Modbus
|
||||||
settings, Modbus Mapping, I/O Config), and device-state persistence
|
settings, Modbus Mapping, I/O Config), and device-state persistence
|
||||||
with factory reset.
|
with factory reset.
|
||||||
|
- **Host network settings** *(requested, planned — spec §15)*: a
|
||||||
|
Docker-gated, opt-in settings page (`WAGO_SIM_HOSTNET=1` **and**
|
||||||
|
container detection) that lists the host OS's network interfaces
|
||||||
|
and adds/removes/changes their IPv4 addresses through a
|
||||||
|
whitelisted host-side agent — so simulated node re-addressing
|
||||||
|
(DIP dedicated-IP mode) and network-loss fault cases become real
|
||||||
|
on the bench network. Runtime-only changes, snapshot/undo, and an
|
||||||
|
audit log; fully absent (404) when the flag is off.
|
||||||
- **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
|
||||||
@@ -343,6 +351,34 @@ requirement ID for each item in parentheses.
|
|||||||
protocol tracing, diagnostics and fault injection (FR-14.2.5–
|
protocol tracing, diagnostics and fault injection (FR-14.2.5–
|
||||||
14.2.6); scoping questions to answer before planning (§14.3).
|
14.2.6); scoping questions to answer before planning (§14.3).
|
||||||
|
|
||||||
|
### Requested — host network settings (spec §15, not yet scheduled)
|
||||||
|
|
||||||
|
- [ ] Host OS IP settings page (FR-15.2.1–15.2.3): exposed in the web
|
||||||
|
UI only when `WAGO_SIM_HOSTNET=1` **and** running inside Docker
|
||||||
|
(compose sets `WAGO_SIM_IN_DOCKER=1`; `/.dockerenv` as a
|
||||||
|
supplementary signal); authenticated page listing the host's
|
||||||
|
interfaces with link state and current IPv4 addresses, read
|
||||||
|
from live host state, with add/remove/change-address operations
|
||||||
|
validated client- and agent-side; routes answer 404 when
|
||||||
|
disabled — no dormant surface.
|
||||||
|
- [ ] Host-side agent + safety rails (FR-15.2.4–15.2.8): a
|
||||||
|
whitelisted companion service on the host (Unix socket mounted
|
||||||
|
into the container; `pyroute2`/`ip` on Linux v1, systemd unit in
|
||||||
|
`deploy/`) — interface whitelist, runtime-only (non-persistent)
|
||||||
|
address changes so a host reboot restores deployed addressing,
|
||||||
|
snapshot before every mutation with undo/restore, single-line
|
||||||
|
audit log; degraded state (agent unreachable) shows a banner
|
||||||
|
and answers 503 without affecting the rest of the UI; readonly
|
||||||
|
mode hides the page and 403s mutations.
|
||||||
|
- [ ] DIP dedicated-IP integration (FR-15.2.9): applying a DIP-switch
|
||||||
|
address change in dedicated-IP mode routes through the agent so
|
||||||
|
the derived IP lands on the host NIC — the PLC on the bench
|
||||||
|
network must genuinely re-connect to the new node address, like
|
||||||
|
a physical coupler after a DIP change (ties into §11
|
||||||
|
FR-11.3.3); scoping questions (platform scope, bridge vs host
|
||||||
|
networking, agent auth, IPv6, link up/down) in §15.4 before
|
||||||
|
planning.
|
||||||
|
|
||||||
### Web UI (spec §10) — in implementation
|
### Web UI (spec §10) — in implementation
|
||||||
|
|
||||||
- [x] Spec §10.3–10.6 updated with binding implementation decisions:
|
- [x] Spec §10.3–10.6 updated with binding implementation decisions:
|
||||||
|
|||||||
+186
-5
@@ -7,7 +7,7 @@
|
|||||||
| Project | `wago-modbustcp-simulator-py` |
|
| Project | `wago-modbustcp-simulator-py` |
|
||||||
| Version | 1.4 (Draft for review) |
|
| Version | 1.4 (Draft for review) |
|
||||||
| Date | 2026-10-03 |
|
| Date | 2026-10-03 |
|
||||||
| 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 |
|
| 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), and host network settings (§15) requested 2026-10-06 |
|
||||||
| 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) |
|
||||||
|
|
||||||
@@ -1018,7 +1018,8 @@ Terminal monitors (§9) suffice for single engineers, but FAT benches are
|
|||||||
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,
|
- FR-10.2.10: The UI's **configuration** pages (Ethernet/port settings,
|
||||||
Modbus watchdog settings, I/O Config with SAVE CONFIG, Modbus Mapping
|
Modbus watchdog settings, I/O Config with SAVE CONFIG, Modbus Mapping
|
||||||
overview, address-selection DIP switch) are specified in §11; §10 covers
|
overview, address-selection DIP switch) are specified in §11; the
|
||||||
|
Docker-gated host network settings page is specified in §15. §10 covers
|
||||||
value/state oversight and manipulation.
|
value/state oversight and manipulation.
|
||||||
- FR-10.2.11: **Channel names** (requested 2026-10-03): every module
|
- FR-10.2.11: **Channel names** (requested 2026-10-03): every module
|
||||||
channel can carry an application-specific name (e.g. `start_button`,
|
channel can carry an application-specific name (e.g. `start_button`,
|
||||||
@@ -1594,7 +1595,187 @@ the same process-image core.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 15. Roadmap (post-framework)
|
## 15. Feature Request — Host Network Settings (Docker Bench Host)
|
||||||
|
|
||||||
|
> **Status: requested 2026-10-06, not yet planned into a roadmap
|
||||||
|
> phase.** A settings page in the web UI that views and manipulates
|
||||||
|
> the **host OS's IP addresses**, exposed only when an explicit
|
||||||
|
> environment flag is set **and** the simulator runs inside Docker.
|
||||||
|
> This section captures the requirements and the enabling
|
||||||
|
> architecture (a whitelisted host-side agent); it does not commit to
|
||||||
|
> a schedule.
|
||||||
|
|
||||||
|
### 15.1 Motivation
|
||||||
|
|
||||||
|
A containerized simulator (§12) cannot reach beyond its own network
|
||||||
|
namespace. It can rebind its listen address (FR-11.3.3 dedicated-IP
|
||||||
|
mode), but the **host's** network interfaces — what the bench network
|
||||||
|
and the PLC under test actually see — are outside the container. As a
|
||||||
|
result, FAT cases that depend on *network-level* events cannot be
|
||||||
|
staged from inside the simulator today:
|
||||||
|
|
||||||
|
- "Re-addressing" the virtual coupler (DIP switch, FR-11.3.1–11.3.3)
|
||||||
|
changes nothing on the bench network in the default bridge
|
||||||
|
deployment: the PLC keeps talking to the unchanged host address, so
|
||||||
|
the reconnect/re-addressing logic in the PLC program is never
|
||||||
|
exercised.
|
||||||
|
- Cable-pull / node-power-off fault cases require stopping the whole
|
||||||
|
container (coarse — every port drops at once) or shell access to the
|
||||||
|
bench host, breaking the "operate everything from the browser"
|
||||||
|
workflow of the web UI (§10).
|
||||||
|
- Moving the simulated node to a different subnet mid-bench
|
||||||
|
(multi-bench swaps, address conflicts) likewise needs host access.
|
||||||
|
|
||||||
|
The requested feature closes the gap: an opt-in settings page through
|
||||||
|
which an authenticated operator changes the host OS's IP addresses
|
||||||
|
from the bench UI — making the simulated node's network identity
|
||||||
|
**real on the bench network**, and making network-level fault cases
|
||||||
|
first-class FAT scenarios.
|
||||||
|
|
||||||
|
### 15.2 Requirements
|
||||||
|
|
||||||
|
- FR-15.2.1: **Opt-in via environment flag.** The feature is disabled
|
||||||
|
unless `WAGO_SIM_HOSTNET` is set truthy (same semantics as
|
||||||
|
`WAGO_SIM_VERBOSE`: `1`/`true`/`yes`/`on`); the flag lives in the
|
||||||
|
compose file so enabling it is a visible, deliberate deployment
|
||||||
|
change. Default: off. When off, the page is absent and every
|
||||||
|
`/api/hostnet/*` route answers 404 — no dormant surface.
|
||||||
|
- FR-15.2.2: **Docker-only.** Independently, the simulator must detect
|
||||||
|
a container environment — binding: the compose file sets
|
||||||
|
`WAGO_SIM_IN_DOCKER=1` (supplementary signal: `/.dockerenv` exists).
|
||||||
|
Outside docker the routes stay 404 regardless of the flag: a
|
||||||
|
bare-metal operator has direct access to the OS network settings;
|
||||||
|
the page exists precisely because a container does not.
|
||||||
|
- FR-15.2.3: **Settings page.** A page in the web UI's configuration
|
||||||
|
area (alongside the Port/Ethernet page, FR-11.4.1) listing the
|
||||||
|
host's network interfaces — name, link state, current IPv4
|
||||||
|
addresses — read from **live host state**, not a desired-state
|
||||||
|
mirror, so out-of-band changes made on the host appear on refresh.
|
||||||
|
The page also shows the agent's health and the effective whitelist.
|
||||||
|
- FR-15.2.4: **Operations.** Add an address (address + prefix length),
|
||||||
|
remove an address, replace an interface's primary address — each
|
||||||
|
validated client-side and agent-side (address/prefix syntax,
|
||||||
|
interface exists, interface whitelisted). Changes are
|
||||||
|
**runtime-only** (like `ip addr add`: non-persistent across host
|
||||||
|
reboots); v1 deliberately does not write netplan/NetworkManager/
|
||||||
|
systemd-networkd configuration, so a host reboot is a guaranteed
|
||||||
|
escape hatch back to the deployed addressing. Optional v2, behind
|
||||||
|
the same whitelist and an explicit "disruptive" confirmation: set
|
||||||
|
an interface's link up/down (cable-pull simulation).
|
||||||
|
- FR-15.2.5: **Safety rails.** The agent enforces an interface
|
||||||
|
**whitelist** from its own config file (operations on other
|
||||||
|
interfaces are refused and surfaced as errors on the page); it
|
||||||
|
snapshots an interface's address set before every mutation, and the
|
||||||
|
page offers **undo last** / **restore interface**; every mutation
|
||||||
|
and every refusal is appended to a single-line **audit log**
|
||||||
|
(operator session, interface, old → new, timestamp) written to
|
||||||
|
stdout/journald like the simulator's own logging (FR-12.2.6) and
|
||||||
|
viewable (bounded) on the page.
|
||||||
|
- FR-15.2.6: **Trust boundary** (same stance as FR-10.2.16): the page
|
||||||
|
requires an authenticated session (FR-10.2.8); read-only mode
|
||||||
|
(`WAGO_SIM_WEB_READONLY`) hides the page and answers mutations with
|
||||||
|
403. Changing host addresses is a privileged operation by design —
|
||||||
|
the flag must never be set on a network the operator does not
|
||||||
|
control.
|
||||||
|
- FR-15.2.7: **Host-side agent** (binding architecture decision). A
|
||||||
|
container cannot change host addresses, and the simulator container
|
||||||
|
itself shall not run privileged (§12 non-root, least-privilege
|
||||||
|
deployment). Instead a small companion service —
|
||||||
|
`wago-sim-hostnet-agent` — runs **on the host** (systemd unit in
|
||||||
|
`deploy/`, root or `CAP_NET_ADMIN`), listening on a Unix domain
|
||||||
|
socket that the compose file mounts into the container read-write.
|
||||||
|
The agent's protocol is a narrow whitelist of operations (health,
|
||||||
|
list, snapshot, address add/remove/change, restore) over JSON
|
||||||
|
lines; it never executes a shell with operator input — on Linux v1
|
||||||
|
it uses the netlink API (`pyroute2`, with the `ip` tool as a
|
||||||
|
fallback). *Rejected alternative, documented why*: running the
|
||||||
|
simulator container itself privileged with host namespaces — it
|
||||||
|
forfeits the non-root deployment and couples host control to the
|
||||||
|
simulator's own lifecycle and restarts.
|
||||||
|
- FR-15.2.8: **Degraded states never break the UI.** Flag set but the
|
||||||
|
agent socket absent/unreachable: the page shows a clear "host
|
||||||
|
control unavailable" banner and mutation routes answer 503 with a
|
||||||
|
message; the Modbus server and the rest of the web UI are
|
||||||
|
unaffected.
|
||||||
|
- FR-15.2.9: **DIP dedicated-IP integration** (FR-11.3.3). When a DIP
|
||||||
|
address change is applied in dedicated-IP mode and the derived
|
||||||
|
interface is whitelisted, the apply step may route through the same
|
||||||
|
agent — the derived IP is added to the host NIC — so the PLC on the
|
||||||
|
bench network must genuinely re-connect to the new node address,
|
||||||
|
exactly like a physical coupler after a DIP change. Under
|
||||||
|
`network_mode: host` the simulator rebinds directly per FR-11.3.3;
|
||||||
|
either way the agent supplies the address on the host.
|
||||||
|
|
||||||
|
### 15.3 Architecture sketch (planned)
|
||||||
|
|
||||||
|
```
|
||||||
|
bench host (Linux)
|
||||||
|
├── wago-sim hostnet-agent --config /etc/wago-sim/hostnet.yaml
|
||||||
|
│ (systemd unit: deploy/wago-sim-hostnet-agent.service;
|
||||||
|
│ root or CAP_NET_ADMIN — it owns the interface whitelist)
|
||||||
|
│ config: socket: /run/wago-sim/hostnet.sock, whitelist: [...]
|
||||||
|
└── docker compose
|
||||||
|
├── mounts /run/wago-sim:/run/wago-sim (agent socket in)
|
||||||
|
└── wago-sim serve (page + /api/hostnet/* routes,
|
||||||
|
gated by FR-15.2.1 flag + FR-15.2.2 docker detection)
|
||||||
|
```
|
||||||
|
|
||||||
|
Web API, mounted only under the FR-15.2.1/2 gates:
|
||||||
|
|
||||||
|
| Method/Route | Purpose | FR |
|
||||||
|
|---|---|---|
|
||||||
|
| `GET /api/hostnet` | availability (flag, docker, agent health) + interface/address list + whitelist | 15.2.3 |
|
||||||
|
| `POST /api/hostnet/interfaces/{name}/addresses` | add an address (address, prefix length) | 15.2.4 |
|
||||||
|
| `DELETE /api/hostnet/interfaces/{name}/addresses/{addr}` | remove an address | 15.2.4 |
|
||||||
|
| `POST /api/hostnet/interfaces/{name}/restore` | undo last / restore snapshot | 15.2.5 |
|
||||||
|
| `GET /api/hostnet/audit` | bounded recent audit lines | 15.2.5 |
|
||||||
|
|
||||||
|
### 15.4 Scoping questions (answer before planning)
|
||||||
|
|
||||||
|
1. Platform scope v1: Linux bench hosts only (agent via `pyroute2`)?
|
||||||
|
Windows hosts run the container inside Docker Desktop/WSL2 — the
|
||||||
|
container's "host" is the WSL2 VM; reaching the Windows NICs needs
|
||||||
|
a Windows-side agent over a named pipe — defer or include?
|
||||||
|
2. Networking-mode story for the DIP integration (FR-15.2.9): keep
|
||||||
|
the current bridge deployment (host IP + mapped port) as v1, or
|
||||||
|
require `network_mode: host` for full parity (node IP == host IP,
|
||||||
|
port 502)?
|
||||||
|
3. Agent authentication: Unix-socket file permissions only, or a
|
||||||
|
shared token in the agent config to defend against other local
|
||||||
|
users?
|
||||||
|
4. IPv6 in v1 or deferred?
|
||||||
|
5. Does link up/down (cable pull) belong in v1 — it can sever the
|
||||||
|
operator's own web UI session on that NIC — or are address
|
||||||
|
add/remove/change sufficient for the planned FAT cases?
|
||||||
|
|
||||||
|
### 15.5 Acceptance criteria (draft)
|
||||||
|
|
||||||
|
1. Without `WAGO_SIM_HOSTNET`: no page; all `/api/hostnet/*` routes
|
||||||
|
answer 404; the rest of the UI unchanged (regression suite green).
|
||||||
|
2. Flag set but not in docker: same as 1.
|
||||||
|
3. Flag set + docker + agent reachable: the page lists the host's real
|
||||||
|
interfaces; adding `192.168.1.33/24` to the whitelisted interface
|
||||||
|
shows in `ip addr` **on the host**, and the new address is
|
||||||
|
reachable from the bench network (a master connects through it).
|
||||||
|
4. Removing that address severs the master's connection through it —
|
||||||
|
the PLC's reconnect logic is exercised (the FAT case).
|
||||||
|
5. Restore/undo returns the interface to its pre-change snapshot; a
|
||||||
|
host reboot likewise restores the deployed addressing (changes are
|
||||||
|
runtime-only, FR-15.2.4).
|
||||||
|
6. An operation on a non-whitelisted interface is refused by the
|
||||||
|
agent and surfaced as an error on the page; the audit log records
|
||||||
|
every mutation and every refusal.
|
||||||
|
7. Read-only mode: page hidden, mutations 403.
|
||||||
|
8. DIP integration: applying switch position 33 in dedicated-IP mode
|
||||||
|
results in `192.168.1.33` present on the whitelisted NIC (bridge
|
||||||
|
mode) or the server rebind (host mode); the "restart required"
|
||||||
|
semantics of FR-11.3.3 are unchanged.
|
||||||
|
9. Agent socket missing: "host control unavailable" banner,
|
||||||
|
mutations 503, Modbus server and the rest of the web UI unaffected.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 16. Roadmap (post-framework)
|
||||||
|
|
||||||
| Phase | Feature |
|
| Phase | Feature |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -1603,11 +1784,11 @@ the same process-image core.
|
|||||||
| 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)**; **runtime device configuration (§11)**: module hot-configuration with image rebuild, DIP-switch emulation, WBM-equivalent pages, device-state persistence |
|
| 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 |
|
||||||
| ? | **Multi-vendor device profiles (§13)** and **additional fieldbus protocols PROFINET/COMLI (§14)** — not yet scheduled; phase assignment after §13.3/§14.3 scoping |
|
| ? | **Multi-vendor device profiles (§13)**, **additional fieldbus protocols PROFINET/COMLI (§14)**, and **host network settings (§15)** — not yet scheduled; phase assignment after §13.3/§14.3/§15.4 scoping |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 16. References
|
## 17. 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