feat(examples): resolve M-area Byte/Word/DWord in browse_tags.py via symbolic READ#768
Open
tommasofaedo wants to merge 1 commit into
Open
feat(examples): resolve M-area Byte/Word/DWord in browse_tags.py via symbolic READ#768tommasofaedo wants to merge 1 commit into
tommasofaedo wants to merge 1 commit into
Conversation
…bolic READ
The EXPLORE symbol blob cannot carry the SIMATIC data type of an M tag: the
DataType attribute is a constant back-reference in the compressed stream —
identical for a Byte, a Word and a DWord tag (verified with an oracle on tags
of known type). So %MB/%MW/%MD could not be distinguished from the blob and
those tags previously showed LogicalAddress='?'.
A symbolic READ recovers it: reading an M tag by its LID (= the XML ID
attribute) returns the value as a fixed-width raw block whose width equals the
declared type size — 1 byte %MB, 2 %MW, 4 %MD. _refine_m_widths() applies this
to every non-Bool M tag (Bool tags stay bit-addressed from EXPLORE).
Safety: tags whose ID has an unmapped digit ('?') are skipped, so a wrong LID
can never yield a confident wrong type.
Also: element-bounded ByteOffset extraction (two fallbacks for garbled labels/
closings) and four FDICT positions for two-digit IDs.
Verified live on an S7-1200 FW V4.1 over TLS with controlled tags:
Byte=0x12->1B (%MB100), Word=0x1234->2B (%MW102), DWord=0x12345678->4B (%MD104);
no regression on I/Q (input_1=%I0.0, output_1=%Q0.1).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-up to #756 / #767. Teaches
examples/browse_tags.pyto resolve the SIMATIC data type (and thus%MB/%MW/%MDaddress) of M-area tags, which the EXPLORE symbol blob cannot express.Why
The EXPLORE symbol blob does not carry the data type of an M tag. The
DataTypeattribute decodes to a constant — a back-reference to the same preset-dictionary position for a Byte, a Word and a DWord tag alike. I verified this with an oracle (DICT_ZERO/ONES/A/B) on tags of known type: all three referencedict[0x7b96]="Bool". So%MB/%MW/%MDare indistinguishable from the blob, and those tags previously printedLogicalAddress='?'.How
A symbolic READ recovers the type. Reading an M tag by its LID (which equals the XML
IDattribute) returns the value as a fixed-width raw block whose width is the declared type size:%MB%MW%MD_refine_m_widths()does this for every non-Bool M tag (Bool tags are already bit-addressed by EXPLORE and left untouched). It reuses a fresh connection per read, since the PLC resets the TCP session after the first symbolic operation.Safety guard: if a tag's
IDhas any unmapped digit ('?'), the LID is uncertain and the refinement is skipped — better a'?'than a confident wrong type (a wrong LID would read a different object and could return a plausible-but-wrong width).Also included:
ByteOffsetextraction with two fallbacks, so the offset value is still recovered when theByteOffset=label or the element close falls in unmapped FDICT positions.dict[0x7d20..21]='3\"',dict[0x7ddb..dc]='4\"'; previously0).Verification
Verified live on an S7-1200 FW V4.1 over TLS with controlled tags of known type/value:
Values are exact; the DWord returns 4 raw bytes (not VLQ-compressed), confirming the width is the declared type size, not a value-minimised width. No regression on I/Q (
input_1=%I0.0,output_1=%Q0.1).Notes / honesty
pre-commit(ruff-format + ruff-check, v0.14.10) clean.mtag_wrue): those suffix bytes alias onto the preset-dictTruetoken, so they can't be reconstructed without the full real dictionary. Type and address — what this PR is about — are exact.🤖 Generated with Claude Code