# 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 DXF → JSON → SCL pipeline in a first version**. From a CSV export (ILS 2.0) it derives a material-flow graph and a TRO list, annotates a copy of the BricsCAD drawing with the result, reads the (possibly hand-edited) drawing back into a TRO-JSON, and emits an `FB_Main` **SCL skeleton** from that JSON. 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/` and `examples/` are 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 + BricsCAD DXF into a material-flow graph, a derived TRO list/diagram, an annotated copy of the drawing, a TRO-JSON read back out of that drawing, and an `FB_Main` SCL skeleton. 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) and `ezdxf>=1.4.0` (DXF read/write, `tro_annotate.py` only); `pytest` is commented out as not yet needed. There is no build/lint/test command configured yet — `tests/` is empty and no test runner or linter is set up. Once tests exist, use `pytest` (already anticipated in `requirements.txt`, just commented out) and set `PYTHONPATH` via `bin/setenv` first so imports resolve against `lib/`. ## 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/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: DXF → JSON → SCL (first version implemented) The DXF → JSON → SCL pipeline now runs end-to-end in a first version. After `tro_annotate.py` burns the TROs into a copy of the drawing, the user can hand-edit that DXF in BricsCAD (via the `TRO_INSERT`/`TRO_EDIT` commands, see `doc/HundM/BricsCAD_TRO_Symbol.md`) — moving TROs, adding new ones, changing a type — and two further `lib/` tools carry the drawing the rest of the way to importable SCL: 1. **`lib/tro_extract.py`** (implemented) — reads the (possibly hand-edited) annotated DXF **only** (not the CSV) and derives a TRO-JSON (`_tro.json`): the TROs tagged with XDATA, their `predecessors`/`successors` computed from the flow arrows, and plant coordinates resolved through the persisted registration. See `doc/Python_Scripts.md` §5a. 2. **`lib/scl_skeleton.py`** (implemented) — reads that TRO-JSON and emits an `FB_Main` SCL skeleton (`_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. 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 — `tro_extract.py` currently emits a TRO-focused JSON, not this full schema; - 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); - a **`--skip-json`** convenience path that would read DXF + CSV directly and emit SCL without an intermediate JSON file. 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 / CAD annotations from a layout, read the TROs back into JSON, and emit an FB_Main SCL skeleton (see doc/Python_Scripts.md) log/ gitignored results/ gitignored — CLI tool output (.dot/.svg/.md/.dxf/.scl/.json) tests/ unit tests — empty for now ``` When extending the pipeline (the remaining pieces in "Roadmap" above), put new modules under `lib/` (importable via `SKEL_LIB` on `PYTHONPATH`), add a `bin/.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/`.