# AB Legacy PCCC integration-test fixture — `ab_server` (Docker) [libplctag](https://github.com/libplctag/libplctag)'s `ab_server` supports both CIP (ControlLogix / CompactLogix / Micro800) and PCCC (SLC 500 / MicroLogix / PLC-5) families from one binary. This fixture reuses the AB CIP Docker image (`otopcua-ab-server:libplctag-release`) with different `--plc` flags. No new Dockerfile needed — the compose file's `build:` block points at the AB CIP `Docker/` folder so `docker compose build` from here reuses the same multi-stage build. **Docker is the only supported launch path**; a fresh clone needs Docker Desktop and nothing else. | File | Purpose | |---|---| | [`docker-compose.yml`](docker-compose.yml) | Three per-family services (`slc500` / `micrologix` / `plc5`); all bind `:44818` | ## Run From the repo root: ```powershell # SLC 500 family — widest PCCC coverage docker compose -f tests\ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests\Docker\docker-compose.yml --profile slc500 up # Per-family docker compose -f tests\...\Docker\docker-compose.yml --profile micrologix up docker compose -f tests\...\Docker\docker-compose.yml --profile plc5 up ``` Detached + stop: ```powershell docker compose -f tests\...\Docker\docker-compose.yml --profile slc500 up -d docker compose -f tests\...\Docker\docker-compose.yml --profile slc500 down ``` First run builds the `otopcua-ab-server:libplctag-release` image (~3-5 min — clones libplctag + compiles `ab_server`). If the AB CIP fixture already built the image locally, docker reuses the cached layers + this runs in seconds. Only one family binds `:44818` at a time; to switch families stop the current service + start another. ## Endpoint - Default: `localhost:44818` (EtherNet/IP standard) - Override with `AB_LEGACY_ENDPOINT=host:port` to point at a real SLC / MicroLogix / PLC-5 PLC on its native port. ## Run the integration tests In a separate shell with a container up: ```powershell cd C:\Users\dohertj2\Desktop\lmxopcua dotnet test tests\ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests ``` `AbLegacyServerFixture` TCP-probes `localhost:44818` at collection init + records a skip reason when unreachable. Tests use `[AbLegacyFact]` / `[AbLegacyTheory]` which check the same probe. ## What each family seeds PCCC tag format is `[]` without a type suffix — file letter implies type: - `N` = 16-bit signed integer - `F` = 32-bit IEEE 754 float - `B` = 1-bit boolean (stored as uint16, bit-addressable via `/n`) - `L` = 32-bit signed integer (SLC 5/05 V15+ only) - `ST` = 82-byte ASCII string (MicroLogix-specific extension) | Family | Seeded tags | Notes | |---|---|---| | SLC 500 | `N7[10]`, `F8[10]`, `B3[10]`, `L19[10]` | Baseline; covers the four numeric file types a typical SLC project uses | | MicroLogix | `B3[10]`, `N7[10]`, `L19[10]` | No `F8` — MicroLogix 1000 has no float file; use L19 when scaled integers aren't enough | | PLC-5 | `N7[10]`, `F8[10]`, `B3[10]` | No `L` — PLC-5 predates the L file type; DINT equivalents went in integer files | ## Known limitations ### ab_server PCCC read/write round-trip (verified 2026-04-20) **Scaffold is in place; wire-level round-trip does NOT currently pass against `ab_server --plc=SLC500`.** With the SLC500 compose profile up, TCP 44818 accepts connections and libplctag negotiates the session, but the three smoke tests in `AbLegacyReadSmokeTests.cs` all fail at read/write with `BadCommunicationError` (libplctag status `0x80050000`). Possible root causes: - ab_server's PCCC server-side opcode coverage may be narrower than libplctag's PCCC client expects — the tool is primarily a CIP server; PCCC was added later + is noted in libplctag docs as less mature. - libplctag's PCCC-over-CIP encapsulation may assume a real SLC 5/05 EtherNet/IP NIC's framing that ab_server doesn't emit. The scaffold ships **as-is** because: 1. The Docker infrastructure + fixture pattern works cleanly (probe passes, container lifecycle is clean, tests skip when absent). 2. The test classes target the correct shape for what the AB Legacy driver would do against real hardware. 3. Pointing `AB_LEGACY_ENDPOINT` at a real SLC 5/05 / MicroLogix 1100 / 1400 should make the tests pass outright — the failure mode is ab_server-specific, not driver-specific. Resolution paths (pick one): 1. **File an ab_server bug** in `libplctag/libplctag` to expand PCCC server-side coverage. 2. **Golden-box tier** via Rockwell RSEmulate 500 — closer to real firmware, but license-gated + RSLinx-dependent. 3. **Lab rig** — used SLC 5/05 / MicroLogix 1100 on a dedicated network; the authoritative path. ### Other known gaps (unchanged from ab_server) - **Timer / Counter file decomposition** — PCCC T4 / C5 files contain three-field structs (`.ACC` / `.PRE` / `.DN`). Not in ab_server's scope; tests targeting `T4:0.ACC` stay unit-only. - **ST (ASCII string) files** — real MicroLogix ST files have a length field plus CRLF-sensitive semantics that don't round-trip cleanly. - **Indirect addressing** (`N7:[N10:5]`) — not in ab_server's scope. - **DF1 serial wire behaviour** — the whole ab_server path is TCP; DF1 radio / serial fidelity needs real hardware. See [`docs/drivers/AbLegacy-Test-Fixture.md`](../../../docs/drivers/AbLegacy-Test-Fixture.md) for the full coverage map. ## References - [libplctag on GitHub](https://github.com/libplctag/libplctag) — `ab_server` lives under `src/tools/ab_server/` - [`docs/drivers/AbLegacy-Test-Fixture.md`](../../../docs/drivers/AbLegacy-Test-Fixture.md) — coverage map + gap inventory - [`docs/v2/dev-environment.md`](../../../docs/v2/dev-environment.md) §Docker fixtures — full fixture inventory - [`../../ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Docker/`](../../ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Docker/) — the shared Dockerfile this compose file's `build:` block references