Files
sps_skel/doc/Konzept_Layout_Hardware_SCL.md
T
Samer AyadiandClaude Opus 5.5 df24cf5adb hw_import + merge_hw_layout: Hardwareplanung einlesen und mit dem Layout zusammenfuehren
Stufen 2 und 3 aus doc/Konzept_Layout_Hardware_SCL.md:

- lib/hw_import.py: TIA-Import (*_TIA.xlsx, ohne openpyxl gelesen) +
  Positionsdatei (*_positionsconv.json) -> <projekt>_hw.json: je BMK
  Adresse, Index-Konstante, VERW, Station, Lage, Foerderer (K0102, #106 ->
  K0106); Antriebe MA/FC/GF; Gegenpruefung beider Quellen.
- lib/merge_hw_layout.py: <csv>_tro.json + <projekt>_hw.json ->
  <csv>_anlage.json (model.AnlageDocument): bindings je TRO-ID + Slot +
  Rolle mit Konstante und Adresse, Foerderer per Mehrheit (Mubea: K0102 =
  Kreisel3, K0104 = Kreisel2, K0105 = Kreisel1), Handkorrekturen
  cfg/hw_overrides.ini. Zuordnungslogik aus e_planning.py hierher
  verschoben; e_planning re-exportiert sie, Ergebnis unveraendert.
- TRO-JSON traegt optional `parts` (Lage/Huellbox, tro_flow --json),
  PinStore bekommt Slots line<n>.
- Gespeicherter Lagebezug mit SHA-256 der Positionsdatei; Unterordner in
  Eingabenamen relativ zu SKEL_DATA.
- Doku: Python_Scripts.md 5d/5e, Konzept, E-Planung_Bruecke (Abgleich
  mubea_layout.dxf / CSV / E-Planung).

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

