Schritte 1-3 aus doc/SCL_Templates.md (neu: Konzept, Wertklassen je Zeile, Namensregeln, Tests, Migrationsplan, Vertrag fuer den CSV->SCL-Workflow). - Golden-Files (tests/test_scl_skeleton_golden.py, tests/fixtures/scl/): komplette FB_Main-Ausgabe von mubea und HundM05 byte-genau festgeschrieben, Zeitstempel maskiert; gewollte Aenderung per SKEL_UPDATE_GOLDEN=1 - lib/scl_context.py (neu): alles, was scl_skeleton aus der TRO-JSON ableitet (Reihenfolge, Separator-/Weichen-/Scanner-Bloecke, Staubereiche, Ziellisten, Namen) als pydantic-Kontext SclFile/SclTro; Namen als SclName (Wert + todo-Merker) als Andockstelle fuer die Namensregeln (Schritt 4). scl_skeleton schreibt nur noch Text; Ausgabe byte-identisch (Golden-Files, zusaetzlich dematic/showroom mit und ohne --start alt/neu verglichen) - lib/scl_templates/ (neu, Jinja2): _macros.scl.j2 + Pilot FB_ILS_MTRO_1Sep1Swi.scl.j2 nach der realen Aufrufstelle TRO107 (PriorityManagerDir2, stInSenJam<n>, xInCarouselRun1, xInRelease TRUE, Separatorzeiten 100/50 ms). Ortsgebundene Zeilen als Vorschlag umgesetzt, jede offene Stelle mit TODO(E-Planung) - Bestaetigung durch SPS steht aus - scl_skeleton: --templates [DIR] (opt-in, ohne Schalter Ausgabe unveraendert), --strict (Exit 1 ohne SCL, wenn ein FB-Typ kein Template hat); Kopf und Zusammenfassung nennen Template-/generische Typen; Templatefehler (StrictUndefined) -> Exit 1 ohne SCL - tests/test_scl_templates.py: Rundlauf Template mit Referenzwerten == Referenz-REGION (normalisiert); jede Platzhalterzeile traegt den TODO-Marker - requirements.txt: jinja2 >= 3.1 (bestehende .venv: pip install -r requirements.txt) - Doku: SCL_Templates.md, Python_Scripts.md §5b, Commandlines.md §2.5, CLAUDE.md Befunde: xInCarouselRun1 laesst sich nicht aus der TRO-JSON ableiten (Kanten- art "umlauf" kommt praktisch nicht vor) -> immer als TODO; nTo1Destinations ist in der Referenz 3 bei 2 Abgaengen (zaehlt evtl. Ziele) -> "pruefen". Mit --templates nur die 1Sep1Swi-REGIONs (+ Kopf) anders als generisch; 32 Tests gruen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
235 lines
15 KiB
Markdown
235 lines
15 KiB
Markdown
# 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.
|
||
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`)
|
||
- `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`,
|
||
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`.
|
||
|
||
### 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`,
|
||
`OpenPoint`, `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-v2`, `model.TroDocument`): TROs, system boundaries `SYSn`, connections with
|
||
their kind, findings. 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.
|
||
|
||
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);
|
||
- `tro_overrides.py` using the shared `model.Connection` / `model.OpenPoint` classes;
|
||
- `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/`.
|