AbLegacy libplctag: S/O/I files and control status bits fail on a real MicroLogix 1400 (default probe S:0 fails) #659

Closed
opened 2026-10-09 05:23:50 -04:00 by dohertj2 · 1 comment
Owner

Found on real hardware 2026-10-09 (MicroLogix 1400 Z-33323, ab://10.201.44.231/, idle; #592 evidence).

On the libplctag transport — the AbLegacy default for every family — these reads return BadCommunicationError on a real MicroLogix 1400, while the native transport reads them correctly from the same controller seconds later:

Address libplctag native
S:0 (the default probe address), S:57, S:4 BadCommunicationError 4 / 1400 / clock
O:0, O:0/3 BadCommunicationError 0 / false
I:0, I:0/0 BadCommunicationError -29376 / false
R6:0.DN, R6:0.EN BadCommunicationError false

N/F/B/T/C/R(.LEN/.POS)/ST read identically on both. The numbered forms libplctag's PCCC parser may expect (S2:0, O0:0, I1:0) are rejected by our address parser (BadNodeIdUnknown), so there is no authoring workaround.

Impact: a MicroLogix authored with the default transport and the default probe (S:0) probes Bad on real hardware, and status/I-O tags never read. ab_server never caught this: its PCCC profiles have no S/O/I files.

LibplctagLegacyTagRuntime passes the parsed address straight through as the libplctag Name. Likely fix: translate file-number-less S/O/I to libplctag's expected form (S2:/O0:/I1: — to be confirmed against libplctag pccc.c) and check control-element status-bit naming; or reconsider the per-family default given native now has real-hardware evidence on MicroLogix. Evidence: docs/plans/2026-10-07-native-ab-transport-gate-results.md (2026-10-09 MicroLogix section), docs/drivers/AbLegacy.md §Wire evidence.

Found on real hardware 2026-10-09 (MicroLogix 1400 Z-33323, `ab://10.201.44.231/`, idle; #592 evidence). On the **libplctag** transport — the AbLegacy **default** for every family — these reads return `BadCommunicationError` on a real MicroLogix 1400, while the **native** transport reads them correctly from the same controller seconds later: | Address | libplctag | native | |---|---|---| | `S:0` (the **default probe address**), `S:57`, `S:4` | BadCommunicationError | 4 / 1400 / clock | | `O:0`, `O:0/3` | BadCommunicationError | 0 / false | | `I:0`, `I:0/0` | BadCommunicationError | -29376 / false | | `R6:0.DN`, `R6:0.EN` | BadCommunicationError | false | N/F/B/T/C/R(.LEN/.POS)/ST read identically on both. The numbered forms libplctag's PCCC parser may expect (`S2:0`, `O0:0`, `I1:0`) are rejected by our address parser (`BadNodeIdUnknown`), so there is no authoring workaround. **Impact:** a MicroLogix authored with the default transport and the default probe (`S:0`) probes Bad on real hardware, and status/I-O tags never read. `ab_server` never caught this: its PCCC profiles have no S/O/I files. `LibplctagLegacyTagRuntime` passes the parsed address straight through as the libplctag `Name`. Likely fix: translate file-number-less S/O/I to libplctag's expected form (S2:/O0:/I1: — to be confirmed against libplctag `pccc.c`) and check control-element status-bit naming; or reconsider the per-family default given native now has real-hardware evidence on MicroLogix. Evidence: `docs/plans/2026-10-07-native-ab-transport-gate-results.md` (2026-10-09 MicroLogix section), `docs/drivers/AbLegacy.md` §Wire evidence.
Author
Owner

Fixed on master — merge 98c00904 (branch commits 0abce36c, 7dbb060f, 7ba86f78), pushed 2026-10-09.

Root cause (libplctag core v2.6.0, bundled with libplctag.NET 1.5.2, src/protocols/ab/pccc.c): the PCCC name parser requires a file number after the file letter (parse_pccc_file_num, ~L881-904; S is only the status file when a digit follows, ~L828-835), so S:0/O:0/I:0 never parsed; and its R-file sub-element table (~L936-1064) has only con/len/pos, so .DN/.EN etc. were unknown. Our adapter passed the address straight through.

Fix: LibplctagLegacyName (libplctag adapter only) rewrites the name before libplctag sees it: S:n→S2:n, O:n→O0:n, I:n→I1:n (the default file numbers the proven native encoder uses), and R status bits (EN/EU/DN/EM/ER/UL/IN/FD) / counter UA → control word + bit (R6:0.CON/13). Operators keep authoring S:0, O:0/3, I:0/0, R6:0.DN. Covers every libplctag entry point incl. the driver probe loop and Test Connect, so the default probe S:0 now works on real hardware.

Write surface not widened: every write whose address the translation changes (S/O/I words and bits, the translated status bits) is refused BadNotSupported on libplctag before anything is created or sent — those writes never worked before. Reads only.

Evidence: 104 translation cases checked against a model of the v2.6.0 parser and the native encoder (46 red without the fix); 40 write-refusal cases. Live, read-only, on the idle MicroLogix 1400 Z-33323: libplctag now equals native for S:0, S:57, O:0, O:0/3, I:0 (and bits /0 /1 /6 /7 /15), R6:0.DN/.EN/.LEN plus regression controls (only the S:4 clock differs). Caveat: the R status bits both read false, so the live read does not discriminate their bit numbers — those rest on the native table + parser model.

Follow-ups: #660 (Test Connect PLC-5 octal probe address, pre-existing). Libplctag bits on L files remain unsupported (no hardware with L files).

Fixed on master — merge `98c00904` (branch commits `0abce36c`, `7dbb060f`, `7ba86f78`), pushed 2026-10-09. **Root cause** (libplctag core v2.6.0, bundled with libplctag.NET 1.5.2, `src/protocols/ab/pccc.c`): the PCCC name parser requires a file number after the file letter (`parse_pccc_file_num`, ~L881-904; `S` is only the status file when a digit follows, ~L828-835), so `S:0`/`O:0`/`I:0` never parsed; and its R-file sub-element table (~L936-1064) has only `con`/`len`/`pos`, so `.DN`/`.EN` etc. were unknown. Our adapter passed the address straight through. **Fix:** `LibplctagLegacyName` (libplctag adapter only) rewrites the name before libplctag sees it: `S:n`→`S2:n`, `O:n`→`O0:n`, `I:n`→`I1:n` (the default file numbers the proven native encoder uses), and R status bits (EN/EU/DN/EM/ER/UL/IN/FD) / counter UA → control word + bit (`R6:0.CON/13`). Operators keep authoring `S:0`, `O:0/3`, `I:0/0`, `R6:0.DN`. Covers every libplctag entry point incl. the driver probe loop and **Test Connect**, so the default probe `S:0` now works on real hardware. **Write surface not widened:** every write whose address the translation changes (S/O/I words and bits, the translated status bits) is refused `BadNotSupported` on libplctag before anything is created or sent — those writes never worked before. Reads only. **Evidence:** 104 translation cases checked against a model of the v2.6.0 parser and the native encoder (46 red without the fix); 40 write-refusal cases. Live, read-only, on the idle MicroLogix 1400 Z-33323: libplctag now equals native for `S:0`, `S:57`, `O:0`, `O:0/3`, `I:0` (and bits /0 /1 /6 /7 /15), `R6:0.DN/.EN/.LEN` plus regression controls (only the `S:4` clock differs). Caveat: the R status bits both read false, so the live read does not discriminate their bit numbers — those rest on the native table + parser model. Follow-ups: #660 (Test Connect PLC-5 octal probe address, pre-existing). Libplctag bits on L files remain unsupported (no hardware with L files).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#659