417 lines
22 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.
# Konzept: Layout und Hardwareplanung → Anlagen-JSON → SCL
Stand 2026-10-11. Zielbild für den Ausbau der Pipeline, damit die beiden
Fachabteilungen unabhängig voneinander und zeitversetzt liefern können. Welche
Angaben aus welcher Quelle kommen, steht in `doc/Datenquellen_Layout_Hardwareplanung.md`;
die Rohangaben beider Quellen in `doc/Klassenhierarchie.md`, Kapitel "Daten".
## Ausgangslage
Die Produktion läuft über zwei Abteilungen:
1. **Anlagenlayout** (aus dem Angebotswesen, detaillierter aus der Projektierung).
Liefert alles für die TROs: Bauteile, Abfolge, Weichen, Staubereiche,
Systemgrenzen.
2. **Hardwareplanung** (Karten, Kabel, Sensoren, Aktoren). Liefert die globalen
Variablen und die tatsächlichen Sensoren und Aktoren mit Namen und Adressen.
Die Hardwareplanung kommt **Tage bis Wochen später** als das Layout. Das System
muss deshalb mit dem Layout allein ein brauchbares SCL-Skelett erzeugen und die
Hardware später nachtragen können, ohne Layout-Arbeit zu wiederholen.
## Zielbild
```text
Abteilung 1: Anlagenlayout Abteilung 2: Hardwareplanung (später)
CSV ──tro_flow──> <csv>_tro.json TIA.xlsx, positionsdraw.json
(TROs, Abfolge, ──hw_import──> <projekt>_hw.json
Staubereiche, Slots) (globale Variablen, Geräte)
│ │
└──────────── merge_hw_layout ─────────────────┘
│
<csv>_anlage.json (Layout + Zuordnungen)
│
scl_skeleton ──> FB_Main.scl, FB_CallSensors.scl, …
```
| Stufe | Skript | Eingabe | Ausgabe | Status |
|---|---|---|---|---|
| 1 Layout | `tro_flow.py --json` | CSV, `cfg/tro_overrides.ini` | `<csv>_tro.json` | vorhanden, wird erweitert |
| 2 Hardware | `hw_import.py` | `*_TIA.xlsx`, `*_positionsdraw.json` (optional `*_EA.xlsx`/`*_WSCAD.xlsx` ohne Positionsdatei) | `<projekt>_hw.json` | vorhanden (2026-10-15), ohne EA/WSCAD |
| 3 Zuordnung | `merge_hw_layout.py` | `<csv>_tro.json`, `<projekt>_hw.json`, Regeln, `cfg/hw_overrides.ini` | `<csv>_anlage.json`, Bericht `.md` | vorhanden (2026-10-15, Logik aus `e_planning.py`) |
| 4 SCL | `scl_skeleton.py` | `<csv>_anlage.json` (oder nur `<csv>_tro.json`) | `.scl` | vorhanden, wird umgestellt |
Grundsätze:
- **Stufe 1 allein reicht für ein Skelett.** Ohne Hardware wird jeder offene Wert
wie heute `TODO(E-Planung)`.
- **Die Stufen verändern sich nicht gegenseitig.** Die Zuordnung legt ihre
Ergebnisse neben das Layout, statt es zu überschreiben. Ein neuer Layoutstand
oder ein neuer Hardwarestand heißt: die betroffene Stufe und alles danach neu
ausführen.
- **Lieber eine Lücke als ein falscher Name** (wie heute in `cfg/e_planning.ini`):
was keine Regel sicher trifft, bleibt offen und steht im Bericht.
- **Drei Quellen, jede sichtbar:** Layout, Hardwareplanung und Defaults
(`cfg/defaults.ini`, Typ-Katalog). Jede SCL-Zeile lässt sich einer davon zuordnen.
## Umbauten
### 1. TRO-JSON zur Layout-JSON ausbauen (Stufe 1)
Heute fehlt der Zuordnung ein Ziel: die TRO-JSON sagt nicht, welche Stellen ein
TRO hat, an die Hardware gehört. Daran scheitern heute Stausensoren und
Weichenventile (`doc/E-Planung_Bruecke.md`, "Offen").
- **Slots je TRO:** je Separator, Weiche, Ausgang und Antrieb ein Eintrag mit der
Layout-ID des Bauteils und den Rollen, die die Hardwareplanung dort füllen muss.
```json
"slots": [
{"slot": "separator1", "layoutId": "0008", "roles": ["sensor", "stopper", "jamSensor?", "partSensor?"]},
{"slot": "switch1", "layoutId": "0037", "exit": 3, "roles": ["valve", "exitSensor?"]},
{"slot": "drive", "layoutId": "0002", "roles": ["carouselRun"]}
]
```
Die Slots ergeben sich aus dem Katalogtyp (`items`) und der Topologie; `?` =
optional, fehlt das Gerät, wird der zugehörige `xPlugged*`-Schalter `FALSE`.
- **Staubereiche als eigene Liste `jamAreas[]`:** ein Staubereich je TRO-Eingang,
mit allen Vorgängern, dem Förderer, auf dem er liegt, und seiner Lage auf dem
Förderer (siehe "Staubereiche" unten). Heute nur abgeleitet beim Rendern
(`scl_context.SclJam`). Dabei korrigieren: `scl_skeleton` erzeugt heute je
Vorgänger einen eigenen Eingang (`arInOutJamEntr1`, `…Entr2`); in den Referenzen
laufen mehrere Vorgänger in **einem** Staubereich zusammen, der TRO hat einen
Eingang (Ausnahme `2Sep1Swi`, PinStore).
- **Weitere Layout-Angaben:** `xIsBorner`, Vorfahrt ja/nein, tragender Förderer
mit Rolle (heute `hosts` ohne Rolle), Längen für `tConvEmpty` und Staulängen.
- **Ableitungen aus `scl_context` nach `tro_flow`/`model` verschieben,** damit die
JSON sie trägt und nicht erst das Rendern sie kennt.
- Schema `sps_skel-tro-v4`.
**Stand (2026-10-11), erster Teil umgesetzt:**
- `model.Slot` und `DerivedTro.slots`: `separator<n>`, `switch<n>`,
`scanner<n>`, `drive` mit Rollen, Anzahl aus dem Katalog (`derive_slots`).
Weichen-Slots haben noch keine `layoutId`: `tro_flow` hält das Weichen- bzw.
Ausschleuselement nicht am TRO fest.
- `model.JamArea` und `TroDocument.jamAreas`: je Separator laut Katalog ein
Eingangs-Staubereich `J<Separator>` mit allen Vorgängern, dem Host und der
Lage (`derive_jam_areas`). Bei 2Sep-Typen ist die Aufteilung der Vorgänger
auf die zwei Eingänge offen (Hinweis im Feld `note`); beim PinStore heißt
der Eingang vorläufig nach dem ersten Linien-Separator.
- `scl_context` liest die Staubereiche aus der JSON: **ein** `JamEntr` je
eigenem Staubereich statt je Vorgänger (Abweichung zu UH01–UH05 behoben),
jeder Ausgang nennt im Kommentar den Staubereich des Nachfolgers. Golden
Files neu erzeugt. Eine v3-Datei ohne `jamAreas` wird weiter gelesen.
- **Noch offen aus Umbau 1:** Layout-ID der Weichen, `xIsBorner`, Vorfahrt,
Host-Rolle, Längen (`tConvEmpty`, Staulängen), `<NNNN>`/`<k>` für den
SCL-Namen der Staubereiche.
### 2. Neues Skript `hw_import.py` (Stufe 2)
- Liest TIA-Import (PLC Tags + Constants) und `positionsdraw.json`. Das genügt:
bei Mubea stehen alle BMK der Positionsdatei im TIA-Import, die Kommentare sind
gleich; EA-Liste und WSCAD-Import bringen nichts dazu (EA ohne Namen, WSCAD nur
die E/A-Baugruppe, die `KENNZEICHNUNG` schon trägt). EA/WSCAD nur als Ersatz,
wenn keine Positionsdatei vorliegt (Weg "nur EA-Liste" in Stufe 3). Befund in
`doc/E-Planung_Bruecke.md`, "Nachprüfung 2026-10-15".
- Schreibt ein neues Modell `HardwareDocument`:
- **Geräte** je BMK: Adresse, Index-Konstante (`cInBG3306`), Kommentar, VERW,
Steuerung, Station/Schrank, Position (falls vorhanden);
- **globale Variablen**: alle Tags und Konstanten, Motor↔Motorschutz-Paare,
Taster, Not-Halt.
- Prüft die Exporte gegeneinander: BMK fehlt in einer Liste, doppelte BMK,
Adresse ohne Tag.
- Übernimmt aus `e_planning.py`: `load_positionsdraw`, `EDevice`, `pair_drives`.
- Erste Quelle: der TIA-Import, weil er Namen und Konstanten 1:1 liefert und die
spätere Prüfung des SCL ermöglicht.
### 3. Neues Skript `merge_hw_layout.py` (Stufe 3)
- Eingabe: `<csv>_tro.json` + `<projekt>_hw.json`; das CSV wird nicht mehr gelesen.
- Zuordnungswege, als Regeln in einer INI (heute `cfg/e_planning.ini`):
- **räumlich** über `positionsdraw`: die bestehende Logik aus `e_planning.py`
(Lagebezug über `dxf_registration`, Höchst-/Sollabstand), jetzt gegen die Slots;
- **Nummernregel**: `MB = BG + 1` bzw. gleiche Nummer, Motor = Motorschutz;
- **nur EA-Liste, ohne Positionen**: über die Kommentare
("in Separator 1 (ILS-CV M0108)") und eine von Hand gepflegte Tabelle
M-Nummer → Layout-Förderer.
- Handkorrekturen in `cfg/hw_overrides.ini` (analog `cfg/tro_overrides.ini`).
- Ausgabe `<csv>_anlage.json`: Layoutteil unverändert, daneben
```json
"bindings": [
{"layoutId": "0008", "role": "sensor", "bmk": "BG3306", "constant": "cInBG3306",
"address": "%E330.6", "source": "positionsdraw", "rule": "raeumlich",
"distance": 12.0, "status": "zugeordnet"}
]
```
`status`: `zugeordnet` | `offen` | `widerspruch`.
- **Stabile Schlüssel:** Zuordnungen hängen an TRO-ID + Slot + Rolle. Die TRO-IDs
sind ab der Festlegung durch die SPS-Programmierer stabil (siehe "TRO-IDs"
unten). Die Layout-`TeileId` taugt dafür **nicht**: sie ändert sich zwischen
zwei CSV-Exporten (siehe dort). `layoutId` in `bindings` dient nur zur
Nachverfolgung im aktuellen Stand.
- **Gegenprüfung** beider Quellen (Anzahl Separatoren vs. `IN SEP`, Weichen vs.
`AE ABZWEIG`, angetriebene Strecken vs. `MA`) in den Bericht.
**Stand Umbau 2/3 (2026-10-15), umgesetzt:**
- `lib/hw_import.py` (`bin/hw_import.bat`): TIA-Import (Blätter an der
Kopfzeile erkannt, xlsx ohne openpyxl gelesen) + Positionsdatei →
`<projekt>_hw.json` (`HardwareDocument`, `sps_skel-hw-v1`): je BMK Adresse,
Richtung, Index-Konstante, VERW, Station, Lage, Förderer; Antriebe mit
Motorschutz und Geber; Gegenprüfung beider Quellen. EA-Liste/WSCAD nicht
gelesen (Weg "nur EA-Liste" bleibt offen).
- `lib/merge_hw_layout.py` (`bin/merge_hw_layout.bat`): `<csv>_tro.json` +
`<projekt>_hw.json` → `<csv>_anlage.json` (`model.AnlageDocument`,
`sps_skel-anlage-v1`): Layout unverändert unter `layout`, daneben
`bindings[]` (Schlüssel TRO-ID + Slot + Rolle, mit Konstante und Adresse aus
dem TIA-Import, Status `zugeordnet`/`offen`/`widerspruch`/`ohne_slot`) und
`conveyors[]`. Handkorrekturen `cfg/hw_overrides.ini`, Zahlenwerte
`cfg/parameter.ini [merge_hw_layout]`.
- Damit `merge_hw_layout` kein CSV liest, trägt die TRO-JSON jetzt `parts` (Lage und
Hüllbox der Layout-Bauteile, von `tro_flow --json`; Schema bleibt v4, eine
Datei ohne `parts` liest sich weiter). Ein `PinStore_Auto` hat je Lagerlinie
einen Slot `line<n>`.
- **Förderernummer:** die E-Planung nennt Förderer im Klartext als `K0102` bzw.
`#106` (beides dieselbe Nummer, `CONVEYOR-#103` = `CONVEYOR-K0103`).
`merge_hw_layout` ordnet sie per Mehrheit der Feldgeräte einem Layout-Förderer zu
(Mubea: K0102 = Kreisel3, K0104 = Kreisel2, K0105 = Kreisel1). Das ist die in
"Staubereiche" gesuchte Quelle für `<NNNN>` und für `xInCarouselRun`.
- Gespeicherter Lagebezug mit SHA-256 der Positionsdatei; ein neuer Stand
gleichen Namens wird neu ermittelt.
- Noch offen: Weichen-/Ausschleus-Slots mit Layout-ID (sonst bleiben
Stausensoren und Ausschleusventile `ohne_slot`), Scanner (`BX`), Weg "nur
EA-Liste", Umstellung von `scl_skeleton` (Umbau 4).
### 4. `scl_skeleton.py` / `scl_context.py` (Stufe 4)
- Liest **eine** Eingabe: `<csv>_anlage.json`; ohne Hardwareteil wie heute
`<csv>_tro.json`.
- `--eplan` und die Zusammenführung in `scl_context._separator` entfallen; der
Kontext liest Namen aus `bindings`, offene Slots werden `TODO(E-Planung)`.
- **Prüfung gegen die globalen Variablen:** jeder Tag und jede `cIn…`-Konstante im
SCL muss im TIA-Import stehen, sonst Abbruch mit Liste.
- **Neue Bausteine** nach Stufe 2: `FB_CallSensors` aus der Sensorliste,
Antriebsaufrufe (`fbCarousel0102`) aus den Motorpaaren, Staubereichs-DBs.
### 5. Defaults als dritte Quelle
Zeiten und Projektkonstanten, die heute fest in `scl_skeleton.py` stehen
(`t#600ms`, `T#1500ms` …), wandern in den Typ-Katalog (`tro_catalog.py`) bzw. eine
Projektdatei `cfg/defaults.ini`.
## Bestehende Programme
| Programm | Rolle im neuen Ablauf |
|---|---|
| `material_flow.py`, `tro_flow.py` | bleiben Stufe 1; Ausbau um Slots und `jamAreas` |
| `tro_catalog.py`, `model.py`, `tro_overrides.py`, `dxf_registration.py` | bleiben Bibliotheken; `model.py` bekommt Slots, `jamAreas`, Anlagen-JSON |
| `e_planning.py` | wird aufgeteilt (unten) |
| `tro_annotate.py` | bleibt als Kontrollansicht, liest künftig die JSON (unten) |
| `tro_extract.py` | entfällt bzw. wird umgebaut (unten) |
| `scl_skeleton.py`, `scl_context.py` | Stufe 4, Umstellung auf `<csv>_anlage.json` |
### `e_planning.py` → `hw_import` + `merge_hw_layout`
| Teil heute | Wohin |
|---|---|
| `load_positionsdraw`, `EDevice`, `pair_drives` | `hw_import.py` |
| `resolve_transform`, `load_rules`, `_assign_spatial`, `_assign_by_number`, Bericht | `merge_hw_layout.py`, Ziele = Slots statt CSV-Bauteile |
| `cfg/e_planning.ini` | Regeldatei von `merge_hw_layout` |
| `EplanDocument` / `<csv>_eplan.json` | entfällt, ersetzt durch `bindings[]` |
Übergang: `e_planning.py` bleibt kurz als Hülle, die `hw_import` und `merge_hw_layout`
nacheinander aufruft, damit `bin/e_planning.bat` weiter funktioniert; danach
löschen.
### `tro_annotate.py` → Kontrollansicht für Layout und Zuordnung
- **Aus der JSON zeichnen** statt `analyse_tros` selbst aufzurufen: die Zeichnung
zeigt dann genau das, woraus das SCL entsteht.
- **Zuordnungen einzeichnen:** neben jedem Slot das BMK (`BG3306`, `MB3306`),
offene Slots und Widersprüche rot. Für die Hardwareplanung die schnellste
Kontrolle der räumlichen Zuordnung.
- `--emit-lisp` (`TROEDIT`) bleibt, solange Marker in BricsCAD bearbeitet werden;
hängt an der Entscheidung zu `tro_extract`.
### `tro_extract.py` → entfällt im neuen Ablauf
Es wäre ein dritter Korrekturweg neben `cfg/tro_overrides.ini` (Layout) und
`cfg/hw_overrides.ini` (Zuordnung) und schreibt noch das alte Schema
`sps_skel-tro-extract-v1`, das niemand mehr liest.
- **Löschen** (Empfehlung), zusammen mit `TROEDIT`/`--emit-lisp`. Korrekturen nur
in den INI-Dateien: nachvollziehbar und versioniert.
- **Umbauen**, falls die Projektierung in BricsCAD korrigieren will: es schreibt
dann Einträge in `tro_overrides.ini`/`hw_overrides.ini`, keine eigene JSON.
Bis zur Entscheidung bleibt es geparkt.
## Festlegungen (2026-10-11)
### TRO-IDs
**Festgelegt:** Die TRO-IDs vergeben die SPS-Programmierer, die zugleich die
Anwender der Skripte sind. Eine ID muss nur **eindeutig** sein. Üblich ist eine
Nummerierung entlang des Materialflusses und eine Benennung nach den Bauteilen
(Kreisel usw.), vorgeschrieben ist das nicht. Sobald größere Teile des SPS-Codes
stehen, ändern sich die IDs nicht mehr; in der frühen Projektphase dürfen sie
mehrmals neu vergeben werden.
**Befund:** Heute vergibt `tro_flow` laufende Nummern je Lauf (`TRO01`, `TRO02` …,
`tro_flow.py` Zeile ~1163); `cfg/tro_overrides.ini` warnt bereits, dass sich die
Nummern bei neuer Datenbasis verschieben. Die Layout-`TeileId` ist ebenfalls nicht
stabil: Vergleich zweier Exporte derselben Anlage
| Vergleich | Bauteile | gleiche Id und Lage | gleiche Lage, andere Id |
|---|---|---|---|
| `mubea.csv` ↔ `mubea_export.csv` | 119 / 125 | 46 | 27 |
| `HundM05.csv` ↔ `HundM05_14.csv` | 45 / 44 | 22 | 16 |
Stabil ist nur die **Lage** des Bauteils.
**Umgesetzt (2026-10-11, `lib/tro_ids.py`, Schalter in `tro_flow.py`;
Einzelheiten in `doc/Python_Scripts.md` §4 "TRO-IDs"):**
- Eine versionierte ID-Datei je Anlage, `cfg/<csv>_tro_ids.ini`, Abschnitt
`[tro]`: je TRO die ID und die Lage seines Anker-Separators (x, y in mm), der
Kommentar dahinter nennt Typ, Bezeichnung und Separatoren. Von `tro_flow`
angelegt, von den SPS-Programmierern umbenannt. Weitere Abschnitte (später
Separator- und Förderernummern) bleiben bei jedem Lauf erhalten. Ein anderer
Export derselben Anlage nutzt dieselbe Datei über `--ids`.
```ini
[tro]
TRO01 = -400.0, 13920.0 ; 1Sep1Swi | Separator 0003 auf Kreisel2 Bahn L | Sep 0003
K0302_1 = 10310.0, -440.1 ; von Hand umbenannt
```
- **Standard (IDs halten):** `tro_flow` liest die ID-Datei und findet jeden TRO
über die Lage seiner Separatoren wieder (Toleranz `--id-tolerance`, Standard
100 mm, nächster Treffer zuerst, je TRO ein Eintrag). Gefundene TROs behalten
ihre ID, auch umbenannte. Neue TROs bekommen die nächste freie Nummer und
werden an `[tro]` angehängt; weggefallene stehen im Bericht (mit dem TRO, der
ihren Separator jetzt enthält), bleiben in der Datei, ihre ID wird nicht
wiederverwendet. `tro_annotate` liest dieselbe Datei, schreibt sie aber nicht.
- **Programmschalter `--renumber` (frühe Phase):** alle IDs neu entlang des
Materialflusses vergeben (Tiefensuche ab den Beladestationen, auf Kreisel und
Strecke in `TrackIds`-Reihenfolge) und `[tro]` neu schreiben. Ohne ID-Datei
geschieht dasselbe beim ersten Lauf.
- **Geprüft** mit `mubea.csv` → `mubea_export.csv` (andere TeileIds): 18 TROs
wiedergefunden, darunter eine umbenannte ID; `TRO14` als weggefallen gemeldet,
weil der Export die Separatoren 0005 und 0036 zu einem `2Sep2Swi` (`TRO13`)
zusammenfasst.
- **Noch offen:** die Abschnitte `[mubea.csv.tro.TRO03]` usw. in
`cfg/tro_overrides.ini` hängen an der alten Nummerierung und passen schon
heute nicht mehr (`TRO03` ist dort Sep 0010, im aktuellen Lauf Sep 0011).
Sie werden auf die IDs der ID-Datei umgestellt, sobald `tro_flow` die
Overrides wieder liest.
- Dadurch werden auch die Abschnitte `[<csv>.tro.<TRO-ID>]` in
`cfg/tro_overrides.ini` und die Zuordnungen von `merge_hw_layout` stabil.
### Staubereiche
**Bisheriges Namensschema** (Referenzen UH01–UH05, `doc/TRO_Katalog/connect.ini`,
286 Staubereiche):
```text
"DB_JamArea<NNNN>".stJam<NNNN>_<k> Kurzform JA<NNNN>_<k>
```
- `<NNNN>` = **Förderer**, auf dem der Staubereich liegt, ein DB je Förderer:
`0102` = Kreisel K0102 (vgl. `#fbCarousel0102`), `0103`/`0104` = Strecken,
`4103`/`4104` = Vario-Förderer.
- `<k>` = laufende Nummer **entlang des Materialflusses** auf diesem Förderer;
Kreisel K0102 hat `_1` … `_6` in Umlaufrichtung.
- 249 der 286 folgen diesem Schema. Sonderfälle: Lagerlinien `Storage1.1.2` (24),
Übergabe an eine andere Steuerung `IO_Device_UHxx_TO_UHyy…` bzw. lokal
`#arCarrierHandoverJam5000` (9), `JamBuffer101` im Leerträgerpuffer (2), F2H (1).
**Prüfung der Annahme "ein Staubereich = Ausgang des Vorgängers und Eingang des
Nachfolgers":**
- **Kein** Staubereich hat mehr als einen Nachfolger-TRO.
- **65** Staubereiche haben mehrere Vorgänger: dort laufen Ströme zusammen, z. B.
`JA0102_2` mit Vorgängern TRO101, TRO106 und TRO107 (Weichenausgang), alle mit
Nachfolger TRO112.
- Jeder TRO hat genau einen Eingangs-Staubereich; einzige Ausnahme sind die
PinStore-TROs (zusätzlich die Lagerlinie).
Ein Staubereich ist also immer **der Eingang genau eines TRO**, aber nicht immer
der Ausgang genau eines Vorgängers. Ein Name nach dem Schema `ja_tro3tro4` ist bei
Zusammenführungen nicht eindeutig.
**Vorschlag:**
**Ergänzung (2026-10-11):** In einem Mubea-Layout heißen die Staubereiche nach
**ihrem Separator**: der Staubereich vor `Sep1024` heißt `J1024`. Das passt zum
Befund oben: der Staubereich ist die Warteschlange vor dem Stopper, also der
Eingang genau eines TRO bzw. genau eines Separators. Das Layout liegt nicht im
Repo; Quelle der Separatornummer (Zeichnungsbeschriftung, E-Planung, Vergabe durch
die SPS-Programmierer) noch klären.
- **Kennung nach dem Separator:** `J<Separatornummer>`, z. B. `J1024`. Das ist
feiner als eine Kennung je TRO und deckt TROs mit mehreren Separatoren
(`2Sep1Swi` mit `JamEntr1`/`JamEntr2`) ohne Sonderregel ab. Zusammenführungen
sind kein Problem, weil der Name nur am Nachfolger hängt.
- **Separatornummern wie TRO-IDs behandeln:** in derselben ID-Datei, über die Lage
des Separators wiedergefunden, von den SPS-Programmierern vergeben bzw.
übernommen; `--renumber` vergibt sie in der frühen Phase neu.
- **Name im SCL — festgelegt: Standard sind die SCL-Dateien UH01–UH05,** also
`"DB_JamArea<NNNN>".stJam<NNNN>_<k>`. `J<Separatornummer>` ist nur die Kennung
in der JSON (und die Beschriftung im Layout), nicht der SCL-Name. Für den
SCL-Namen braucht es je Staubereich:
- `<NNNN>`: die **Förderernummer** des Förderers, auf dem der Staubereich liegt
(Kreisel K0102 → `0102`); vergeben von den SPS-Programmierern bzw. aus der
Hardwareplanung (`KR-K0102`), gepflegt in der ID-Datei wie TRO-IDs und
Separatornummern;
- `<k>`: laufende Nummer **entlang des Materialflusses** auf diesem Förderer,
aus dem Layout abgeleitet (Kreisel in Umlaufrichtung, beginnend an einer
festzulegenden Stelle, z. B. nach der Einschleusung).
Ohne Förderernummer bleibt der Name `TODO(E-Planung)` wie heute.
- Ausnahmen bleiben Sonderfälle mit eigenem Namen: Lagerlinien, Übergabe an eine
andere Steuerung, Leerträgerpuffer.
### Korrekturen in BricsCAD
**Zurückgestellt.** Eine Alternative wäre, die `<csv>_tro.json` zu visualisieren
und von Hand zu bearbeiten. Bis dahin bleibt `tro_extract.py` geparkt, `TROEDIT`
unverändert.
## Reihenfolge
1. **TRO-IDs stabil machen:** ID-Datei, Wiederfinden über die Lage,
`--renumber`. Darauf bauen Overrides, Staubereiche und Zuordnungen auf.
**Erledigt** (2026-10-11).
2. Slots und `jamAreas` in die TRO-JSON (Umbau 1), ein Eingangs-Staubereich je
TRO — ohne Slots hat die Zuordnung kein Ziel. **Erster Teil erledigt**
(2026-10-11, siehe Umbau 1 "Stand").
3. `hw_import` mit dem TIA-Import als erster Quelle. **Erledigt** (2026-10-15,
siehe unten "Stand Umbau 2/3").
4. `merge_hw_layout` mit der räumlichen Logik aus `e_planning.py`; `e_planning.py` als
Übergangshülle. **Erledigt bis auf die Hülle** (2026-10-15): die Logik liegt
in `merge_hw_layout.py`, `e_planning.py` importiert sie und bleibt vollständig,
solange `scl_skeleton --eplan` die `<csv>_eplan.json` liest (Schritt 5).
5. `scl_skeleton` auf `<csv>_anlage.json` umstellen, `--eplan` entfernen;
`tro_annotate` auf JSON umstellen.
6. Defaults (`cfg/defaults.ini`), `FB_CallSensors`, EA-Liste ohne Positionen.
Zu jedem Schritt: `bin/`-Wrapper für neue Skripte, Tests unter `tests/`
(kleine TIA-Datei als Testdaten), Golden Files bei Schemawechsel bewusst neu
erzeugen, `doc/Python_Scripts.md` ergänzen.
## Offene Entscheidungen
- **Staubereiche:** woher die Separatornummer (`Sep1024` → `J1024`) stammt; wo auf
einem Kreisel die Zählung `<k>` beginnt (Referenz K0102 prüfen). Das SCL-Schema
ist festgelegt (UH01–UH05).
- **Toleranz** beim Wiederfinden der TROs über die Lage: vorläufig 100 mm
(`--id-tolerance`). Ein weiter verschobener Separator wird als "neu" und
"weggefallen" gemeldet, der Programmierer übernimmt die ID von Hand in der
ID-Datei. Mit echten Layoutänderungen prüfen, ob der Wert passt.
- **Korrekturen in BricsCAD oder in der JSON:** zurückgestellt.