The single auto-refreshing zero-JS status page gave operators a 25-column wall and no way to drill into one connection. This adds a Bootstrap fleet dashboard (filterable/sortable KPI table) and a per-PLC detail page with a real-time debug view of raw PLC-side BCD vs. decoded client-side values, streamed live over a SignalR feed. The debug view is fed by an on-demand per-tag value capture, armed only while a detail page is open. All assets (Bootstrap, SignalR client, fonts) are embedded so the UI works unchanged on firewalled networks; GET /status.json is untouched for scrapers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DL205 Modbus Simulator
Wraps the dl205.json pymodbus profile as a standalone launcher and as an xUnit managed lifecycle.
Manual launch
pwsh tests/sim/run-dl205-sim.ps1 -Port 5020
On first run the script creates a Python venv at tests/sim/.venv and installs:
pymodbus==3.13.0
aiohttp
(pymodbus 3.13.0 does not provide a [server] extra; the simulator is included in
the base package. aiohttp is required by the simulator's HTTP console.)
Re-runs detect the existing venv and skip provisioning (fast path, < 2 s to first packet).
Ctrl-C exits cleanly. The venv directory is gitignored.
Requirements
- Python 3.10+ on
PATH(tested with 3.13). The script also tries the Windowspylauncher. - Network access for first-run venv provisioning. Subsequent runs are fully offline.
Parameters
| Parameter | Default | Description |
|---|---|---|
-Profile |
dl205.json |
pymodbus JSON device profile |
-Port |
5020 |
TCP port the Modbus server binds |
xUnit integration
Test classes that need a live simulator declare:
[Collection(nameof(DL205SimulatorCollection))]
The DL205SimulatorFixture (in tests/Mbproxy.Tests/Sim/) spawns run-dl205-sim.ps1 via pwsh -NoProfile -File, polls for a TCP connection within 10 s, and exposes Host, Port, and LogTail. If Python is unavailable, SkipReason is populated and every test in the collection skips cleanly rather than failing.
Version pin
pymodbus[server]==3.13.0 — update this README and run-dl205-sim.ps1 together when re-pinning.