Unified Tag API replacing SymbolTable#697
Merged
gijzelaerr merged 4 commits intomasterfrom Apr 20, 2026
Merged
Conversation
Replace the homegrown SymbolTable class with a simpler Tag-based API
using PLC4X / Siemens STEP7 address syntax that's familiar to every
TIA Portal user.
New API:
- snap7.tags.Tag dataclass: area, db_number, byte_offset, bit, datatype,
count, name
- Tag.from_string("DB1.DBX0.0:BOOL") — full PLC4X parser
- load_csv / load_json / load_tia_xml — return dict[str, Tag]
- Client.read_tag(tag_or_str) — read typed value
- Client.write_tag(tag_or_str, value) — write typed value
- Client.read_tags([tag, ...]) — batch read via optimizer
Address syntax supported:
- DB1.DBX0.0:BOOL, DB1.DBB10:BYTE, DB1.DBW10:INT, DB1.DBD10:REAL
- DB1:10:INT (short form), DB1:10:STRING[20], DB1:10:REAL[5] (array)
- M10.5:BOOL, MW20:WORD (Merker)
- I0.0:BOOL, Q0.0:BOOL (I/O)
- Leading %% optional
Removed:
- snap7/util/symbols.py (SymbolTable, TagAddress)
- tests/test_symbols.py
- doc/API/symbols.rst
SymbolTable was experimental, unreleased, and its homegrown dict syntax
was not aligned with industry convention. The new Tag string syntax
matches what TIA Portal watch tables use.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
S7-1200/1500 DBs with "Optimized block access" enabled (the TIA Portal
V13+ default) do not use fixed byte offsets — the PLC relocates
variables internally between downloads. Symbolic access navigates the
PLC's symbol tree using LIDs (Local IDs) instead.
Tag extensions:
- access_sequence: list[int] — LID path through the symbol tree
- symbol_crc: int — layout version validation (0 = skip)
- is_symbolic property — True when access_sequence is set
- Tag.from_access_string("8A0E0001.A", "REAL") classmethod using the
S7CommPlusDriver dot-separated hex format (AccessArea.LID.LID...)
S7CommPlus client:
- read_symbolic(access_area, lids, symbol_crc) — GetMultiVariables with
LID-based ItemAddress
- write_symbolic(...) — SetMultiVariables equivalent
- Module-level _build_symbolic_read/write_payload helpers
s7.Client routing:
- read_tag/write_tag detect Tag.is_symbolic and route to S7CommPlus
symbolic access; classic byte-offset tags continue to use legacy
- read_tags falls back to sequential when any tag is symbolic
(batching symbolic reads via optimizer is future work)
- snap7.Client.read_tag raises NotImplementedError for symbolic tags
(legacy S7 has no symbolic support)
Experimental — the wire implementation follows S7CommPlusDriver but
has not been validated against a real optimized-DB PLC yet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Complete the symbolic access loop: browse() now captures the LID (from
the object RID in EXPLORE responses) and symbol_crc for each variable.
These can be fed into Tag objects for optimized-block access.
New:
- snap7.tags.from_browse(variables) — converts browse() results to
dict[str, Tag], producing symbolic Tags when LIDs are present
- _parse_explore_fields now captures "lid" and "symbol_crc" keys
Workflow for optimized DBs:
variables = client.browse()
tags = from_browse(variables)
value = client.read_tag(tags["Motor.Speed"]) # symbolic access
Still experimental — the CRC handling in particular needs real PLC
validation. If browse doesn't provide a CRC, the Tag uses CRC=0
(skip check) which the PLC may or may not accept depending on config.
Co-Authored-By: Claude Opus 4.6 (1M context) <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.
Summary
Unified Tag API for reading and writing typed PLC values, using PLC4X / Siemens STEP7 address syntax familiar to every TIA Portal user. Includes symbolic (LID-based) access for S7-1200/1500 optimized DBs.
Tag API
A
Tagdescribes a typed value at a specific S7 address. Tags can be created ad-hoc, loaded from files, or discovered from the PLC.Address syntax
Leading
%is optional. All fixed-size types support[count]arrays.Symbolic access for optimized DBs (experimental)
S7-1200/1500 DBs with "Optimized block access" enabled (the TIA Portal V13+ default) do not use fixed byte offsets. The PLC relocates variables internally between downloads, so byte addresses like
DB1.DBX0.0are unreliable. Symbolic access navigates the PLC's symbol tree using LIDs (Local IDs).The wire encoding follows the S7CommPlusDriver reference but has not yet been validated against a real optimized-DB PLC.
API additions
snap7.tags.Tag— canonical dataclass (area, db_number, byte_offset, datatype, bit, count, name, access_sequence, symbol_crc, is_symbolic)Tag.from_string(address)— PLC4X address parserTag.from_access_string(hex_path, datatype, ...)— symbolic access parserload_csv,load_json,load_tia_xml— returndict[str, Tag]from_browse(variables)— convertclient.browse()results to Tag dictClient.read_tag(tag_or_str)— read typed valueClient.write_tag(tag_or_str, value)— write typed valueClient.read_tags([tags])— batch read via optimizerS7CommPlusClient.read_symbolic,write_symbolic— LID-based PDU builders