diff --git a/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/DL205.xmpp b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/DL205.xmpp
new file mode 100644
index 0000000..46ac26f
--- /dev/null
+++ b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/DL205.xmpp
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/README.md b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/README.md
index c2fcdbd..6d062eb 100644
--- a/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/README.md
+++ b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/README.md
@@ -1,30 +1,105 @@
# ModbusPal simulator profiles
-Drop device-specific `.xmpp` profiles here. The integration tests connect to the
-endpoint in `MODBUS_SIM_ENDPOINT` (default `localhost:502`) and expect the
-simulator to already be running — tests do not launch ModbusPal themselves,
-because its Java GUI + JRE requirement is heavier than the harness is worth.
+Two hand-authored `.xmpp` profiles you load into ModbusPal to drive the
+integration-test suite without a real PLC:
+
+| File | What it simulates | Test category |
+|---|---|---|
+| [`Standard.xmpp`](Standard.xmpp) | Generic Modbus TCP server — HR[0..31] = address-as-value, alternating coils, one auto-incrementing register at HR[100] for subscribe tests, scratch ranges for write-roundtrip tests. | `Trait=Standard` |
+| [`DL205.xmpp`](DL205.xmpp) | AutomationDirect DirectLOGIC DL205 / DL260 quirks per [`docs/v2/dl205.md`](../../../docs/v2/dl205.md): low-byte-first string packing, CDAB Float32, BCD numerics, V-memory address markers, Y/C coil mappings. | `Trait=DL205` |
+
+Both listen on TCP **port 502** (the standard Modbus port — change in the
+ModbusPal GUI if a port conflict). Run **only one at a time** since they
+share the port.
## Getting started
-1. Download ModbusPal from SourceForge (`modbuspal.jar`).
+1. Download ModbusPal 1.6b from
+ [SourceForge](https://sourceforge.net/projects/modbuspal/) — `modbuspal.jar`.
+ Requires Java 8+ (Java 17/21 work but emit Swing deprecation warnings).
2. `java -jar modbuspal.jar` to launch the GUI.
-3. Load a profile from this directory (or configure one manually) and start the
- simulator on TCP port 502.
-4. `dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests` — tests
- auto-skip with a clear `SkipReason` if the TCP probe at the configured
- endpoint fails within 2 seconds.
+3. **File > Load** → pick `Standard.xmpp` (or `DL205.xmpp`).
+4. Click the **Run** button (top-right of the toolbar) to start serving on TCP 502.
+5. `dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests` —
+ tests auto-skip with a clear `SkipReason` if the TCP probe at the
+ configured endpoint fails within 2 seconds (`ModbusSimulatorFixture`).
-## Profile files
+## Switching between Standard and DL205
-- `DL205.xmpp` — _to be added_ — register map reflecting the AutomationDirect
- DL205 quirks tracked in `docs/v2/modbus-test-plan.md`. The scaffolded smoke
- test in `DL205/DL205SmokeTests.cs` needs holding register 100 writable and
- present; a minimal ModbusPal profile with a single holding-register bank at
- address 100 is sufficient.
+Stop the running simulator (toolbar's **Stop** button), **File > Load**
+the other profile, **Run**.
## Environment variables
-- `MODBUS_SIM_ENDPOINT` — override the simulator endpoint. Accepts `host:port`;
- defaults to `localhost:502`. Useful when pointing the suite at a real PLC on
- the bench.
+- `MODBUS_SIM_ENDPOINT` — override the simulator endpoint
+ (`host:port`). Defaults to `localhost:502`. Useful when pointing the suite
+ at a real PLC on the bench, or running ModbusPal on a non-default port.
+
+## What's encoded in each profile
+
+### Standard
+
+- HR[0..31]: each register's value equals its address.
+- HR[100]: bound to a `LinearGenerator` (0..65535 over 60s, looping) — drives
+ subscribe-and-receive tests.
+- HR[200..209]: scratch range for write-roundtrip tests.
+- Coils[0..31]: alternating on/off (even=on).
+- Coils[100..109]: scratch range.
+
+### DL205 (per `docs/v2/dl205.md`)
+
+| HR address | Quirk demonstrated | Raw value | Decoded value |
+|---|---|---|---|
+| `0` | Register zero is valid (rejects-register-0 rumour disproved) | `-13570` (0xCAFE) | marker |
+| `1024` (= V2000 octal) | V-memory octal-to-decimal mapping | `8192` (0x2000) | marker |
+| `8448` (= V40400 octal) | V40400 → PDU 0x2100 (NOT register 0) | `16448` (0x4040) | marker |
+| `1040..1042` | String "Hello" packed first-char-low-byte | `25928, 27756, 111` | `"Hello"` |
+| `1056..1057` | Float32 1.5f in CDAB word order | `0, 16320` | `1.5f` |
+| `1072` | Decimal 1234 in BCD encoding | `4660` (0x1234) | `1234` |
+| `1280..1407` | 128-register block (FC03 cap = 128 above spec's 125) | address − 1280 | for FC03 cap test |
+
+| Coil address | Quirk demonstrated |
+|---|---|
+| `2048` | Y0 maps to coil 2048 (DL260 layout) |
+| `3072` | C0 maps to coil 3072 (DL260 layout) |
+| `4000..4007` | Scratch C-relay range for write-roundtrip tests |
+
+## Limitations of ModbusPal 1.6b
+
+- **Only `holding_registers` + `coils`** sections in the official build —
+ no `input_registers` (FC04) and no `discrete_inputs` (FC02). DL205's
+ X-input markers can't be encoded faithfully here. Tests for FC02 / FC04
+ wait for a fork (e.g. `SCADA-LTS/ModbusPal`) or a pymodbus rewrite.
+- **No semantic bindings** for strings / BCD / arbitrary byte layouts. The
+ DL205 profile encodes everything as pre-computed raw 16-bit integers
+ with the math worked out in inline comments. Anything fancier becomes
+ unreadable above ~50 quirky registers — switch to pymodbus when that
+ threshold approaches.
+- **Project is abandoned** since 1.6b on the official SourceForge listing.
+ Active forks: `SCADA-LTS/ModbusPal`, `ControlThings-io/modbuspal`,
+ `mrhenrike/ModbusPalEnhanced`.
+- **No headless mode** in the official 1.6b JAR (`-loadFile` / `-hide`
+ flags exist only in source-built forks). For CI use, plan to switch to
+ pymodbus's `ModbusSimulatorServer` (JSON config, scriptable callbacks,
+ first-class headless).
+- **CVE-2018-10832** XXE in `.xmpp` import. Don't import `.xmpp` files from
+ untrusted sources. Profiles in this repo are author-controlled; safe.
+
+## Alternatives if ModbusPal stops working
+
+| Tool | Pros | Cons |
+|---|---|---|
+| **pymodbus `ModbusSimulatorServer`** | Headless-first, JSON config, per-register seeding, custom callbacks for byte-level layouts. Best CI fit. | Python dependency. |
+| **diagslave** | Simple, headless, fast. | Flat register banks; no per-address seeding from config; no scripting. |
+| **ModbusMechanic** | Headless config-file mode. | Lightly documented. |
+| **ModRSsim2** | Windows GUI, CSV import, scripting. | GUI-centric. |
+
+## File format reference
+
+ModbusPal `.xmpp` is XML with a DTD reference (`modbuspal.dtd`). Root element
+`` with three children:
+- `` — internal id counter (start at 100+)
+- `` — `` for TCP listen, plus a `` placeholder
+- One or more `` containing `` (``), `` (``), ``
+
+Per-register `` ties a register to a `LinearGenerator` / `RandomGenerator` / `SineGenerator` automation declared at the project level. `order="0"` = LSW, `order="1"` = MSW for 32-bit types. There is **no string binding** and **no byte-swap-within-word** binding.
diff --git a/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/Standard.xmpp b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/Standard.xmpp
new file mode 100644
index 0000000..ec89678
--- /dev/null
+++ b/tests/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusPal/Standard.xmpp
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+