diff --git a/CLAUDE.md b/CLAUDE.md index 52f929b..dab4c61 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -138,6 +138,16 @@ this order for onboarding: 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 → `_tro.json` (with slots, `jamAreas`), hardware planning → + `hw_import.py` → `_hw.json`, `hw_assign.py` → `_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) diff --git a/doc/Datenquellen_Layout_Hardwareplanung.md b/doc/Datenquellen_Layout_Hardwareplanung.md new file mode 100644 index 0000000..76dc475 --- /dev/null +++ b/doc/Datenquellen_Layout_Hardwareplanung.md @@ -0,0 +1,246 @@ +# Datenquellen für TROs und SCL: mechanisches Layout und Hardwareplanung + +Stand 2026-10-11. Welche Angaben für die TRO-Liste und die erzeugten `.scl`-Bausteine +aus dem **mechanischen Layout** kommen, welche aus der **Hardwareplanung** (EA-Liste +und TIA-Import), und was als **Defaultvorbelegung** gesetzt wird. Die vollständige +Liste der Rohangaben beider Quellen (Spalten, Merkmale, Attribute) steht in +`doc/Klassenhierarchie.md`, Kapitel "Daten", Abschnitte "Angaben 1" und "Angaben 2"; +die Zuordnung jedes SCL-Parameters zu seiner Quelle in den Tabellen danach. +Wie beide Quellen künftig über eine gemeinsame JSON zum SCL werden: +`doc/Konzept_Layout_Hardware_SCL.md`. + +## Die drei Quellen + +| Quelle | Dateien | Liefert im Kern | +|---|---|---| +| **Mechanisches Layout** (Anlagen-Hardware) | CSV-Export ILS 2.0 (`data/*.csv`), aus der BricsCAD-Layoutzeichnung | **Struktur**: welche Bauteile, wer folgt auf wen, Drehrichtung, Längen und Höhen, Anzahl Separatoren/Scanner | +| **Hardwareplanung** (E-Planung) | `-_EA.xlsx`, `-_TIA.xlsx` (PLC Tags + Constants), `-_WSCAD.xlsx`, `_positionsdraw.json` | **Namen und Adressen**: jedes Signal mit BMK, Adresse, Index-Konstante, Rolle, Steuerung, Schaltschrank; mit `positionsdraw` auch die Lage | +| **Defaultvorbelegung** | Typ-Katalog (`lib/tro_catalog.py`), Namensregeln (`scl_context.py`), Projektkonstanten | alles, was weder Layout noch E-Planung kennen: Zeiten, Konstanten-Namen nach Regel, Freigaben, WCS-Ziele | + +Die Schlüssel zwischen den Quellen: + +```text +Layout-Bauteil (TeileId) --[Lage, e_planning.py]--> E-Symbol (BMK, positionsdraw) +E-Symbol (BMK) --[Name]-----------------> TIA PLC Tag (Adresse, Kommentar) + --[cIn]--------------> TIA Constant (Index in DB_Inputs) +E/A-Adresse --[Anschluss]-------------> WSCAD Bezug (Feldstation, Karte) +``` + +EA-Liste und TIA-Import allein haben **keine Lage**, `positionsdraw` hat **keine +Adresse**. Erst über das BMK als gemeinsamen Schlüssel wird aus "Sensor neben +Separator 0008" ein vollständiger SCL-Eintrag mit Adresse und Indexkonstante. + +## Was die Hardwareplanung liefert + +### Für die TROs + +| Angabe | aus | Regel | +|---|---|---| +| Signal gehört zu welchem Layout-Bauteil | `positionsdraw` `pos` | räumlich, `cfg/e_planning.ini` (heute umgesetzt) | +| Rolle des Signals im TRO | `positionsdraw` `VERW`; ersatzweise Kommentar der EA/TIA-Liste | `IN SEP` → Sensor im Separator, `SEP` → Stopperventil, `STAU_REF-LT` → Stausensor, `AE ABZWEIG` → Ausschleusventil, `BT BELADEN` → Beladesensor, `MT in Position`/`ABFR.FINGER`/`conveyor full` → Vario | +| Welche optionalen Sensoren verbaut sind | vorhanden / nicht vorhanden je Rolle | ergibt die `xPlugged*`-Schalter | +| Fördereinheit (M-Nummer) | Kommentar `(ILS-CV M0108)`, `BEZEICHNUNG` `KR-K0102` | Instanzname des Antriebs (`#fbCarousel0102`), Name der Staubereiche (`DB_JamArea0102`) | +| Steuerung, TRO-Nummernkreis | `KENNZEICHNUNG` `=A1+UH01-KF102`, Dateinummer `-`, `mappings` | `UH01` → TRO 1xx | +| Schaltschrank / Bedienfeld | `KENNZEICHNUNG`, WSCAD `Bezug`, `schaltschrank_elemente` | `stInOutMachineState`, Taster `SF…` | +| Motor ↔ Motorschutz | `MA`/`FC` mit gleicher Nummer | `xOutVarioMotor`, `xInMotorProtection` | +| Safety-Signale | WSCAD `Bezug` auf F-Karte (`KF1FDQ…`) | Not-Halt-Kreis, nur Hinweis | +| Plausibilisierung des TRO-Typs | Anzahl "in Separator n", "AE Abzweig", "Pin Abfrage" je M-Nummer | Gegenprüfung des aus dem Layout abgeleiteten Typs | + +### Für die SCL-Dateien + +| Ziel | aus | Bemerkung | +|---|---|---| +| Namen in `FB_Main` (`=> "MB3306"`, `:= "FC0145"`, `"SF0002"`) | TIA PLC Tags `Name` | 1:1 | +| Sensor-Indizes `"DB_Inputs".Sensors["cInBG3306"]` | TIA Constants `cIn` | 1:1; jede Konstante, die der Generator schreibt, muss in diesem Blatt stehen → **Prüfung möglich** | +| `FB_CallSensors`, Größe `DB_Inputs` | alle `cInBG…`/`cInFC…` mit `Value` | noch nicht generiert | +| Variablen- und Konstantentabelle im TIA Portal | der TIA-Import selbst | wird nicht generiert, sondern importiert | +| `stInOutMachineState`, `xInAutomatic`, `xInErrorQuit` | Schrankelemente `SF…`, `KENNZEICHNUNG` | heute `TODO(E-Planung)` | +| `xInSftyOk` | Safety-Programm; WSCAD nur als Hinweis | heute `TODO(E-Planung)` | +| Scanner `BX…`, Cognex-Variablen | **nicht** in EA/TIA-Tagliste (PROFINET) | TIA-Gerätekonfiguration oder `positionsdraw` mit `BX` | + +## Was das mechanische Layout liefert + +### Für die TROs + +| Angabe | aus | Regel / Modul | +|---|---|---| +| Existenz und Grenzen der TROs | Separatoren (`ILS 2.0 Separator`) und ihr Host (`Zuordnung`, `TrackIds`) | `tro_flow.analyse_tros()` | +| TRO-Typ und damit FB | Host Kreisel/Strecke/Gefälle, Weiche, Aus-/Einschleuselement, Scanner | `doc/500573_Mubea/TRO_Identifikation_500573.md`, `tro_catalog` | +| Anzahl Separatoren, Weichen, Scanner je TRO | `Zuordnung`, `Naechster Separator`, Weichen-Merkmale | Parameterblöcke `stInSeparator`, `stInSwitch` | +| Vorgänger/Nachfolger | `Nachbarn` (mit Bahn `-L`/`-R`), `TrackIds`, `Drehrichtung` | `material_flow` → Kanten, Ein-/Ausgangs-Staubereiche | +| Systemgrenzen | `BTMT Beladung`/`Entladung`, `Eingang`/`Ausgang` | `SYSn`, `xIsBorner` | +| Ziele je Weichenabgang | Erreichbarkeit im TRO-Graphen | `nTo1Destinations`, Zielliste | +| Vorfahrt nötig | Einschleuselement / zwei Ströme in einen Staubereich | `xPrioDir`, `xReleaseOk` | +| Tragende Fördertechnik | Host-Kreisel bzw. Gefälle | `xInCarouselRun1/2` | +| angetriebene Strecke | `L_VF_m`, `Antriebfahrtrichtung` `Auf` | Vario | +| Längen | `L_VF_m`, `L_GF_m`, Kreiselabstand | Grundlage für `tConvEmpty`, Staulängen | + +### Für die SCL-Dateien + +REGION-Reihenfolge, FB-Typ, Instanzname, Zahl und Reihenfolge der Parameterzeilen, +Staubereichs-Verkettung (Exit von A = Entr von B), `FC_Direction`-Aufruf mit dem +Carrier aus dem Eingangs-Staubereich, `nTo1Destinations`, Cognex-Dummy bei TROs ohne +Scanner. Das ist heute der Teil, den `scl_skeleton.py` schon ohne E-Planung füllt. + +## Überschneidungen: gegenseitige Prüfung + +Beide Quellen beschreiben dieselbe Anlage, aber unabhängig voneinander. Wo sie sich +überschneiden, prüft die eine die andere: + +| Angabe | Layout | Hardwareplanung | +|---|---|---| +| Separatoren je Strecke/Kreisel | `Anzahl_Separator`, `Zuordnung` | Anzahl `IN SEP`/"in Separator n" je M-Nummer | +| Weiche/Abzweig vorhanden | `ILS Weiche`, `ILS Ausschleuselement` | `AE ABZWEIG`, `ABZWEIG-K104`, `ES branch` | +| Scanner | `ILS 2.0 Scanner` | `BX…` (nur in `positionsdraw` mancher Projekte) | +| angetriebene Strecke | `L_VF_m`, `Auf` | `MA…`/`FC…` mit Bezeichnung der Strecke | +| Lage | `Position` | `pos` (nach Lagebezug `dxf_registration`) | + +Ein Widerspruch (z. B. Layout 6 Separatoren, E-Planung 5 `IN SEP`) heißt meist: +unterschiedliche Planungsstände. Er gehört in den Bericht `_eplan.md`, nicht +stillschweigend in die SCL. + +## Beispielzeilen mit Herkunft + +Zwei reale Aufrufstellen aus `doc/TRO_Katalog/scl_templates/` (UH01), Zeile für Zeile +mit der Quelle als Kommentar: + +- **Layout** = mechanisches Layout (CSV) +- **HW-Planung** = Hardwareplanung (EA-Liste, TIA-Import, WSCAD, `positionsdraw`) +- **Default** = Defaultvorbelegung (Typ-Default, Namensregel, Projektkonstante) + +Bei zwei Quellen steht die führende zuerst: "HW-Planung + Layout" heißt, der Name +kommt aus der Hardwareplanung, die Zuordnung zu diesem TRO bzw. Ausgang aus dem +Layout. Der Status heute (Generator setzt / `TODO(E-Planung)`) steht in den +Tabellen von `doc/Klassenhierarchie.md`. + +Die Codeblöcke sind als `pascal` ausgezeichnet: Markdown-Renderer (VS Code, +GitHub, Gitea) kennen kein `scl`, und SCL ist Pascal-basiert. So werden +Schlüsselwörter, Zuweisungen, Zahlen und `//`-Kommentare hervorgehoben. + +### `FB_ILS_MTRO_1Sep1Swi` (TRO 107, Separator mit Weiche am Kreisel) + +```pascal +REGION TRO 107(1Sep1Swi) // Layout: Typ aus Separator am Kreisel + Ausschleuselement; Nummer 107: Default (Nummernkreis UH01 aus HW-Planung) + #TRO107.stInSeparator1.Settings.nSeparatorNo := "cSep107.1"; // Default: Namensregel cSep.; Anzahl Separatoren: Layout + #TRO107.stInSeparator1.Settings.tDelayToNextItem := "TimeForSepWaiting_Short"; // Default; Short/Medium je Host (Kreisel/Strecke): Layout + #TRO107.stInSeparator1.Settings.tTrailingTime := t#100ms; // Default: Typ-Default, bei IBN prüfen + #TRO107.stInSeparator1.Settings.tHandlingTime := t#50ms; // Default: Typ-Default, bei IBN prüfen + #TRO107.stInSeparator1.Settings.tJam := "TimeForSepJam"; // Default: Projektkonstante + #TRO107.stInSeparator1.Settings.xPluggedJam := TRUE; // HW-Planung: Stausensor (VERW STAU_REF-LT) vorhanden + #TRO107.stInSeparator1.Settings.xPluggedPart := FALSE; // HW-Planung: kein Beladesensor (VERW BT BELADEN) + #TRO107.stInSeparator1.Settings.xPluggedScanner := FALSE; // Layout: kein ILS 2.0 Scanner mit "Naechster Separator" = dieser + #TRO107.stInSeparator1.stSenInSep := "DB_Inputs".Sensors["cInBG3306"]; // HW-Planung + Layout: BG mit VERW IN SEP am Separator; cInBG3306 aus TIA Constants + #TRO107.stInSenJam2 := "DB_Inputs".Sensors["cInBG3305"]; // HW-Planung + Layout: Stausensor; Ausgang 2 = Weiterfahrt auf dem Kreisel + #TRO107.stInSenJam3 := "DB_Inputs".Sensors["cInBG3330"]; // HW-Planung + Layout: Stausensor; Ausgang 3 = Abzweig am Ausschleuselement + + #TRO107.stInSwitch1.Settings.nSwitchNo := "cSwi107.1"; // Default: Namensregel cSwi.; Anzahl Weichen: Layout + #TRO107.stInSwitch1.Settings.xPluggedExSen3 := FALSE; // HW-Planung: Abgangssensor Exit 3 verbaut? + #TRO107.stInSwitch1.Settings.xPluggedExSen4 := FALSE; // HW-Planung: Abgangssensor Exit 4 verbaut? + #TRO107.stInSwitch1.Settings.nTo1Destinations := 3; // Layout: über Abgang 1 erreichbare Ziele (reachable_via) + + #TRO107.stInSettings.xPrioDir2 := TRUE; // Layout: Zusammenführung vor Ausgang 2 -> Vorfahrt nötig + #TRO107(stInPriorityManagerDir2 := "DB_Prozessdaten".stPriorityManager.udt_TRO107.TroIn, // Default: Namensregel udt_TRO; ob nötig: Layout + stOutPriorityManagerDir2 => "DB_Prozessdaten".stPriorityManager.udt_TRO107.TroOut, // Default: Namensregel + nInMainTroNo := "cMainTro107", // Default: Namensregel cMainTro + xInSftyOk := "DB_InterfaceSafety".stFromSafety.EStopMainOF1.Q, // HW-Planung: Not-Halt-Kreis OF1 (Safety-Programm, F-Karten im WSCAD) + xInAllRdyToStart := TRUE, // Default + xInCarouselRun1 := #fbCarousel0102.xOutConveyorFullSpeed, // Layout: Host-Kreisel; Name 0102: HW-Planung (KR-K0102, MA/FC-Bezeichnung) + xInRelease := TRUE, // Default: Freigabe/Testlogik + stInOutMachineState := #stInOutControlUnitCabinetOF1, // HW-Planung: Schaltschrank OF1 (KENNZEICHNUNG, WSCAD Bezug) + stInOutCognexInterface := #stCognexInterfaceDummy, // Layout: kein Scanner am TRO + arInOutJamEntr1 := "DB_JamArea0102".stJam0102_1.arCarrier, // Layout: Vorgänger-Staubereich; DB-Name 0102: HW-Planung (Kreisel K0102) + Default (Index _1) + stInOutJamEntr1 := "DB_JamArea0102".stJam0102_1.stData, // wie oben + arInOutJamExit2 := "DB_JamArea0103".stJam0103_1.arCarrier, // Layout: Nachfolger an Ausgang 2; DB-Name: HW-Planung + Default + stInOutJamExit2 := "DB_JamArea0103".stJam0103_1.stData, // wie oben + arInOutJamExit3 := "DB_JamArea0102".stJam0102_2.arCarrier, // Layout: Nachfolger an Ausgang 3; DB-Name: HW-Planung + Default + stInOutJamExit3 := "DB_JamArea0102".stJam0102_2.stData, // wie oben + stInOutHMI := "DB_Interface_HMI".stTRO.TRO107, // Default: Namensregel + nOutStateLast => "DB_GLOB_TroState".arTroState["cMainTro107"], // Default: Namensregel + xOutStopper1 => "MB3306", // HW-Planung: MB mit VERW SEP, Nummernregel ab BG3306 (TIA PLC Tag) + xOutSw1ExTo3 => "MB3304"); // HW-Planung + Layout: MB AE ABZWEIG am Ausschleuselement von Ausgang 3 + + REGION Direction + "FC_Direction"(nInSwitchNo := "cSwi107.1", // Default: Namensregel + nOutDirection => #TRO107.nInDirection, // Default: fest + InOutCarrier := "DB_JamArea0102".stJam0102_1.arCarrier[1]); // Layout: Carrier aus dem Eingangs-Staubereich + + END_REGION +END_REGION +``` + +### `FB_ILS_MTRO_Vario` (TRO 115, angetriebene Strecke mit Separator) + +```pascal +REGION TRO 115 (Vario) // Layout: Strecke mit L_VF_m / Antriebfahrtrichtung "Auf"; HW-Planung bestätigt (MA, MT in Position) + #TRO115.stInSeparator1.Settings.nSeparatorNo := "cSep115.1"; // Default: Namensregel; Anzahl Separatoren: Layout + #TRO115.stInSeparator1.Settings.tDelayToNextItem := "TimeForSepWaiting_Short"; // Default; Wahl je Host: Layout + #TRO115.stInSeparator1.Settings.tTrailingTime := t#800ms; // Default: Typ-Default Vario, bei IBN prüfen + #TRO115.stInSeparator1.Settings.tHandlingTime := t#300ms; // Default: Typ-Default Vario, bei IBN prüfen + #TRO115.stInSeparator1.Settings.tJam := "TimeForSepJam"; // Default: Projektkonstante + #TRO115.stInSeparator1.Settings.xPluggedJam := FALSE; // HW-Planung: kein Stausensor am Separator + #TRO115.stInSeparator1.Settings.xPluggedPart := FALSE; // HW-Planung: kein Beladesensor + #TRO115.stInSeparator1.Settings.xPluggedScanner := FALSE; // Layout: kein Scanner + #TRO115.stInSeparator1.stSenInSep := "DB_Inputs".Sensors["cInBG3025"]; // HW-Planung + Layout: BG IN SEP am Separator; Index aus TIA Constants + + #TRO115.stInSeparator1.Settings.tSenFree := t#2000ms; // Default: Typ-Default + #TRO115.stInSeparator1.Settings.tSenWait := T#5000ms; // Default: Typ-Default + + #TRO115.stInVario.Settings.xContinousEmptying := FALSE; // Default: Prozessentscheidung + #TRO115.stInVario.Settings.tWaitForJog := T#300ms; // Default: Typ-Default + #TRO115.stInVario.Settings.tConvEmpty := T#45000ms; // Layout: Förderlänge L_VF_m / Geschwindigkeit (Default) -> heute fest + #TRO115.stInVario.Settings.nCountCarrier := 1; // Default: Prozessentscheidung + #TRO115.stInVario.Settings.tWaitForStop := t#3s; // Default: Typ-Default + + #TRO115.stInVario.Settings.tCarrierInPosDelay := t#1200ms; // Default: Typ-Default + #TRO115.stInVario.Settings.tCarrierInPosEdgeDelay := t#100ms; // Default: Typ-Default + + #TRO115.stInVario.Settings.tRasterHigh := t#5s; // Default: Typ-Default + #TRO115.stInVario.Settings.tRasterLow := t#5s; // Default: Typ-Default + + #TRO115.stInVario.stSenCarrInPos := "DB_Inputs".Sensors["cInBG3026"]; // HW-Planung: VERW "MT in Position" an dieser Strecke + #TRO115.stInVario.stSenFinger := "DB_Inputs".Sensors["cInBG3027"]; // HW-Planung: VERW "Finger in position" / ABFR.FINGER + #TRO115.stInVario.stSenLastPos := "DB_Inputs".Sensors["cInBG3000"]; // HW-Planung: VERW "conveyor full" + #TRO115.stInVario.stSenJam := "DB_Inputs".Sensors["cInBG3001"]; // HW-Planung: VERW "Jam detector" / STAU_REF-LT + + #TRO115.stInPriorityManager.xReleaseOk := TRUE; // Layout: keine Zusammenführung -> keine Vorfahrt + #TRO115.stInVario.Settings.xJamSenDelayActive := TRUE; // Default (nur sinnvoll, wenn HW-Planung einen Stausensor hat) + #TRO115.stInVario.Settings.tJamSenDelay := T#2s; // Default: Typ-Default + + #TRO115.stInSettings.xIsBorner := TRUE; // Layout: erster TRO nach Systemgrenze (Beladung/Eingang) + + #TRO115(nInMainTroNo := "cMainTro115", // Default: Namensregel + xInSftyOk := "DB_InterfaceSafety".stFromSafety.EStopMainOF1.Q, // HW-Planung: Not-Halt-Kreis + xInMotorProtection := "FC0145", // HW-Planung: FC mit Nummer des Motors (schaltschrank_elemente, TIA "Meldekontakt Motorschutzschalter") + xInAllRdyToStart := TRUE, // Default + xInReset := "cTodoFalse", // Default + xInErrorQuit := "SF0002", // HW-Planung: Quittiertaster (SF, Schrank) + xInAutomatic := #t_Automatik_OF1 AND "SF0120", // HW-Planung: Schlüsselschalter SF0120; Verknüpfung: Default + xInRelease := "DB_TRO_TEST".TRO115, // Default: Test-/IBN-Freigabe + arInOutJamEntr := "DB_JamArea4104".stJam4104_1.arCarrier, // Layout: Vorgänger-Staubereich; Nummer: HW-Planung (M-Nummer) + Default + stInOutJamEntr := "DB_JamArea4104".stJam4104_1.stData, // wie oben + arInOutJamFinger := "DB_JamArea4103".stJam4103_1.arCarrier, // Layout: Staubereich auf der Vario-Strecke selbst; Nummer: HW-Planung + Default + stInOutJamFinger := "DB_JamArea4103".stJam4103_1.stData, // wie oben + stInOutMachineState := #stInOutControlUnitCabinetOF1, // HW-Planung: Schaltschrank OF1 + stInOutCognexInterface := #stCognexInterfaceDummy, // Layout: kein Scanner + stInOutHMI := "DB_Interface_HMI".stTRO.TRO115, // Default: Namensregel + nOutStateLast => "DB_GLOB_TroState".arTroState["cMainTro115"], // Default: Namensregel + xOutStopper => "MB3025", // HW-Planung: MB VERW SEP, Nummernregel ab BG3025 + xOutVarioMotor => "MA0145"); // HW-Planung + Layout: MA an dieser angetriebenen Strecke (Lage bzw. Bezeichnung) +END_REGION +``` + +### Auszählung der beiden Beispiele + +| Führende Quelle | 1Sep1Swi (39 Zeilen) | Vario (47 Zeilen) | +|---|---|---| +| Layout | 13 | 10 | +| HW-Planung | 11 | 14 | +| Default | 15 | 23 | + +Gezählt sind alle kommentierten Zeilen (Zuweisungen und REGION-Kopf) nach der zuerst +genannten Quelle; "wie oben" zählt wie die Zeile davor. Die Struktur (welche Zeilen es gibt, wie oft, in welcher Reihenfolge) kommt +immer aus dem Layout; die Tabelle zählt, woher der **Wert** einer Zeile kommt. Der +Großteil der Defaults sind Namensregeln und Zeiten, die nach dem Typ-Katalog +vorbelegt und bei der Inbetriebnahme geprüft werden. Fast alle HW-Planung-Zeilen +lassen sich aus TIA-Import und `positionsdraw` füllen; offen bleiben `xInSftyOk` +(Safety-Programm) und die Scanner (PROFINET, nicht im Tag-Import). diff --git a/doc/Klassenhierarchie.md b/doc/Klassenhierarchie.md index b89e6ef..5049ce8 100644 --- a/doc/Klassenhierarchie.md +++ b/doc/Klassenhierarchie.md @@ -443,14 +443,136 @@ Dateien. | Kürzel | Quelle | Was sie liefert | |---|---|---| -| **L** | Hardwarelayout (CSV-Export ILS 2.0, `data/*.csv`) | Bauteile (`TeileArt`: Separator, Scanner, Weiche, Kreisel, Strecke, Gefällestrecke, BTMT Be-/Entladung, Ein-/Ausschleuselement), `Nachbarn`/`TrackIds`, `Merkmale` (Drehrichtung, Antriebfahrtrichtung, Höhen, Längen, Anzahl Separatoren/Scanner, Zuordnung). Daraus abgeleitet: TRO-Typ, Topologie, Reihenfolge, Ziele. | -| **E** | Elektroplanung (EA-Liste/WSCAD/TIA-Variablentabelle, siehe `doc/HundM/EA-Listen-Analyse.md`) | Betriebsmittelkennzeichen und Variablennamen (`BG…` Sensoren, `MB…` Ventile, `MA…` Motoren, `FC…` Motorschutz, `SF…` Taster, `BX…` Scanner), Hardware-Kennungen, welche optionalen Sensoren verbaut sind, Zuordnung zu Schaltschrank und Not-Halt-Kreis. | +| **L** | Anlagen-Hardware = mechanisches Layout (CSV-Export ILS 2.0, `data/*.csv`) | Bauteile (`TeileArt`: Separator, Scanner, Weiche, Kreisel, Strecke, Gefällestrecke, BTMT Be-/Entladung, Ein-/Ausschleuselement), `Nachbarn`/`TrackIds`, `Merkmale` (Drehrichtung, Antriebfahrtrichtung, Höhen, Längen, Anzahl Separatoren/Scanner, Zuordnung). Daraus abgeleitet: TRO-Typ, Topologie, Reihenfolge, Ziele. | +| **E** | Hardwareplanung = Elektroplanung (EA-Liste, TIA-Import, WSCAD-Import, `*_positionsdraw.json`; siehe `doc/HundM/EA-Listen-Analyse.md`) | Betriebsmittelkennzeichen und Variablennamen (`BG…` Sensoren, `MB…` Ventile, `MA…` Motoren, `FC…` Motorschutz, `SF…` Taster, `BX…` Scanner), Hardware-Kennungen, welche optionalen Sensoren verbaut sind, Zuordnung zu Schaltschrank und Not-Halt-Kreis. | | **K** | Namenskonvention | Name folgt aus TRO-Nummer bzw. Staubereichs-/Weichennummer (`cMainTro`, `cSep.`, `"DB_Interface_HMI".stTRO.TRO` …). Keine externe Quelle nötig, sobald Nummernkreis und Regel feststehen. | | **P** | Parameter / Projektstandard | Weder Layout noch E-Planung: Zeiten, Schwellwerte, Projektkonstanten, WCS-/Inbetriebnahme-Logik. Kandidaten für Typ-Defaults (`doc/TRO_Typen.md`). | `L + E` heisst: das Layout sagt, **dass/wie viele** es gibt und **wo**, die E-Planung liefert den **Namen/die Adresse**. Das ist der häufigste Fall. +Die zwei folgenden Abschnitte listen **alle Angaben**, die die beiden externen +Quellen heute enthalten (Stand 2026-10-11, geprüft an `data/*.csv` und an den +Exporten unter `kabellaengen/work/`: `easy_sps-1_EA/_TIA/_WSCAD.xlsx`, +`Mubea_positionsdraw.json`). Was sich daraus für TROs und SCL gewinnen lässt und +zwei kommentierte SCL-Beispiele: `doc/Datenquellen_Layout_Hardwareplanung.md`. + +### Angaben 1: Anlagen-Hardware (mechanisches Layout, CSV) + +Eine Zeile je Bauteil, Trennzeichen `;`, `utf-8-sig`. Gelesen von +`material_flow.load_elements()`. + +#### Spalten (alle Bauteilarten) + +| Spalte | Beispiel | Bedeutung | Nutzen für TRO/SCL | +|---|---|---|---| +| `Elementnummer` | `1` | laufende Zeilennummer des Exports | keiner (nicht stabil) | +| `TeileArt` | `ILS 2.0 Separator` | Bauteilart (Liste unten) | Knotenart, TRO-Typ | +| `TeileId` | `0008` | stabile ID im Layout | Schlüssel für Topologie, Overrides, E-Brücke | +| `Bezeichnung` | `VF_1`, `Kreisel :3` | Klartext aus der Zeichnung | Anzeige, REGION-Kommentar | +| `Planquadrat` | `B/1-C/4` | Raster der Zeichnung | Bericht/Suche | +| `Anzahl` | `1` | Stückzahl | keiner | +| `Position` | `5878.63, 4330.96, 2128.70` | Einfügepunkt x, y, z in mm | Lagebezug zur E-Planung (`dxf_registration`), Abstände | +| `Boundingbox` | `2837.82, 6404.92, 731.58` | Ausdehnung x, y, z in mm | Lage von Weichen/Bahnen | +| `Insertpoint` | `TV0UEkxg…` | kodierter Einfügepunkt (Base64) | intern | +| `K1`–`K4` | `AK41AC7XAFQk` | Anschluss-Koordinatensysteme (Base64, je x/y/z) | Anschlussseite, Lage der AS/ES (`decode_kpoint`) | +| `Nachbarn` | `0006-L, 0014` | berührende Bauteile, bei Kreiseln mit Bahn `-L`/`-R` | Topologie (Kanten) | +| `TrackIds` | `0044, 0027, 0026` | Anbauteile eines Containers in Baureihenfolge bzw. Umlaufrichtung | Reihenfolge Separator/AS/ES auf Strecke und Kreisel | +| `Fehler`, `Warnungen` | `nur ein Partner`, `unverbunden` | Prüfmeldungen des Exports | Qualitätsprüfung | +| `Merkmale` | JSON | artspezifische Eigenschaften (unten) | siehe unten | + +#### Merkmale je `TeileArt` + +| TeileArt | Merkmale | Nutzen für TRO/SCL | +|---|---|---| +| `ILS 2.0 Kreisel` | `Name`, `Kreiselart` (`STANDARD`), `Drehrichtung` (`UZS`/`GUZ`), `Drehung`, `Höhe in m`, `Abstand (Kreiselachse A - Kreiselachse) in Meter`, `Anzahl der Separatoren`, `Anzahl der Scanner`, `Anzahl der Rampen`, `Geruest fuer Einzelmodul` | Host eines TRO (`xInCarouselRun1/2`), Umlaufrichtung → Reihenfolge, Länge → Staulänge; Anzahlen zur Plausibilisierung | +| `ILS 2.0 Strecke` | `Typ` (`Streckengruppe`), `Seite_AS`, `Seite_ES`, `Winkel`, `VF_Winkel`, `DeltaH_mm`, `DeltaL_mm`, `L_VF_m` (angetriebene Teilstücke), `L_GF_m` (Gefälleteilstücke), `Montagehoehe_m`, `Hoehe_Von_mm`, `Hoehe_Bis_mm`, `Antriebfahrtrichtung` (`horizontal`/`Auf`), `Anzahl_Separator`, `Anzahl_Scanner`, `Separatorlist` | angetrieben (`L_VF_m`, `Auf`) → Vario/Antrieb; Längen → `tConvEmpty`, Staulänge; Anzahlen zur Plausibilisierung | +| `ILS 2.0 Gefaellestrecke` | wie Strecke, `L_VF_m` und `Antriebfahrtrichtung` leer | Host "Gefälle" → `1Sep`, `xInCarouselRun1 := TRUE` | +| `ILS 2.0 Separator` | `Zuordnung` (Host, ggf. mit Bahn `-L`/`-R`), `ARTINR`, `Höhe`, `Drehung`, `Typ` | **TRO-Anker**: jeder Separator ist ein TRO oder Teil davon; Host → TRO-Typ | +| `ILS 2.0 Scanner` | `Zuordnung`, `Naechster Separator`, `ARTINR`, `Höhe`, `Drehung`, `Typ` | Scanner am TRO (`xPluggedScanner`, `stInBarcodeReader`, REGION-Titel) | +| `ILS Weiche` | `Kreisel A`, `Kreisel B`, `Achse von Kreisel`, `Beruehrung` (`Kreis/Kreis`), `Erzeugt aus` | Kreisel-Kreisel-Weiche → `1SepNSwi`, `xCar2NecRight/Left`, zweiter Kreisel `xInCarouselRun2` | +| `ILS Ausschleuselement` | `Kreisel`, `Strecke`/`Förderer`, `Streckenende` (`Anfang`), `Element` (`AS_Element_90_links_3D`), `ARTINR`, `Erzeugt aus` | Abgang Kreisel → Strecke: Weichenausgang `Exit3/4`, Ziel je Abgang | +| `ILS Einschleuselement` | wie Ausschleuselement, `Streckenende` `Ende` | Zusammenführung Strecke → Kreisel: Vorfahrt (`xPrioDir`, PriorityManager) | +| `ILS 2.0 BTMT Beladung` / `Entladung` | `ARTINR`, `Höhe`, `Drehung` | Systemgrenze `SYSn`, `xIsBorner`, Ziele; Ladeschleife | +| `Eingang` / `Ausgang` | `ARTINR`, `Höhe`, `Drehung` | Systemgrenze zu Nachbaranlage, Übergabe-Staubereich | + +`ARTINR` (Artikelnummer) unterscheidet Bauarten, z. B. Separator `200000077`, +Scanner `829534306`; daran ließe sich die Weichenbauart (`xNewSwitch`) prüfen. + +Zusätzlich gibt es den **Sivas-Stücklisten-Export** (`data/*_sivas.csv`: +`SivasNummer`, `Dispogruppe`, `Laenge[mm]`, `IDs`, `details` mit +Förder-/Gefällegruppen, Kurven, `MotorSeite`). Er ist eine Stückliste, keine +Topologie, und wird nicht gelesen; brauchbar wäre `MotorSeite` und die +Gruppenlängen. + +**Nicht im Layout:** Betriebsmittelkennzeichen, E/A-Adressen, welche optionalen +Sensoren verbaut sind, Schaltschrank/Steuerung, Zeiten, Ziel-Nummern des WCS. + +### Angaben 2: Hardwareplanung (EA-Liste, TIA-Import, WSCAD-Import, positionsdraw) + +Vier Exporte derselben E-Planung. Gemeinsamer Schlüssel ist das +**Betriebsmittelkennzeichen (BMK)** `BG3306`, `MB3306` …; nur `positionsdraw` +kennt eine Lage, nur EA/TIA/WSCAD kennen die E/A-Adresse. + +**`-_EA.xlsx`** — Blatt "Ein-, Ausgaenge", je SPS `n` eine Datei + +| Spalte | Beispiel | Bedeutung | +|---|---|---| +| `Name` | `E324.0` | E/A-Adresse | +| `Kommentar` | `Stausensor 1 (ILS-CV M0108)` | Funktionsrolle, lfd. Nr., Fördereinheit (M-Nummer), Bereich | +| `Zeile` | `2` | Verweis Schaltplan | + +**`-_TIA.xlsx`** — Importdatei für das TIA Portal + +| Blatt / Spalte | Beispiel | Bedeutung | Nutzen für SCL | +|---|---|---|---| +| PLC Tags `Name` | `BG3240`, `MB3306`, `MA0062`, `FC0062` | BMK = Variablenname | direkt die Namen in `FB_Main` (`=> "MB3306"`, `:= "FC0145"`) | +| PLC Tags `Path` | `Import` | Variablentabelle | Ordner der Variablentabelle | +| PLC Tags `Data Type` | `Bool` | Datentyp (nur Bool) | – | +| PLC Tags `Logical Address` | `%E324.0`, `%A006.2` | Absolutadresse | Prüfung, `FB_CallSensors` | +| PLC Tags `Comment` | `Stausensor 1 (ILS-CV M0108)` | wie EA-Kommentar | Rolle, M-Nummer | +| PLC Tags `Hmi Visible/Accessible/Writeable` | `True` | HMI-Flags | – | +| PLC Tags `Typeobject ID`, `Version ID` | leer | – | – | +| Constants `Name` | `cInBG3240`, `cInFC0062`, `cOutMA0062` | Index-Konstante je Signal | genau die Indizes in `"DB_Inputs".Sensors["cInBG3306"]` | +| Constants `Data Type`, `Value` | `Int`, `1` | Array-Index | Dimensionierung `DB_Inputs` | + +**`-_WSCAD.xlsx`** — Importdatei für das E-CAD + +| Spalte | Beispiel | Bedeutung | Nutzen für SCL | +|---|---|---|---| +| `Anschluss` | `E324.0` | E/A-Adresse | Schlüssel zu EA/TIA | +| `Kommentar` | wie EA | | | +| `Bezug` | `=A01+UC0101-KF1DI1` | Anlage, Feldstation (`UC…`), Baugruppe (`KF1DI1`, `KF1FDQ2` = F-Karte) | Steuerungs-/Schaltschrankzuordnung, Safety-Signale | +| `Symboltext`, `Sondertext 1..8` | meist leer | | | + +**`_positionsdraw.json`** — Kabellängen-Tool, E-Symbole aus der Zeichnung + +| Schlüssel / Attribut | Beispiel | Bedeutung | Nutzen für TRO/SCL | +|---|---|---|---| +| `sensors{BMK@SPS}` | `BG0542@UNKNOWN` | Feldgeräte (BG, MB, MA …) | Hauptquelle der Brücke | +| `.IO` / `.B` | `BG0542` | BMK | Schlüssel zu TIA | +| `.pos` | `[-42369.8, -11437.2]` | Lage in mm | **Zuordnung zum Layout-Bauteil** (`e_planning.py`) | +| `.VERW` | `IN SEP`, `SEP`, `STAU_REF-LT`, `AE ABZWEIG`, `ABZWEIG-K104`, `BT BELADEN`, `SYNC P1..4`, `ABFR.FINGER`, `ÜBERGABE`, `ÜBERNAHME`, `BANDBRUCH`, `KETTENBRUCH`, `ZAPPLER P1`, `MOT_0,37kW` | Verwendung (kontrolliertes Vokabular) | **Rolle** des Signals im TRO | +| `.BEZEICHNUNG` | `STAUSENSOR STR. 01`, `PRÜFUNG BT. POS.1 (KR-K0102 EINFAHRT PUFFER)` | Klartext | Strecken-/Kreiselnummer, Plausibilisierung | +| `.BESCHR` | `STAUSENSOR` | Gerätebeschreibung | – | +| `.KENNZEICHNUNG` | `=A1+UH01-KF102` | Steuerung `UH01`, E/A-Station `KF102` | Steuerung, TRO-Nummernkreis, Schaltschrank | +| `.ARTINR` | `829434300` | Artikelnummer Gerät | Gerätetyp | +| `.SPS` | `''`, `A/B` | SPS-Nummer (oft leer) | Steuerung | +| `.A`, `.C`, `.ID`, `.MENGE`, `.POSITION`, `.GRUPPE`, `.ETIKETTE`, `.AUFLOESE`, `.TEXT-D/E/ES/F` | | Blockattribute des Symbols | – | +| `schaltschrank_elemente{…}` | `FC0200` `MOTORSCHUTZ CONVEYER #100`, `SF…` Taster, `PF…` Leuchten, `QA7000` Hauptschütze, `GF` Encoder, `BP` Druckschalter | Elemente im Schrank, ohne Feldlage | Motorschutz ↔ Motor, Bedienelemente, Encoder | +| `mappings` | `UH01: [BMK …]` bzw. Verteiler → BMK | Zuordnung zur Steuerung/Verteiler aus der Verkabelung | Steuerungsaufteilung | +| `distributors`, `racks`, `tunnels` | | Verteiler, Trassen | – | +| `warnings`, `not_found`, `double_ids` | | Prüfprotokoll | Qualitätsprüfung | + +**BMK-Präfixe:** `BG` Sensor, `SF` Taster/Schalter, `DI` Diagnose, `BP` +Druckschalter, `GF` Encoder, `BX` Scanner (nur PROFINET, nicht in den Digitallisten), +`MB` Ventil (Stopper, Weiche, Ausschleuser), `MA`/`QA` Motor/Schütz, `DQ` +Sonderausgang, `FC` Motorschutz, `PF` Leuchtmelder. + +**Nicht in der Hardwareplanung:** Topologie (wer auf wen folgt), TRO-Grenzen, +Ziele/Weichenrichtungen, Zeiten, Analogwerte und PROFINET-Geräte (Cognex-Variablen +stehen in der TIA-Gerätekonfiguration, nicht im Tag-Import). + ### TRO-Kopf und Instanzaufruf | Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung | diff --git a/doc/Konzept_Layout_Hardware_SCL.md b/doc/Konzept_Layout_Hardware_SCL.md new file mode 100644 index 0000000..fe833a3 --- /dev/null +++ b/doc/Konzept_Layout_Hardware_SCL.md @@ -0,0 +1,323 @@ +# 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──> _tro.json EA/TIA/WSCAD.xlsx, positionsdraw.json + (TROs, Abfolge, ──hw_import──> _hw.json + Staubereiche, Slots) (globale Variablen, Geräte) + │ │ + └──────────── hw_assign ─────────────────┘ + │ + _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` | `_tro.json` | vorhanden, wird erweitert | +| 2 Hardware | `hw_import.py` | `*_TIA.xlsx`, `*_EA.xlsx`, `*_WSCAD.xlsx`, `*_positionsdraw.json` | `_hw.json` | neu | +| 3 Zuordnung | `hw_assign.py` | `_tro.json`, `_hw.json`, Regeln, `cfg/hw_overrides.ini` | `_anlage.json`, Bericht `.md` | neu (Logik aus `e_planning.py`) | +| 4 SCL | `scl_skeleton.py` | `_anlage.json` (oder nur `_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: `_tro.json` + `_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 `_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: `_anlage.json`; ohne Hardwareteil wie heute + `_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 `_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` / `_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/_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 `[.tro.]` 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".stJam_ Kurzform JA_ +``` + +- `` = **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. +- `` = 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:** + +- **Kennung in der JSON nach dem Nachfolger:** `JA_`, z. B. `JA_TRO112`; + ein zweiter Eingang (PinStore) `JA_TRO208_2`. Eindeutig, solange die TRO-IDs + eindeutig sind, und mit ihnen stabil. +- **Name im SCL nach dem bisherigen Schema** `"DB_JamArea".stJam_`: + `` lässt sich aus dem Layout ableiten (Reihenfolge auf dem Förderer in + Flussrichtung), `` ist die Förderernummer. Die vergeben wie die TRO-IDs + die SPS-Programmierer bzw. sie kommt aus der Hardwareplanung (`KR-K0102`); sie + steht in derselben ID-Datei (`[mubea.foerderer]`, `K0102 = `). Ohne + Förderernummer bleibt der Name `TODO(E-Planung)` wie heute. +- **Alternative,** falls das alte Schema nicht nötig ist: SCL-Name direkt aus der + Kennung (`"DB_JamArea".JA_TRO112`); braucht keine Förderernummern, weicht aber + von den bestehenden Projekten und deren `FC_Call_Jams` ab. Entscheidung offen. + +### Korrekturen in BricsCAD + +**Zurückgestellt.** Eine Alternative wäre, die `_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 `_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 + +- **SCL-Name der Staubereiche:** bisheriges Schema mit Förderernummer (Empfehlung) + oder neues Schema direkt aus `JA_`. +- **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.