Phase 3 PR 43 — Swap ModbusPal to pymodbus for the integration-test simulator #42
Reference in New Issue
Block a user
Delete Branch "phase-3-pr43-pymodbus-swap"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Replaces the
.xmppprofiles from PR 42 with pymodbus 3.13.0ModbusSimulatorServerJSON configs. Per the README's prior 'when this becomes unwieldy, switch to pymodbus' note — happening now while the catalog is still small.Why swap
addrJSON entry)increment/random/timestamp/uptimeactions + custom Python actions--http_portpip install 'pymodbus[simulator]==3.13.0'Files
Pymodbus/standard.json— generic Modbus TCP server. HR[0..31] address-as-value, HR[100] declarativeincrementaction, HR[200..209] scratch, alternating coils.Pymodbus/dl205.json— DL205/DL260 quirks perdocs/v2/dl205.md. Each quirky register has an inline_quirkJSON-comment naming the behavior.shared blocks: truematches DL series memory model.Pymodbus/serve.ps1—-Profile {standard|dl205}wrapper that validates pymodbus.simulator is on PATH, picks the right JSON, and execs the simulator in foreground.Pymodbus/README.md— install + run + per-profile reference tables + alternatives + file-format reference.Code changes
ModbusSimulatorFixturedefault port502→5020(pymodbus convention; sidesteps Windows admin requirement). Skip-message points atPymodbus\serve.ps1instead of 'start ModbusPal'. Override viaMODBUS_SIM_ENDPOINT.csproj<None Update>rule swapped fromModbusPal/**toPymodbus/**— JSON + PS1 + README copy to test-output.DL205Profile.cs+DL205SmokeTests.csxml-doc references updated.Doc changes
docs/v2/modbus-test-plan.mdharness section rewritten with the swap rationale; PR-history list marks PR 42 SUPERSEDED. Test-conventions bullet generalized from 'don't depend on ModbusPal state' to 'don't depend on simulator state'.Run
Test posture
ConvertFrom-Jsonclean).winget search Python.Python.3 --exactreturned no matches). JSON should parse on a pymodbus install; if not,Pymodbus/README.md's schema-reference link points at the canonical doc.What's next
The DL205 quirks are now both documented (
docs/v2/dl205.md) and simulator-encoded (Pymodbus/dl205.json). The next bounded PR per the roadmap inmodbus-test-plan.mdis the first quirk-implementation PR (PR 44+) — string-byte-order option in the Modbus driver, followed by theDL205_String_low_byte_first_within_registerintegration test that asserts it works againstdl205.json.ModbusSimulatorFixture default port bumped from 502 to 5020 to match the pymodbus convention. Override via MODBUS_SIM_ENDPOINT for a real PLC on its native 502. Skip-message updated to point at the new Pymodbus\serve.ps1 wrapper instead of 'start ModbusPal'. csproj <None Update> rule swapped from ModbusPal/** to Pymodbus/** so the new JSON profiles + serve.ps1 + README copy to test-output as PreserveNewest. standard.json — generic Modbus TCP server, slave id 1, port 5020, shared blocks=false (independent coils + HR address spaces, more textbook-PLC-like). HR[0..31] seeded with address-as-value via per-register uint16 entries, HR[100] auto-increments via the built-in increment action with parameters minval=0/maxval=65535 (drives subscribe-and-receive integration tests so they have a register that ticks without a write — pymodbus's increment ticks per-access not wall-clock, which is good enough for a 250ms-poll test), HR[200..209] scratch range left at 0 for write tests, coils 0..31 alternating, coils 100..109 scratch. write list covers 0..1023 so any test address is mutable. dl205.json — AutomationDirect DirectLOGIC DL205/DL260 quirk simulator, slave id 1, port 5020, shared blocks=true (matches DL series memory model where coils/DI/HR overlay the same word address space). Each quirky register seeded with the pre-computed raw uint16 value documented in docs/v2/dl205.md, with an inline _quirk JSON-comment naming the behavior so future-me reading the file knows why HR[1040]=25928 means 'H' lo / 'e' hi (the user's headline string-byte-order finding). Encoded quirks: V0 marker at HR[0]=0xCAFE; V2000 at HR[1024]=0x2000; V40400 at HR[8448]=0x4040; 'Hello' string at HR[1040..1042] first-char-low-byte; Float32 1.5f at HR[1056..1057] in CDAB word order (low word first); BCD register at HR[1072]=0x1234; FC03-128-cap block at HR[1280..1407]; Y0/C0 coil markers at 2048/3072; scratch C-relays at 4000..4007. serve.ps1 wrapper — pwsh script with a -Profile {standard|dl205} parameter switch. Validates pymodbus.simulator is on PATH (clearer message than the raw CommandNotFoundException), validates the profile JSON exists, builds the right --modbus_server/--modbus_device/--json_file/--http_port arg list, and execs pymodbus.simulator in the foreground. -HttpPort 0 disables the web UI. Foreground exec lets the operator Ctrl+C to stop without an extra control script. README.md fully rewritten for pymodbus: install command (pip install 'pymodbus[simulator]==3.13.0' — pinned for reproducibility, [simulator] extra pulls aiohttp), per-profile reference tables, the same DL205 quirk → register table from PR 42 but adjusted for pymodbus paths, what's-NEW-vs-ModbusPal section (all four tables, raw uint16 seeding, declarative actions, custom Python action modules, headless, web UI, maintained), trade-offs section (float32-as-two-uint16s for explicit CDAB control, increment ticks per-access not wall-clock, shared-blocks mode for DL205 vs separate for Standard), file-format quick reference for hand-authoring more profiles. References pinned to the pymodbus readthedocs simulator/config + REST API pages. docs/v2/modbus-test-plan.md harness section rewritten with the swap rationale; PR-history list updated to mark PR 42 SUPERSEDED by PR 43 and call out PR 44+ as the per-quirk implementation track. Test-conventions bullet about 'don't depend on ModbusPal state between tests' generalized to 'don't depend on simulator state' and a note added that pymodbus's REST API can reset state between facts if a test ever needs it. DL205Profile.cs and DL205SmokeTests.cs xml-doc updated to reference pymodbus / dl205.json instead of ModbusPal / DL205.xmpp. Functional validation deferred — Python isn't installed on this dev box (winget search returned no matches for Python.Python.3 exact). JSON parses structurally (PowerShell ConvertFrom-Json clean on both files), build clean, .json + serve.ps1 + README all copy to test-output as expected. User installs pymodbus when they want to actually run the simulator end-to-end; if pymodbus rejects the config the README's reference link to pymodbus's simulator/config schema doc is the right next stop. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>