mbproxy/docs: retire superseded design/plan docs and dissolve DL260/
The standalone design.md, kpi.md, operations.md, and the docs/plan/ phase tree were point-in-time planning artefacts now superseded by the topic-organized docs/ tree (Architecture/, Features/, Operations/, Reference/, Testing/). The DL260/ folder mixed a device-reference doc, a test fixture, a sample test, and a screenshot; its contents now live in their natural homes (dl205.md + mbtcp_settings.JPG under docs/Reference/, dl205.json next to its launcher in tests/sim/, sample test dropped). All cross-references in the surviving docs, README, CLAUDE.md, the config template, and source comments are repointed to the new locations. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,9 @@ The pymodbus DL205 simulator stands in for real DL205/DL260 hardware in the E2E
|
||||
|
||||
## Why a Simulator
|
||||
|
||||
`mbproxy` targets a fleet of AutomationDirect DL205/DL260 controllers that test machines do not have. The pymodbus profile at [`../../DL260/dl205.json`](../../DL260/dl205.json) already models the device-side quirks (BCD nibbles at known holding-register addresses, CDAB-ordered 32-bit values, C-relay/Y-output coil mappings) as concrete register seeds. The harness wraps that profile in an xUnit `IAsyncLifetime` fixture so every E2E test class opens against a fresh known-good DL-series target without manual setup.
|
||||
`mbproxy` targets a fleet of AutomationDirect DL205/DL260 controllers that test machines do not have. The pymodbus profile at [`../../tests/sim/dl205.json`](../../tests/sim/dl205.json) already models the device-side quirks (BCD nibbles at known holding-register addresses, CDAB-ordered 32-bit values, C-relay/Y-output coil mappings) as concrete register seeds. The harness wraps that profile in an xUnit `IAsyncLifetime` fixture so every E2E test class opens against a fresh known-good DL-series target without manual setup.
|
||||
|
||||
The device-side rationale for each seed (why HR 1072 is `0x1234`, why FC03 caps at 128, etc.) lives in [`../../DL260/dl205.md`](../../DL260/dl205.md). The harness exists to make that profile addressable from xUnit tests; it does not duplicate the device documentation.
|
||||
The device-side rationale for each seed (why HR 1072 is `0x1234`, why FC03 caps at 128, etc.) lives in [`../Reference/dl205.md`](../Reference/dl205.md). The harness exists to make that profile addressable from xUnit tests; it does not duplicate the device documentation.
|
||||
|
||||
## Harness Layout
|
||||
|
||||
@@ -72,7 +72,7 @@ if (_sim.SkipReason is not null)
|
||||
Assert.Skip(_sim.SkipReason);
|
||||
```
|
||||
|
||||
The unit-test suite (any test without `[Trait("Category", "E2E")]`) runs without any Python at all. CI machines must have Python 3.10+ and PowerShell 7+; local developers running only unit tests need nothing extra. The phase-01 gate (see [`../plan/README.md`](../plan/README.md)) explicitly verifies that on a machine with Python and pymodbus installed, none of the smoke tests skip — a skip on a properly equipped CI machine is treated as an environment failure, not a test pass.
|
||||
The unit-test suite (any test without `[Trait("Category", "E2E")]`) runs without any Python at all. CI machines must have Python 3.10+ and PowerShell 7+; local developers running only unit tests need nothing extra. The unit-test suite's no-skip policy explicitly verifies that on a machine with Python and pymodbus installed, none of the smoke tests skip — a skip on a properly equipped CI machine is treated as an environment failure, not a test pass.
|
||||
|
||||
The skip reasons the fixture produces map cleanly onto the recovery action:
|
||||
|
||||
@@ -146,7 +146,7 @@ The connection-model rationale for why the multiplexer produces multi-frame recv
|
||||
|
||||
## Simulator Profile
|
||||
|
||||
`DL260/dl205.json` is the pymodbus server config. It seeds the registers the E2E tests assert against:
|
||||
`tests/sim/dl205.json` is the pymodbus server config. It seeds the registers the E2E tests assert against:
|
||||
|
||||
| Address | Width | Seeded value | Used to prove |
|
||||
|---------|-------|--------------|---------------|
|
||||
@@ -155,7 +155,7 @@ The connection-model rationale for why the multiplexer produces multi-frame recv
|
||||
| HR 1072 | uint16 | `0x1234` (raw BCD nibbles) | Single-register FC03 BCD decode through the proxy |
|
||||
| HR 1080/1081 | uint16 pair | CDAB-ordered 32-bit BCD | 32-bit BCD decode across the word pair |
|
||||
|
||||
The full register map and the device-side rationale for each entry live in [`../../DL260/dl205.md`](../../DL260/dl205.md).
|
||||
The full register map and the device-side rationale for each entry live in [`../Reference/dl205.md`](../Reference/dl205.md).
|
||||
|
||||
Two profile-level settings are load-bearing for the harness:
|
||||
|
||||
@@ -166,7 +166,7 @@ The `write` block in the JSON controls which ranges accept FC06/FC16. Writes out
|
||||
|
||||
## Alternate Profiles
|
||||
|
||||
The `MODBUS_SIM_PROFILE` environment variable selects an alternate profile alongside `dl205.json`. This is the seam for scenario-specific simulators — for example, a profile with `"type exception": true` to verify the proxy does not depend on the default lax pymodbus behaviour, or a profile that seeds a specific partial-overlap test case at a known address. The existing pattern is `DL260/DL205BcdQuirkTests.cs`, which already drives the simulator with profile-driven assertions. When a new scenario needs its own profile, drop the JSON alongside `dl205.json` and select it via the env var rather than swapping the default — the default profile is the contract for the smoke tests and `MultiplexerE2ETests` and should not be silently mutated.
|
||||
The `MODBUS_SIM_PROFILE` environment variable selects an alternate profile alongside `dl205.json`. This is the seam for scenario-specific simulators — for example, a profile with `"type exception": true` to verify the proxy does not depend on the default lax pymodbus behaviour, or a profile that seeds a specific partial-overlap test case at a known address. When a new scenario needs its own profile, drop the JSON alongside `dl205.json` and select it via the env var rather than swapping the default — the default profile is the contract for the smoke tests and `MultiplexerE2ETests` and should not be silently mutated.
|
||||
|
||||
## Running the Simulator Standalone
|
||||
|
||||
@@ -231,5 +231,6 @@ The read direction proves the proxy rewrote the response; the write direction pr
|
||||
- [Connection Model](../Architecture/ConnectionModel.md) — why the multiplexer's shared backend connection produces the multi-frame condition that triggers pymodbus's framer quirk
|
||||
- [Troubleshooting](../Operations/Troubleshooting.md) — hang-diagnosis pattern for tests that exceed their `[Fact(Timeout)]`
|
||||
- [Log Events](../Reference/LogEvents.md) — `mbproxy.multiplex.request.timeout` is the production watchdog against TxId mis-echo
|
||||
- [DL205/DL260 device quirks](../../DL260/dl205.md) — device-side rationale for every register the simulator profile seeds
|
||||
- [Phase plan README](../plan/README.md) — Test discipline section that codifies the 5 000 ms default and the `--blame-hang-timeout` rule
|
||||
- [DL205/DL260 device quirks](../Reference/dl205.md) — device-side rationale for every register the simulator profile seeds
|
||||
|
||||
Test discipline: E2E tests default to a 5 000 ms `[Fact(Timeout)]`, and `dotnet test` is run with `--blame-hang-timeout` to capture a dump on any hang.
|
||||
|
||||
Reference in New Issue
Block a user