56eee3c563
Adds the mbproxy service end-to-end. Phases 00-08 implement the production-ready single-listener / 1:1-backend transparent Modbus TCP proxy with bidirectional BCD rewriting for the ~54-PLC DL205/DL260 fleet. Phase 9 replaces the connection layer with a single backend socket per PLC plus MBAP TxId rewriting, lifting the H2-ECOM100's 4-concurrent-client cap as an operational ceiling. Phase 9 additions of note: - PlcMultiplexer + UpstreamPipe + TxIdAllocator + CorrelationMap - InFlightRequest with IReadOnlyList<InterestedParty> (load-bearing for Phase 10 read coalescing — do not collapse to a single field) - Per-request watchdog: surfaces Modbus exception 0x0B to upstream on BackendRequestTimeoutMs, defending against lost responses, dead-PLC paths, and pymodbus 3.13.0's concurrent-multiplexed- request bug (its ServerRequestHandler.last_pdu state race) - Status DTO + HTML gain inFlight / maxInFlight / txIdWraps / disconnectCascades / queueDepth (Tier 1.6 in docs/kpi.md) Tests: 263 unit + 38 E2E. Multiplexer correctness under truly concurrent backend traffic is proved against a stub backend in PlcMultiplexerTests; MultiplexerE2ETests paces requests so pymodbus 3.13's single-PDU framer stays in known-good mode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
50 lines
1.7 KiB
Markdown
50 lines
1.7 KiB
Markdown
# DL205 Modbus Simulator
|
|
|
|
Wraps the `DL260/dl205.json` pymodbus profile as a standalone launcher and as an xUnit managed lifecycle.
|
|
|
|
## Manual launch
|
|
|
|
```powershell
|
|
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 Windows `py` launcher.
|
|
- Network access for first-run venv provisioning. Subsequent runs are fully offline.
|
|
|
|
## Parameters
|
|
|
|
| Parameter | Default | Description |
|
|
|------------|--------------------------------|------------------------------------|
|
|
| `-Profile` | `../../DL260/dl205.json` | pymodbus JSON device profile |
|
|
| `-Port` | `5020` | TCP port the Modbus server binds |
|
|
|
|
## xUnit integration
|
|
|
|
Test classes that need a live simulator declare:
|
|
|
|
```csharp
|
|
[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.
|