Skip to content

fix(s7commplus): accept unprefixed response values - #881

Open
gijzelaerr wants to merge 3 commits into
fix/833-response-dispatchfrom
fix/872-get-var-substreamed-response
Open

fix(s7commplus): accept unprefixed response values#881
gijzelaerr wants to merge 3 commits into
fix/833-response-dispatchfrom
fix/872-get-var-substreamed-response

Conversation

@gijzelaerr

@gijzelaerr gijzelaerr commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • accept GetVarSubStreamed response PValues both directly after ReturnValue and after the legacy zero marker
  • encode legacy SessionKey absolute DB reads with one 1-based address ID and derive the byte size from the returned PValue
  • stack on fix(s7commplus): correlate request responses #883 so bounded delayed replies from older sequences cannot be mistaken for the current DB-read result
  • cover the captured S7-1511C response layouts and combined sync/async response ordering with regression tests

Root cause

The first #872 hardware trace exposed an unprefixed SessionKey challenge PValue. After that parser fix, DB116 reads encoded the requested size as a second nested address ID, which older S7-1500 firmware does not interpret as a byte count. The latest trace then showed a second independent problem: DB-read sequence 7 consumed a delayed protection-level response for sequence 6 and reported its payload as an item-read error.

This branch is intentionally based on #883 so the PLC retest exercises the corrected address and response-correlation paths together while keeping their reviews separate.

Validation

  • uv run --frozen pytest -q: 2092 passed, 82 skipped
  • uv run --frozen pre-commit run --all-files: passed
  • uv build --no-sources: passed

Hardware retesting on the unchanged S7-1511C at exact head 95514e2 is still required before closing the issue.

Progresses #872.

@gijzelaerr

Copy link
Copy Markdown
Owner Author

Added a follow-up fix based on the latest S7-1511C hardware trace.

The failing DB116 offset 708 INT read previously encoded address IDs [709, 2]. SessionKey-era PLCs interpret every ID after the access area as a nested symbolic path, so the second ID was not a byte count. The updated branch now sends the absolute address as [709] and derives/validates the returned size from the PValue. Multi-read uses the same encoding.

Local verification is clean: 2,078 passed, 82 skipped; all pre-commit hooks passed; sdist and wheel build passed. Please retest the same db_read(116, 708, 2) against the updated PR branch. A successful hardware retest is still required before we call the issue resolved.

@gijzelaerr
gijzelaerr changed the base branch from master to fix/833-response-dispatch September 11, 2026 14:03
@gijzelaerr

Copy link
Copy Markdown
Owner Author

@gaurav041089 There is now a new testable head, 95514e2, combining the DB116 absolute-address correction with recovery from the delayed response visible in your latest log. That log shows the DB read sent as sequence 7, followed by the outstanding protection-level response for sequence 6; the client then parsed that older response as the DB result. The updated branch discards bounded older responses and waits for the matching sequence.

Please install the exact revision with:

python -m pip install --force-reinstall "python-snap7[s7commplus] @ git+https://github.com/gijzelaerr/python-snap7.git@95514e2"

Before testing, please run this once so we can verify which files Python imports:

import s7commplus
import s7commplus.connection
print(s7commplus.__file__)
print(s7commplus.connection.__file__)

Then rerun the same db_read(116, 708, 2) with debug logging. If a delayed reply occurs, the new log should say it is ignoring the older sequence. Please attach the complete log whether the read succeeds or fails.

@russwing

Copy link
Copy Markdown
Contributor

Real-hardware evidence, since @gijzelaerr asked for a retest against the outstanding 1511C item-read failure.

This branch does not fix reads on either of our CPUs. Merged onto the #892 acceptance harness and run against two bench units — byte-for-byte identical failure before and after.

CPU firmware result
S7-1200 1212C DC/DC/DC (6ES7 212-1BE40-0XB0) V4.7.3 read fails, unchanged by this PR
S7-1500 1511F-1 PN (6ES7 511-1FK02-0AB0) V2.9.7 read fails, unchanged by this PR

Both over S7CommPlus V2 with TLS, against the canonical e2e_test_dbs.scl fixture with optimised block access disabled.

What the reads actually return

Same CPU (1212C), same DB, same offsets, legacy S7 alongside S7CommPlus:

DB1.0  size= 2   legacy=00 0a                     s7cp=92 00 00 01
DB1.0  size= 8   legacy=00 0a 00 ff 42 f6 e6 66   s7cp=92 00 00 01
DB1.2  size= 4   legacy=00 ff 42 f6               s7cp=42
DB1.0  size=16   legacy=<16 correct bytes>        s7cp=92 00 00 01

The legacy column is ground truth from the same CPU seconds apart, so the DB contents are correct.

Size is ignored (2, 8 and 16 all return the same four bytes), offset is ignored or mis-scaled (DB1.2 returns the byte at DB1.4), and the returned bytes are not in the block at all.

Why I think this is not "unprefixed response values"

That framing implies the right data arriving in the wrong shape. What we see is the wrong data: a request for sixteen bytes and a request for two return the same four, and none of them is a prefix or suffix of the real contents. Identical bytes on two different CPU families suggests client-side decode rather than a per-model quirk.

I cannot say whether this is the same root cause as the 1511C report — different model, and I do not have that reporter's fixture — but if it is, this PR does not close it.

Full pass and methodology in #892. Both CPUs are dedicated bench units and remain available if you want a specific probe run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants