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:
@@ -647,3 +647,56 @@ pre: cycle=falseG pump=falseG
|
||||
-- neighbours: B3:199=0G B3:201=0G
|
||||
post: cycle=falseG pump=falseG N7:23=0G F8:190=0G B3:200=0G
|
||||
```
|
||||
|
||||
### 2026-10-09 (later) — libplctag S/O/I + control status bits fixed (#659), re-read on Z-33323
|
||||
|
||||
Root cause, from libplctag v2.6.0 `src/protocols/ab/pccc.c` (the native core inside `libplctag.NativeImport` 1.0.41, pulled by the `libplctag` 1.5.2 package): `parse_pccc_file_num` (L881) requires a digit after the file letter and `parse_pccc_file_type` (L828-835) only treats `S` as the status file when a digit follows, so `S:0`/`O:0`/`I:0` never parse; `sub_element_lookup` (L936-1064) has only `con`/`len`/`pos` for R files, and `parse_pccc_bit_num` (L1162) refuses a `/bit` on a non-2-byte element, so neither `R6:0.DN` nor `R6:0/13` parses. The libplctag adapter now translates (`LibplctagLegacyName`): `S:n`→`S2:n`, `O:n`→`O0:n`, `I:n`→`I1:n` (the native encoder's implicit file numbers) and an unknown status bit → `R6:0.CON/<bit>`. Press idle beforehand (`N10:150/0` = `B3:0/4` = false, Native) and afterwards (both false again). AbLegacy CLI built from branch `i659`, reads only, one short session per read, ≥ 1.2 s apart:
|
||||
|
||||
```
|
||||
S:0 Int Libplctag value=4 status=0x00000000 (Good)
|
||||
S:0 Int Native value=4 status=0x00000000 (Good)
|
||||
S:57 Int Libplctag value=1400 status=0x00000000 (Good)
|
||||
S:57 Int Native value=1400 status=0x00000000 (Good)
|
||||
S:4 Int Libplctag value=12688 status=0x00000000 (Good)
|
||||
S:4 Int Native value=-31956 status=0x00000000 (Good)
|
||||
O:0 Int Libplctag value=0 status=0x00000000 (Good)
|
||||
O:0 Int Native value=0 status=0x00000000 (Good)
|
||||
O:0/3 Bit Libplctag value=false status=0x00000000 (Good)
|
||||
O:0/3 Bit Native value=false status=0x00000000 (Good)
|
||||
I:0 Int Libplctag value=-29376 status=0x00000000 (Good)
|
||||
I:0 Int Native value=-29376 status=0x00000000 (Good)
|
||||
I:0/0 Bit Libplctag value=false status=0x00000000 (Good)
|
||||
I:0/0 Bit Native value=false status=0x00000000 (Good)
|
||||
I:0/1 Bit Libplctag value=false status=0x00000000 (Good)
|
||||
I:0/1 Bit Native value=false status=0x00000000 (Good)
|
||||
R6:0.DN Bit Libplctag value=false status=0x00000000 (Good)
|
||||
R6:0.DN Bit Native value=false status=0x00000000 (Good)
|
||||
R6:0.EN Bit Libplctag value=false status=0x00000000 (Good)
|
||||
R6:0.EN Bit Native value=false status=0x00000000 (Good)
|
||||
R6:0.LEN Int Libplctag value=32 status=0x00000000 (Good)
|
||||
R6:0.LEN Int Native value=32 status=0x00000000 (Good)
|
||||
N9:0 Int Libplctag value=2331 status=0x00000000 (Good)
|
||||
N9:0 Int Native value=2331 status=0x00000000 (Good)
|
||||
F8:226 Float Libplctag value=2.1 status=0x00000000 (Good)
|
||||
F8:226 Float Native value=2.1 status=0x00000000 (Good)
|
||||
B3:28 Int Libplctag value=2309 status=0x00000000 (Good)
|
||||
B3:28 Int Native value=2309 status=0x00000000 (Good)
|
||||
T4:15.PRE Int Libplctag value=6000 status=0x00000000 (Good)
|
||||
T4:15.PRE Int Native value=6000 status=0x00000000 (Good)
|
||||
C5:8.DN Bit Libplctag value=true status=0x00000000 (Good)
|
||||
C5:8.DN Bit Native value=true status=0x00000000 (Good)
|
||||
ST14:10 String Libplctag value="Z-33323" status=0x00000000 (Good)
|
||||
ST14:10 String Native value="Z-33323" status=0x00000000 (Good)
|
||||
05:31:09 I:0/6 Libplctag Value: true | Status: 0x00000000 (Good)
|
||||
05:31:11 I:0/6 Native Value: true | Status: 0x00000000 (Good)
|
||||
05:31:13 I:0/15 Libplctag Value: true | Status: 0x00000000 (Good)
|
||||
05:31:16 I:0/15 Native Value: true | Status: 0x00000000 (Good)
|
||||
05:31:18 I:0/7 Libplctag Value: false | Status: 0x00000000 (Good)
|
||||
05:31:20 I:0/7 Native Value: false | Status: 0x00000000 (Good)
|
||||
05:31:22 S:4 Libplctag Value: 17831 | Status: 0x00000000 (Good)
|
||||
05:31:24 S:4 Native Value: -26549 | Status: 0x00000000 (Good)
|
||||
05:31:26 S:4 Libplctag Value: -4646 | Status: 0x00000000 (Good)
|
||||
05:31:28 S:4 Native Value: 17335 | Status: 0x00000000 (Good)
|
||||
```
|
||||
|
||||
Every address reads identically on both transports. `S:4` is the free-running clock, so its value differs read to read on each transport (both Good). `I:0` = -29376 = 0x8D40, and bits `/6` and `/15` read true on both while `/0`, `/1`, `/7` read false — the bit is extracted from the word libplctag read, not defaulted. ab_server has no S/O/I files, so this real-controller read is the only wire evidence; the translation is unit-pinned against a model of the `pccc.c` parser (`LibplctagLegacyNameTests`).
|
||||
|
||||
Reference in New Issue
Block a user