fix(ablegacy): translate S/O/I and R status bits for libplctag's PCCC parser (#659)
libplctag 2.6.0 (bundled by libplctag 1.5.2 / NativeImport 1.0.41) pccc.c needs an explicit file number (parse_pccc_file_num; S is only the status file when a digit follows) and has no R-file status-bit mnemonics (sub_element_lookup: con/len/pos only; a /bit is refused on a 6-byte element). So the canonical S:0 (the default probe), O:0/3, I:0/0 and R6:0.DN failed with BadCommunicationError on a real MicroLogix 1400 while native read them. LibplctagLegacyName (libplctag adapter only) now emits S2:/O0:/I1: (the native encoder's implicit file numbers) and R6:0.CON/<bit> for status bits libplctag lacks (R EN/EU/DN/EM/ER/UL/IN/FD, C UA), bit numbers taken from the native table. The authored grammar is unchanged. Unit tests pin the translation per family and check, through a model of the pccc.c parser, that the translated name addresses exactly what the native encoder does (46 fail without the fix). Live: Z-33323 idle, reads only - libplctag now equals native for S/O/I/R status bits; controls unchanged. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -194,8 +194,8 @@ Native routing: SLC500/MicroLogix/PLC-5 are direct; `logixpccc` uses Unconnected
|
||||
follow-up). PLC-5 writes are refused the same way. libplctag performs a masked bit write here; a native
|
||||
read-modify-write of the control word would race the PLC updating TT/DN. Reads of status bits are unaffected.
|
||||
- ⚠️ **On libplctag (the default) a status-bit write is NOT refused** — it goes to the controller as a write to the
|
||||
timer/counter/control element (libplctag's bit-tag write; not exercised on a wire — `ab_server` has no T/C/R
|
||||
files). Nothing in authoring prevents it: the address is free text,
|
||||
timer/counter/control element (libplctag's masked bit-tag write; an `R` status bit is sent as `R<f>:<e>.CON/<bit>`
|
||||
since #659; not exercised on a wire — `ab_server` has no T/C/R files). Nothing in authoring prevents it: the address is free text,
|
||||
any `dataType` may be chosen (a status bit is naturally authored `Bit`), and `writable` defaults to `true`.
|
||||
Author status-bit tags with `"writable": false` unless writing them is genuinely intended.
|
||||
- **PLC-5 native is N-file reads only**; every other PLC-5 operation is refused with `BadNotSupported`.
|
||||
@@ -216,25 +216,36 @@ before and after). Read pass, each address on libplctag then native (raw output
|
||||
|
||||
| Address(es) | libplctag | Native |
|
||||
|---|---|---|
|
||||
| `S:0` (default probe), `S:57` (= 1400), `S:4` | **BadCommunicationError** | Good (4, 1400, clock) |
|
||||
| `S:0` (default probe), `S:57` (= 1400), `S:4` | Good, equal (4, 1400, clock) since #659; **BadCommunicationError** before | Good (4, 1400, clock) |
|
||||
| `N9:0`, `N9:4`, `N7:255` | Good | Good, equal |
|
||||
| `F8:226` (2.1), `F8:214` (200.0) | Good | Good, equal |
|
||||
| `B3:24`, `B3:28` (0x0905), bits `/0`, `/8`, `/9`, `B3:132/14` | Good | Good, equal |
|
||||
| `T4:15/93/14/11.PRE`, `.ACC`, `.DN`; `T40:3/12.PRE` | Good | Good, equal |
|
||||
| `C5:0.PRE/.ACC`, `C5:1.PRE`, `C5:8.DN` | Good | Good, equal |
|
||||
| `R6:0.LEN`, `.POS` | Good | Good, equal |
|
||||
| `R6:0.DN` (and `.EN`) | **BadCommunicationError** | Good |
|
||||
| `R6:0.DN` (and `.EN`) | Good, equal since #659; **BadCommunicationError** before | Good |
|
||||
| `ST14:10` (`"Z-33323"`), `ST14:0` | Good | Good, equal — **ST byte order correct** |
|
||||
| `O:0`, `O:0/3`, `I:0`, `I:0/0` | **BadCommunicationError** | Good |
|
||||
| `O:0`, `O:0/3`, `I:0`, `I:0/0`, `I:0/1`, `I:0/6`, `I:0/15` | Good, equal since #659; **BadCommunicationError** before | Good |
|
||||
|
||||
Native writes on the same idle press, each restored to 0 and verified: `N7:23` 0→4242→0 (neighbours `N7:22/24`
|
||||
unchanged), `F8:190` 0→42.5→0, `B3:200` bit RMW `/5` set → 32, `/3` set → 40, `/5` clear → 8, `/3` clear → 0
|
||||
(neighbours `B3:199/201` unchanged). Addresses vetted against the sibling Z-33756 program export (no ladder,
|
||||
symbol, HMI, panel or migration reference) and Z-33323's own symbol table, and read 0 beforehand.
|
||||
⚠️ **libplctag (the default) cannot read `S`, `O`, `I` or control status bits on this controller**, and the
|
||||
numbered forms (`S2:0`, `O0:0`, `I1:0`) are rejected by the address parser — so the default probe `S:0` fails on a
|
||||
real MicroLogix under the default transport (tracked as a follow-up issue). Not tested on hardware: L and A files
|
||||
(no press has them), function files, PLC-5, SLC, `logixpccc`.
|
||||
**libplctag `S`/`O`/`I` and control status bits — fixed (#659).** Before the fix libplctag (the default) returned
|
||||
`BadCommunicationError` for `S:`, `O:`, `I:` and `R6:0.DN`/`.EN` on this controller, so the default probe `S:0`
|
||||
failed on real hardware. Root cause, from libplctag 2.6.0's `src/protocols/ab/pccc.c` (the core bundled by the
|
||||
`libplctag` 1.5.2 package): `parse_pccc_file_num` requires a digit after the file letter (and `S` is only the
|
||||
status file when a digit follows it), and its sub-element table has only `con`/`len`/`pos` for R files — a bare
|
||||
`R6:0/13` is refused too, because a `/bit` is only allowed on a 2-byte element. The libplctag adapter
|
||||
(`LibplctagLegacyName`) now translates the canonical address into the form that parser accepts — `S:n` → `S2:n`,
|
||||
`O:n` → `O0:n`, `I:n` → `I1:n` (the same default file numbers the native encoder uses, on every family) and a status
|
||||
bit libplctag lacks (`R` `EN/EU/DN/EM/ER/UL/IN/FD`, `C` `UA`) → `R6:0.CON/<bit>` (control word + bit, bit numbers
|
||||
from the native table). The authored grammar is unchanged; `S2:0`/`O0:0`/`I1:0` stay rejected by the parser (one
|
||||
spelling per address). Re-run on the same idle press 2026-10-09: every address above reads **identical** on both
|
||||
transports (`S:4` is a free-running clock and differs read to read on each). ⚠️ The translation also means a
|
||||
libplctag **write** to an `R` status bit now reaches the controller as libplctag's masked bit write (it used to fail
|
||||
at tag creation) — the same behaviour T/C status bits always had on libplctag; see the status-bit write note above.
|
||||
Not tested on hardware: L and A files (no press has them), function files, PLC-5, SLC, `logixpccc`.
|
||||
|
||||
Simulator evidence:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user