Files
sps_skel/CLAUDE.md
T
Michael StanglandClaude Opus 5.5 0115ef68b7 TRO-JSON v4: Slots je TRO und Staubereiche (jamAreas)
- model: Slot (separator/switch/scanner/drive + Rollen), JamArea (J<Separator>,
  Eingang eines TRO mit allen Vorgaengern), derive_slots, derive_jam_areas;
  Schema sps_skel-tro-v4, v3-Dateien werden weiter gelesen
- scl_context: ein JamEntr je eigenem Staubereich statt je Vorgaenger (wie
  UH01-UH05), Ausgaenge nennen den Staubereich des Nachfolgers
- Golden Files neu erzeugt, Tests fuer Slots/Staubereiche, Doku nachgezogen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:44:02 +02:00

260 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project purpose
`sps_skel` takes a mechanical layout (from project planning/sales) together with an
electrical layout (list of sensors, stoppers, switches, etc.) and generates a **skeleton
of Siemens SCL code** ("TRO" — Transfer Route Object — blocks for a conveyor/material-flow
control system) that can be imported directly into TIA Portal.
The repository has moved past pure analysis: `lib/` now holds working Python tooling that
runs the **full CSV → TRO-JSON → SCL pipeline in a first version**. From a CSV export (ILS
2.0) it derives a material-flow graph and a TRO list, writes the TROs as a TRO-JSON defined
by the shared pydantic model `lib/model.py`, and emits an `FB_Main` **SCL skeleton** from
that JSON. A copy of the BricsCAD drawing annotated with the same TROs serves as a viewer
for visual checking; it is no longer a data source. The skeleton is deliberately not a running
program — every value that must come from the electrical planning is left as a visible
`TODO(E-Planung)` gap rather than guessed. What is **not** done yet is the fuller layout-JSON
schema (`doc/HundM/Json_Layout-Konzept.md`) as an intermediate format and the generation of
the other per-controller blocks (`FB_CallSensors`, `FC_Direction`/`FC_Call_Jams` as
standalone files); see "Roadmap" below. `tests/` holds the first tests
(`tests/test_model.py`); `examples/` is still empty scaffolding (see "Standard Programm
Template" below). What exists today is:
- `bin/` — environment/venv management scripts, plus one `.bat`/`.sh` wrapper pair per CLI
tool in `lib/` (see "Environment scripts" below)
- `lib/*.py` — CLI tools and libraries that turn a CSV export into a material-flow graph,
a derived TRO list/diagram, a TRO-JSON (`lib/model.py`), an `FB_Main` SCL skeleton, and
(with the BricsCAD DXF) an annotated copy of the drawing for visual checking;
`lib/e_planning.py` assigns the E-planning's sensors/valves (from the cable-length
tool's `*_positionsdraw.json`) to the layout parts so the skeleton can carry real names.
See **`doc/Python_Scripts.md`** for what each script does and which switches it takes.
- `data/` — input CSV exports (gitignored, not committed)
- `cad/tro_types.lsp` — generated type list for the BricsCAD `TROEDIT` dialog (written by
`tro_annotate.py --emit-lisp`)
- `cfg/dxf_registration.json` — persisted, verified CSV↔DXF coordinate transform;
`cfg/tro_overrides.ini` — hand-maintained corrections to the derived TROs (see `tro_overrides.py`);
`cfg/e_planning.ini` — project-specific rules for assigning E-planning symbols to layout parts;
`cfg/<csv>_tro_ids.ini` — per-plant TRO-ID file (versioned, IDs renamed by the SPS
programmers), created/extended by `tro_flow.py` via `lib/tro_ids.py`
- `doc/*.md` — analysis documents that reverse-engineer the SCL patterns and propose the
fuller JSON layout schema for the parts of the pipeline still to be built out
Read `doc/` before writing any generator code — start with `doc/Python_Scripts.md` for the
existing tooling, then the domain-model documents below; together they contain the actual
domain model this project is meant to implement.
## Environment scripts (bin/)
Every script has a `.bat` (Windows) and `.sh` (Linux/macOS) pair. The four scripts below are
environment/venv management only — they never invoke a concrete Python script:
| Script | Purpose |
|---|---|
| `setenv.bat` / `source setenv.sh` | Sets `SPS_SKEL` (project root) and `SKEL_BIN/LIB/CFG/DATA/LOG/RESULTS/EXAMPLES/TESTS`; prepends `SKEL_LIB` to `PYTHONPATH`; creates missing folders |
| `install_py.bat` / `install_py.sh` | Calls `setenv`, creates `.venv` (`py -m venv` / `python3 -m venv`), installs `requirements.txt`. Aborts with a message if `.venv` already exists |
| `activate_venv.bat` / `activate_venv.sh` | Calls `setenv`, activates `.venv` (errors if missing — run `install_py` first) |
| `get_cmd.bat` / `get_cmd.sh` | Calls `setenv`, opens a new shell with the environment variables set |
**Convention:** every CLI tool added to `lib/` gets its own `.bat`/`.sh` wrapper pair in
`bin/`, named after the module (e.g. `lib/tro_flow.py` → `bin/tro_flow.bat` /
`bin/tro_flow.sh`). Each wrapper calls `setenv`, activates `.venv` if present, then runs the
module with `py`/`python3 "%*"`/`"$@"`. This supersedes the old "env-only" rule — see
`bin/material_flow.bat`, `bin/tro_flow.bat`, `bin/tro_annotate.bat` (+ `.sh`) for the current
pattern, and `doc/Python_Scripts.md` for what each tool does and which switches it takes.
Typical workflow on Windows:
```
bin\install_py.bat # one-time: create venv + pip install
bin\activate_venv.bat # each session: activate venv + show versions
```
Linux/macOS equivalents must be **sourced**, not executed:
```
bash bin/install_py.sh
source bin/activate_venv.sh
```
Requires Python 3.10+. `requirements.txt` pins `pydantic>=2.0.0` (used throughout `lib/`
for validated models), `ezdxf>=1.4.0` (DXF read/write, `tro_annotate.py` only) and
`pytest>=9.0.0`.
Tests: `python -m pytest tests/` with `.venv` active. `tests/conftest.py` puts `lib/` on
`sys.path`, so `bin/setenv` is not required for the tests. No build step or linter is set
up.
## Domain model (from doc/)
The target system is a Siemens TIA Portal / SCL project for automated conveyor/carrier
routing, modeled around **TRO** (Transfer Route Object) blocks. Key documents, read in
this order for onboarding:
0. **`doc/Python_Scripts.md`** — the existing CLI tooling (`lib/material_flow.py`,
`lib/tro_flow.py`, `lib/tro_annotate.py`, `lib/tro_extract.py`, `lib/scl_skeleton.py`,
`lib/e_planning.py`, plus the `lib/tro_catalog.py`, `lib/model.py`, `lib/dxf_registration.py` and
`lib/tro_overrides.py` libraries they share): what each script does, its switches, inputs/outputs. This is
working code, not a proposal — read it before touching `lib/`.
1. **`doc/HundM/Json_Layout-Konzept.md`** — the core proposal: a JSON file as single source
of truth (`plc`, `controlUnits`, `sensors[]`, `conveyors[]`, `tros[]`, `loadingBooms[]`,
`emptyCarrBuffers[]`, `routing`, `jamAreas[]`, `scanners[]`, `connections[]`,
`destinations[]`) from which the repetitive, per-topology SCL code in `FB_Main`,
`FB_CallSensors`, `FC_Direction`, `FC_Call_Jams` would be generated.
2. **`doc/TRO_Typen.md`** — catalogs all 10 TRO function-block types actually found across
the 5 reference controllers (UH01–UH05) and shows that 9 of them are additive
combinations of one base type (`1Sep` = one separator/stopper) plus reusable
sub-blocks (`FB_ILS_STRO_Sep`, `FB_ILS_STRO_Switch`, `FB_ILS_STRO_Vario`,
`FB_BarcodeReaderCognex`, `FB_CarrAccumulate1Sep`). Only `LoadingBoom` is structurally
independent. `lib/tro_catalog.py` is the executable form of this catalog (name, FB
block, sub-components, color, CAD symbol per type).
3. **`doc/HundM/EA-Listen-Analyse.md`** — analyzes the raw I/O list Excel exports
(`*_EA.xlsx`/`*_TIA.xlsx`/`*_WSCAD.xlsx`) and companion position/cabling JSON exports,
and what can vs. cannot be auto-derived from them (signal naming prefixes `BG/SF/DI/BP`
for inputs, `MB/MA/QA/DQ/FC/PF` for outputs; topology/timing/customCode cannot be
derived from I/O lists alone — those must come from the JSON model or CAD symbol).
4. **`doc/HundM/BricsCAD_TRO_Symbol.md`** — proposes a BricsCAD block symbol whose
attributes feed the JSON `tros[]` entries; documents which fields are captured on the
symbol vs. derived from drawing topology or type-based timing defaults.
`lib/tro_annotate.py` implements a first version of this (marker blocks with `ID`/
`TYPE`/`FB_BLOCK` attributes), plus the `TROEDIT` BricsCAD dialog (`cad/tro_types.lsp`,
generated by `tro_annotate.py --emit-lisp`).
5. **`doc/HundM/SCL_Analyse_Standardisierung.md`** — cross-controller duplication analysis;
identifies ~22 blocks duplicated identically across all 5 controllers (candidates for
a shared library) and flags "version chaos" areas (e.g. `FB_StockRemovalBLKModul*`
variants) that should NOT be naively merged.
6. **`doc/HundM/suggestion.md`** — a follow-up proposal to collapse the 7 `FB_ILS_MTRO_*`
variants into a single `FB_ILS_MTRO` block driven by an array/config descriptor
instead of hand-duplicated numbered members (`...1`, `...2`, `Dir1..Dir4`). References
a `lib/create_skel.py` (`guess_fbtype()`) as the intended generator entry point. That
specific module does not exist in this repo — it is the HundM Excel-based generator
sketch, a different input source (see "Roadmap" below). This repo's own SCL emitter is
`lib/scl_skeleton.py`, which already emits an `FB_Main` skeleton from the TRO-JSON.
7. **`doc/500573_Mubea/TRO_Identifikation_500573.md`** — the derivation rules
`lib/tro_flow.py` implements: how to infer a TRO's type from its separator's host
object (Gefällestrecke/Strecke/Kreisel) when no I/O list or `FB_Main` exists yet.
8. **`doc/TRO_Katalog/TRO_Katalog.md`** — central image/concept catalog per TRO type
(schematic, real layout image, SCL template, JSON example, CAD symbol attributes);
its generated images come from `doc/TRO_Katalog/tro_graphs/gen_tro_graphs.py`
(doc-tooling, not part of the generator — see `doc/Python_Scripts.md` §8) built from
`doc/TRO_Katalog/connect.ini`.
9. **`doc/Datenquellen_Layout_Hardwareplanung.md`** — which TRO/SCL data comes from the
mechanical layout (CSV), which from the hardware planning (EA list, TIA import,
WSCAD, `positionsdraw`) and which is a default; two reference call sites annotated
line by line. The full raw field lists of both sources are in
`doc/Klassenhierarchie.md`, chapter "Daten".
10. **`doc/Konzept_Layout_Hardware_SCL.md`** — the target workflow (planned, not built):
layout → `<csv>_tro.json` (with slots, `jamAreas`), hardware planning →
`hw_import.py` → `<projekt>_hw.json`, `hw_assign.py` → `<csv>_anlage.json`,
then `scl_skeleton.py`; what happens to `e_planning.py` (split),
`tro_annotate.py` (viewer reading the JSON) and `tro_extract.py` (dropped).
### Used libraries (referenced but not vendored)
Most `FB_ILS_MTRO_*` types exist in this repo **only as `.liblink`** references to an
external `ILSLib` library — the actual FB source is not in this Git repo.
`doc/TRO_Katalog/scl_templates/*.scl` contains the real **call-site/instantiation code**
(parametrization in `FB_Main`) for those types, not the FB body. Only a few types have
local, fully-vendored SCL source (`FB_ILS_MTRO_Vario_workStation`, `FB_EmptyCarrBuffer`,
`FB_LoadingBoom_INBOUND`, `FB_ILS_MTRO_2Sep1Swi` — the last one unused/orphaned). Treat
`doc/TRO_Katalog/scl_templates/*.scl` as **read-only reference material** for pattern
extraction, not code to execute or modify.
## Roadmap: CSV → TRO-JSON → SCL (first version implemented)
Since 2026-10-09 the main path is **CSV → `tro_flow.py --json` → TRO-JSON →
`scl_skeleton.py` → SCL**. Layer order (who may import whom): `tro_catalog.py` (TRO *types*)
← `lib/model.py` (TRO *instances* and the TRO-JSON: `TroBase` → `DerivedTro`, `Connection`,
`TroCandidate`, `Analysis`, `TroDocument`) ← derivation (`material_flow.py`, `tro_flow.py`) ←
outputs (`scl_skeleton.py`, `tro_annotate.py`, reports). `items`/`fbType` are always read
from the catalog via the TRO type, never stored. See `doc/Python_Scripts.md` §6b.
Inside the SCL output, `lib/scl_context.py` (TRO-JSON → render context, all derivations)
sits between `model.py` and `scl_skeleton.py` (context → text only). With `--templates`
(opt-in) REGIONs come from Jinja2 templates in `lib/scl_templates/<fbType>.scl.j2`
(pilot: `FB_ILS_MTRO_1Sep1Swi`), each round-trip tested against its reference call site
in `doc/TRO_Katalog/scl_templates/` (`tests/test_scl_templates.py`); every line holding a
placeholder must carry `TODO(E-Planung)`. Migration steps, decisions per template line
and status: `doc/SCL_Templates.md`. Golden files in `tests/fixtures/scl/` pin the SCL output byte for
byte — rewrite them (`SKEL_UPDATE_GOLDEN=1`) only for a reviewed, intended change.
1. **`lib/tro_flow.py --json`** (implemented) — writes `<csv>_tro.json` (schema
`sps_skel-tro-v4`, `model.TroDocument`): TROs with their hardware `slots`, system
boundaries `SYSn`, connections with their kind, `jamAreas` (one per TRO entry, key
`J<Separator>`, all predecessors that feed it), findings. TRO-IDs come from `cfg/<csv>_tro_ids.ini` (`lib/tro_ids.py`): each
TRO is found again by the position of its separators, so IDs survive a new layout export
(TeileIds do not); `--renumber` renumbers along the material flow, `--ids` points another
export of the same plant at the same file. See `doc/Python_Scripts.md` §4.
2. **`lib/scl_skeleton.py`** (implemented) — reads that TRO-JSON through `TroDocument` (a
wrong/renamed key or `items` not matching the catalog stops the run) and emits an `FB_Main` SCL
skeleton (`<source>_FB_Main.scl`): one `REGION` per TRO with the instance call and every
parameter line in the right order, plus inline `FC_Direction` calls for switch TROs.
Everything derivable from the layout is filled (REGION order, FB type, parameter-block
counts, destination list per switch exit, `nTo1Destinations` for single-switch TROs);
everything that must come from the electrical planning is a `TODO(E-Planung)` gap.
Switches `--json`, `--out`, `--start` (the last picks an entry point while the plant is a
closed loop with no loading/unloading station). See `doc/Python_Scripts.md` §5b.
3. **`lib/tro_annotate.py`** — **viewer only**: draws the same TROs (same `analyse_tros`
call as `tro_flow.py`) into a copy of the DXF for a visual check in BricsCAD.
4. **`lib/tro_extract.py`** — **parked**: reads the annotated DXF back into the old
`sps_skel-tro-extract-v1` JSON, which `scl_skeleton.py` no longer accepts. Not deleted, not
extended; if drawing edits (`TRO_INSERT`/`TRO_EDIT`) are ever needed again, it should
write `model.TroDocument`. See `doc/Python_Scripts.md` §5a.
5. **`lib/e_planning.py`** (implemented, first version) — CSV + E-planning
`*_positionsdraw.json` → `<csv>_eplan.json` (`EplanDocument`): registers the E drawing to
the CSV (`dxf_registration.py`) and assigns BMKs to layout parts by rules in
`cfg/e_planning.ini` (distance, target distance, numbering rule `MB = BG + 1`).
`scl_skeleton.py --eplan` fills separator sensor and stopper valve from it; jam sensors
and outfeed/switch valves are assigned but not yet placed in the SCL. See
`doc/Python_Scripts.md` §5c and `doc/E-Planung_Bruecke.md`.
What is **not** built out yet, relative to the original two-tool design:
- the fuller **layout-JSON schema** of `doc/HundM/Json_Layout-Konzept.md` (`plc`,
`controlUnits`, `sensors[]`, `conveyors[]`, `tros[]`, `loadingBooms[]`,
`emptyCarrBuffers[]`, `routing`, `jamAreas[]`, `scanners[]`, `connections[]`,
`destinations[]`) as the intermediate format — `model.TroDocument` is a TRO-focused
JSON, not this full schema yet;
- the **other per-controller blocks** (`FB_CallSensors`, `FC_Direction`/`FC_Call_Jams` as
standalone files) — only `FB_Main` is generated today;
- **type-based timing defaults** from `doc/TRO_Typen.md` and the `OVERRIDE_TIMING_JSON` CAD
attribute (timings are emitted as `TODO(E-Planung): pruefen` placeholders for now);
- `Component` classes per part type (Separator, Switch, Scanner, VarioDrive, …) on the TRO,
driving the per-part SCL emitters in `scl_skeleton.py`.
Note the `create_skel.py` / `guess_fbtype()` generator sketched in `doc/HundM/suggestion.md`
and `doc/HundM/Json_Layout-Konzept.md` §14.5 is a **separate concept** and is not implemented
here: it is designed to derive its skeleton JSON from HundM's Excel I/O-list exports
(`*_TIA.xlsx`, `*_positions.json`, ...), a different input source than this repo's CSV+DXF
pipeline. The JSON *schema* it targets is the same (`doc/HundM/Json_Layout-Konzept.md`); only
the derivation source differs.
## Standard Programm Template
This project follows the user's standard Python project scaffold convention:
```
sps_skel/
bin/ environment scripts, plus one .bat/.sh wrapper pair per lib/ CLI tool
cad/ generated BricsCAD LISP support (tro_types.lsp) for the TROEDIT dialog
cfg/ config files (INI/JSON); dxf_registration.json holds the persisted,
verified CSV<->DXF coordinate transform
data/ input CSV exports — gitignored, not committed
doc/ documentation — see doc/Python_Scripts.md for the CLI tools, plus the
domain-model documents listed above
examples/ example files — empty for now
lib/ Python source, importable via SKEL_LIB on PYTHONPATH — CLI tools and
libraries that derive material flow / TRO lists from a layout, write
them as TRO-JSON (model.py), emit an FB_Main SCL skeleton, and draw
the TROs into the CAD drawing (see doc/Python_Scripts.md)
log/ gitignored
results/ gitignored — CLI tool output (.dot/.svg/.md/.dxf/.scl/.json)
tests/ unit tests (pytest) — test_model.py for the TRO-JSON model
```
When extending the pipeline (the remaining pieces in "Roadmap" above), put new modules under
`lib/` (importable via `SKEL_LIB` on `PYTHONPATH`), add a `bin/<name>.bat`/`.sh` wrapper pair
for each following the pattern of `bin/tro_flow.bat`/`.sh` (see "Environment scripts" above),
document its switches in `doc/Python_Scripts.md`, and add tests under `tests/`.