Files
sps_skel/doc/Konzept_Layout_Hardware_SCL.md
T
Michael StanglandClaude Opus 5.5 ef57a2218e Konzept: Staubereiche nach Separator, SCL-Namen nach UH01-UH05
- Kennung der Staubereiche in der JSON nach ihrem Separator (J<Sep>,
  wie im Mubea-Layout J1024 fuer Sep1024)
- SCL-Name festgelegt auf den Standard UH01-UH05:
  "DB_JamArea<NNNN>".stJam<NNNN>_<k> (Foerderernummer, Reihenfolge
  entlang des Materialflusses)
- Separator- und Foerderernummern wie TRO-IDs in der ID-Datei

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

342 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.
# 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 EA/TIA/WSCAD.xlsx, positionsdraw.json
(TROs, Abfolge, ──hw_import──> <projekt>_hw.json
Staubereiche, Slots) (globale Variablen, Geräte)
│ │
└──────────── hw_assign ─────────────────┘
│
<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`, `*_EA.xlsx`, `*_WSCAD.xlsx`, `*_positionsdraw.json` | `<projekt>_hw.json` | neu |
| 3 Zuordnung | `hw_assign.py` | `<csv>_tro.json`, `<projekt>_hw.json`, Regeln, `cfg/hw_overrides.ini` | `<csv>_anlage.json`, Bericht `.md` | neu (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`.
### 2. Neues Skript `hw_import.py` (Stufe 2)
- Liest TIA-Import (PLC Tags + Constants), EA-Liste, WSCAD-Import und optional
`positionsdraw.json`.
- 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 `hw_assign.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.
### 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` + `hw_assign`
| Teil heute | Wohin |
|---|---|
| `load_positionsdraw`, `EDevice`, `pair_drives` | `hw_import.py` |
| `resolve_transform`, `load_rules`, `_assign_spatial`, `_assign_by_number`, Bericht | `hw_assign.py`, Ziele = Slots statt CSV-Bauteile |
| `cfg/e_planning.ini` | Regeldatei von `hw_assign` |
| `EplanDocument` / `<csv>_eplan.json` | entfällt, ersetzt durch `bindings[]` |
Übergang: `e_planning.py` bleibt kurz als Hülle, die `hw_import` und `hw_assign`
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.
**Vorschlag:**
- Eine versionierte ID-Datei je Anlage, z. B. `cfg/<anlage>_tro_ids.ini`: je TRO
die ID und die Lage seines Anker-Separators (x, y in mm), optional ein Name.
Von `tro_flow` angelegt, von den SPS-Programmierern umbenannt.
```ini
; Beispiel, Werte erfunden
[mubea]
TRO107 = 12450.0, 3310.0 ; Kreisel 2 vor Beladung
TRO108 = 13250.0, 3310.0
```
- **Standard (IDs halten):** `tro_flow` liest die ID-Datei und findet jeden TRO
über die Lage des Anker-Separators wieder (Toleranz einstellbar). Gefundene TROs
behalten ihre ID. Neue TROs bekommen eine vorläufige ID (nächste freie Nummer
entlang des Materialflusses) und stehen im Bericht; weggefallene TROs stehen im
Bericht, ihre ID wird nicht automatisch wiederverwendet.
- **Programmschalter `--renumber` (frühe Phase):** alle IDs neu entlang des
Materialflusses vergeben und die ID-Datei neu schreiben.
- Dadurch werden auch die Abschnitte `[<csv>.tro.<TRO-ID>]` in
`cfg/tro_overrides.ini` und die Zuordnungen von `hw_assign` 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.
2. Slots und `jamAreas` in die TRO-JSON (Umbau 1), ein Eingangs-Staubereich je
TRO — ohne Slots hat die Zuordnung kein Ziel.
3. `hw_import` mit dem TIA-Import als erster Quelle.
4. `hw_assign` mit der räumlichen Logik aus `e_planning.py`; `e_planning.py` als
Übergangshülle.
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; Verhalten, wenn ein
Separator weiter verschoben wurde (Vorschlag: als "neu" + "weggefallen" melden,
der Programmierer übernimmt die ID von Hand).
- **Korrekturen in BricsCAD oder in der JSON:** zurückgestellt.