Merge e-planung-bruecke: stabile TRO-IDs, TRO-JSON v4, E-Planung-Bruecke
Uebernimmt Michael Stangls Zweig (tro_ids, Slots/jamAreas v4, e_planning --eplan, Konzept- und Datenquellen-Doku) in master, auf dem seitdem die SCL-Templates fuer alle 7 Typen mit Referenz-Aufrufstelle liegen. Konfliktloesung: - lib/scl_context.py: beide Seiten zusammengefuehrt - Michaels _separator (E-Planung-Namen) und Staubereiche (_entries/_exit_area, ein JamEntr je eigenem Staubereich) plus die Template-Felder (_scanner, _store, carriers/data, part_sensor). _jam() fuehrt jetzt auch jam_id. Die beim automatischen Zusammenfuehren verlorene Property SclJam.title wiederhergestellt. - Templates 1Sep, 1Sep2Swi, 1Sep_SSCC, Vario, Vario_workStation, PinStore_Auto auf v4 nachgezogen: Kommentar "Staubereich J.... von/vor ..." wie im Pilot; PinStore-TODO zaehlt Staubereiche statt Nachbarn (mubea: 2 Zulaeufe laufen in einen Eingang). - Golden-Files *_templates neu erzeugt; geaendert sind ausschliesslich Staubereichs-Zeilen (Kennung im Kommentar, ein Eingang statt einem je Vorgaenger). Generische Golden-Files = Michaels Stand. - Neuer Test: E-Planung-Namen kommen auch in der Template-Ausgabe an. - Doku: README Schema v4, SCL_Templates.md Staubereiche und TODO-Zahlen. Geprueft: 71 Tests gruen; tro_flow --json + scl_skeleton --templates auf allen 8 CSVs ohne Fehler. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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) | `<projekt>-<n>_EA.xlsx`, `<projekt>-<n>_TIA.xlsx` (PLC Tags + Constants), `<projekt>-<n>_WSCAD.xlsx`, `<zeichnung>_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<BMK>]--------------> 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 `-<n>`, `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<BMK>` | 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<n>`, `stInSwitch<n>` |
|
||||
| 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 `<csv>_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<TRO>.<n>; 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<TRO>.<n>; 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<n>; ob nötig: Layout
|
||||
stOutPriorityManagerDir2 => "DB_Prozessdaten".stPriorityManager.udt_TRO107.TroOut, // Default: Namensregel
|
||||
nInMainTroNo := "cMainTro107", // Default: Namensregel cMainTro<n>
|
||||
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).
|
||||
@@ -0,0 +1,161 @@
|
||||
# Brücke Layout ↔ E-Planung über `*_positionsdraw.json`
|
||||
|
||||
Stand 2026-10-10. Erst Machbarkeitsprüfung, inzwischen umgesetzt als
|
||||
`lib/e_planning.py` (Regeln `cfg/e_planning.ini`, Aufruf `bin/e_planning.bat`,
|
||||
`scl_skeleton --eplan`); Bedienung in `doc/Python_Scripts.md` §5c, Stand der
|
||||
Umsetzung unten.
|
||||
|
||||
## Problem
|
||||
|
||||
Das Kapitel "Daten" in `doc/Klassenhierarchie.md` zeigt: das Hardwarelayout (CSV)
|
||||
liefert die **Struktur** (welche TROs, welche Separatoren/Weichen, wer mit wem), die
|
||||
E-Planung die **Namen und Adressen** (`BG…`, `MB…`, `MA…`, `FC…`). Die EA-Liste allein
|
||||
kennt aber keine Topologie. Es fehlt die Zuordnung **Layout-Bauteil (CSV-`TeileId`) →
|
||||
Betriebsmittelkennzeichen (BMK)**.
|
||||
|
||||
## Idee
|
||||
|
||||
Die E-Planung wird als Layer über der Hardwareplanung gezeichnet: Sensor- und
|
||||
Aktorsymbole liegen in der Zeichnung neben dem Bauteil, zu dem sie gehören. Das
|
||||
Kabellängen-Tool (`C:\10-Develop\gitrepos\kabellaengen`, `lib/getpositions.py`)
|
||||
schreibt diese Symbole mit Position und Attributen nach `<zeichnung>_positionsdraw.json`.
|
||||
Damit ist die Brücke eine **räumliche Zuordnung**: E-Symbol → nächstes Layout-Bauteil
|
||||
passender Art.
|
||||
|
||||
## Datenquelle `*_positionsdraw.json`
|
||||
|
||||
| Schlüssel | Inhalt | Nutzen für sps_skel |
|
||||
|---|---|---|
|
||||
| `sensors` | je BMK (`BG0642@UNKNOWN`): `pos` [x, y], `VERW` (Verwendung), `BEZEICHNUNG` (Klartext), `BESCHR`, `ARTINR`, `KENNZEICHNUNG` (`=A1+UH01-KF107`) | Hauptquelle: Sensoren/Ventile/Motoren im Feld |
|
||||
| `schaltschrank_elemente` | Elemente im Schrank (Motorschutz `FC…`, Taster, Leuchten, `QA…`) mit `VERW`, `BEZEICHNUNG`, `KENNZEICHNUNG`, ohne Feldposition | Motorschutz ↔ Motor, Bedienelemente |
|
||||
| `mappings` | Steuerung → Liste ihrer BMK (`UH01: [...]`) | Steuerungsaufteilung, Nummernkreis |
|
||||
| `racks`, `distributors`, `tunnels` | Kabeltrassen, Verteiler | für sps_skel ohne Belang |
|
||||
| `double_ids`, `warnings` | doppelte BMK, fehlende Attribute | Qualitätsprüfung der E-Daten |
|
||||
|
||||
Die Erdungs-Beispiele (`PR500501_…_Erdung_…`, `ST500652_…`) enthalten nur
|
||||
Potentialausgleich (`POT…`) und taugen nicht für die Brücke. Brauchbar sind
|
||||
Dateien mit `BG`/`MB`/`MA`: `Mubea_positionsdraw.json` (157 Feld-BMK),
|
||||
`ST500592_ILS_positionsdraw.json` (~3100), `ST500592_10_5-10_Omniflo_…` (~900),
|
||||
`ST-Fortna_positions_.json` (mit 38 Scannern `BX`).
|
||||
|
||||
## Test an Mubea
|
||||
|
||||
Eingaben: `data/mubea.csv` (Layout, 38 Separatoren) und
|
||||
`kabellaengen/work/Mubea_positionsdraw.json` (E-Planung). Die Zahlen in diesem
|
||||
Abschnitt stammen aus der ersten Untersuchung (Umkreis 700 mm, ohne Regeln); das
|
||||
Ergebnis der Umsetzung steht unten.
|
||||
|
||||
### 1. Lagebezug
|
||||
|
||||
Die Ermittlung aus `lib/dxf_registration.py` (`derive_transform`) funktioniert
|
||||
unverändert, wenn man die E-Symbole mit `VERW` `SEP`/`IN SEP` als Rolle "Separator"
|
||||
einsetzt:
|
||||
|
||||
```text
|
||||
mubea.csv <- Mubea_positionsdraw.json: dx +50613.6 mm, dy +8555.8 mm, Drehung 0
|
||||
26/38 Separatoren im Toleranzband
|
||||
```
|
||||
|
||||
Das entspricht dem schon gespeicherten Bezug `mubea.csv|500573_60_1.dxf`
|
||||
(dx +50833.7, dy +8414.5) bis auf ~250 mm: die E-Zeichnung liegt im selben
|
||||
Koordinatensystem wie die Layoutzeichnung. Zum Prüfen genügt also der
|
||||
bestehende Mechanismus; als Schlüssel in `cfg/dxf_registration.json` kann
|
||||
`<csv>|<positionsdraw.json>` dienen.
|
||||
|
||||
### 2. Was sich zuordnen lässt
|
||||
|
||||
| E-Symbol (`VERW`) | Layout-Partner | Abstand | Ergebnis |
|
||||
|---|---|---|---|
|
||||
| `IN SEP` (BG, Sensor im Separator) | Separator | **0–1 mm** im Pin-Speicher (20/20), sonst 200–500 mm | Anker: das Symbol sitzt auf dem Separator |
|
||||
| `SEP` (MB, Stopperventil) | Separator | konstant **~270 mm** daneben | eindeutig über Nummernregel (unten), nicht über Abstand |
|
||||
| `AE ABZWEIG` (MB, Ausschleusventil) | Ausschleuselement | konstant **1414 mm** (20/20, Versatz (−1405, −159)) | eindeutig, wenn der Versatz je Symbolart bekannt ist |
|
||||
| `STAU_REF-LT` (BG, Stausensor) | Ausschleuselement | konstant **1391 mm** (20/20) | wie oben |
|
||||
| `ABZWEIG-K104` (MB, Weiche) | Weiche | 783 mm | eindeutig (nur eine Weiche) |
|
||||
| `BANDBRUCH`, `KETTENBRUCH`, `ÜBERGABE`/`ÜBERNAHME`, `SYNC P1..4`, `ZAPPLER` | Kreisel/Strecke/Station | uneinheitlich, teils > 50 m (Symbol an Konvejoren außerhalb des CSV-Ausschnitts) | nicht über Abstand, nur über `BEZEICHNUNG` |
|
||||
|
||||
Nebeneinander liegende Separatoren (Pin-Speicher, Raster 800 mm) machen den
|
||||
Abstand allein mehrdeutig: das MB von Strecke n liegt 270 mm von Separator n und
|
||||
530 mm von Separator n+1. Eindeutig wird es erst mit der Nummernregel.
|
||||
|
||||
### 3. Nummernregel der E-Planung
|
||||
|
||||
Ventil = Sensor + 1, gleiche Funktionsgruppe:
|
||||
|
||||
| Paar | Treffer (von 58 MB) |
|
||||
|---|---|
|
||||
| `MB(n)` `SEP` ↔ `BG(n−1)` `IN SEP` (z. B. BG0642 / MB0643) | 31 |
|
||||
| `MB(n)` `AE ABZWEIG` ↔ `BG(n−1)` `STAU_REF-LT` (z. B. BG0542 / MB0543) | 21 |
|
||||
| sonstige Paare (`VEREINZ(CP)`, `STOPPER (CP)`, `AE ABZW.`) | 3 |
|
||||
| ohne BG-Partner | 3 |
|
||||
|
||||
Damit reicht es, den **Sensor** räumlich zuzuordnen (der `IN SEP` liegt auf dem
|
||||
Separator); das Ventil folgt aus der Nummer. Die SCL-Referenzen zeigen dasselbe
|
||||
Muster (`stSenInSep := …["cInBG3242"]`, `xOutStopper1 => "MB3242"`) — dort sogar
|
||||
mit gleicher Nummer; die Regel ist also projektabhängig und gehört in eine
|
||||
Konfiguration, nicht in den Code.
|
||||
|
||||
Gleiches gilt für Motor ↔ Motorschutz: `MA0200` "PIN CONVEYOR#100" ↔
|
||||
`FC0200` "MOTORSCHUTZ CONVEYER #100" (gleiche Nummer, `schaltschrank_elemente`),
|
||||
wie in der SCL `xOutVarioMotor => "MA0145"`, `xInMotorProtection := "FC0145"`.
|
||||
|
||||
### 4. Was nicht passt
|
||||
|
||||
12 von 38 Layout-Separatoren (vor allem an den Kreiseln K0102/K0104/K0105) haben im
|
||||
Umkreis von 700 mm kein `IN SEP`/`SEP`; umgekehrt liegen mehrere `IN SEP` des
|
||||
Kreisels K0102 neben Aus-/Einschleuselementen statt neben einem Separator. Vermutlich
|
||||
ist die CSV (aus `500573_60_1.dxf`) ein anderer Planungsstand als die E-Zeichnung
|
||||
`Mubea.dxf` des Kabellängen-Tools, oder Kreisel-Separatoren sind im CSV anders
|
||||
modelliert. Das muss mit zueinander passenden Ständen geprüft werden, bevor man
|
||||
eine Quote angibt.
|
||||
|
||||
`Mubea_positionsdraw.json` enthält **keine Scanner** (`BX`). Für Scanner-Zuordnung
|
||||
ist ein anderes Projekt nötig (`ST-Fortna_positions_.json`, `ILS-Baugruppe`).
|
||||
|
||||
## Was die Brücke für das Kapitel "Daten" liefert
|
||||
|
||||
| SCL-Datum | aus `positionsdraw.json` | Regel |
|
||||
|---|---|---|
|
||||
| `stInSeparator<n>.stSenInSep` | BG mit `VERW` `IN SEP` | räumlich am Separator (Anker) |
|
||||
| `xOutStopper<n>` | MB mit `VERW` `SEP` | Nummernregel ab dem BG |
|
||||
| `stInSenJam<n>`, `Settings.xPluggedJam` | BG `STAU_REF-LT` | räumlich, Versatz je Symbolart; vorhanden ⇒ `xPluggedJam := TRUE` |
|
||||
| `xOutSw<n>ExTo3/4` | MB `AE ABZWEIG` / Weichen-MB | Nummernregel ab dem Stausensor bzw. räumlich an Weiche/Ausschleuselement |
|
||||
| `Settings.xPluggedPart`, `stSenPart` | BG `BT BELADEN` | räumlich; vorhanden ⇒ `TRUE` |
|
||||
| `xInMotorProtection`, `xOutVarioMotor` | MA im Feld + FC in `schaltschrank_elemente` | gleiche Nummer |
|
||||
| `xInCarouselRun` (welcher Antrieb) | FC/MA-`BEZEICHNUNG` "KREISEL-K0102", "CONVEYOR #100" | Textabgleich mit dem Host-Kreisel des TRO |
|
||||
| Steuerung, TRO-Nummernkreis, `stInOutMachineState` | `KENNZEICHNUNG` `=A1+UH01-KF107`, `mappings` | `UH01` = Steuerung, `KF107` = E/A-Station |
|
||||
| Plausibilisierung | `BEZEICHNUNG` "SEPARATOR STR. 14", "KR-K0102 VOR BT-BELADUNG" | Strecken-/Kreiselnummer gegen Layout prüfen |
|
||||
|
||||
Nicht aus dieser Quelle: Not-Halt-Kreis (`xInSftyOk`), Taster für Automatik/Quittieren
|
||||
(stehen nur als Schrankelemente ohne Bezug zum TRO), Scanner-Hardwarekennungen,
|
||||
Weichenbauart (`xNewSwitch`).
|
||||
|
||||
## Umsetzung (Stand 2026-10-10)
|
||||
|
||||
1. **`lib/e_planning.py`**: liest `*_positionsdraw.json` in `EDevice` (BMK, VERW,
|
||||
Bezeichnung, Kennzeichnung → Steuerung/E/A-Station, Position).
|
||||
2. **Lagebezug** über `dxf_registration.derive_transform` mit den `IN SEP`-Sensoren
|
||||
als Rolle "Separator"; abgelegt in `cfg/dxf_registration.json` unter
|
||||
`<csv>|<positionsdraw.json>`.
|
||||
3. **Regeln in `cfg/e_planning.ini`** (projektabhängig): je Rolle Layout-Art, VERW,
|
||||
Höchstabstand, **Sollabstand** (für die konstanten Versätze von Stausensor und
|
||||
Ausschleusventil — sonst gewinnt bei 0080/0084 ein näherer, fremder Stausensor
|
||||
des Kreisels K0102) und die Nummernregel (`MB = BG + 1`).
|
||||
4. **Ausgabe** `<csv>_eplan.json` (`EplanDocument`) und Bericht `<csv>_eplan.md`.
|
||||
`scl_skeleton --eplan` setzt Separator-Sensor und Stopperventil ein
|
||||
(`SclName.todo = False`); alles andere bleibt `TODO(E-Planung)`.
|
||||
|
||||
Ergebnis Mubea mit den ausgelieferten Regeln: Separator-Sensor 21/38,
|
||||
Stopper 22/38, Stausensor 20/23, Ausschleusventil 20/23, Weichenventil 1/1. Den
|
||||
Separator-Sensor nimmt die Regel nur bis 300 mm; die Kreisel-Fälle mit 470–540 mm
|
||||
(z. B. BG0532 an 0044) bleiben bewusst offen.
|
||||
|
||||
Offen:
|
||||
|
||||
- Stausensoren und Ausschleus-/Weichenventile stehen in JSON und Bericht, kommen
|
||||
aber noch nicht in die SCL: die TRO-JSON sagt nicht, welches Ausschleuselement
|
||||
bzw. welche Weiche zu welchem TRO-Ausgang gehört.
|
||||
- Die Lagerlinien eines `PinStore`-TRO (`arInSep[n]`) sind zugeordnet, der
|
||||
Generator erzeugt die Linienparameter aber noch nicht.
|
||||
- Scanner (`BX`) fehlen in den Mubea-Daten; Regel und Test mit
|
||||
`ST-Fortna_positions_.json` stehen aus.
|
||||
- Ein Abgleich mit passenden Ständen von CSV und E-Zeichnung für die Kreisel.
|
||||
+329
-4
@@ -31,6 +31,8 @@ scl_skeleton.py (Ausgabe: SclFile -> FB_Main.scl, generisch oder per Jin
|
||||
|
||||
material_flow.py dxf_registration.py (eigenständig, ohne Abhängigkeit auf obige)
|
||||
tro_overrides.py (importiert model.Connection / model.TroCandidate)
|
||||
e_planning.py (Brücke zur E-Planung; importiert dxf_registration, liest das
|
||||
CSV über material_flow; scl_context kennt nur EplanDocument)
|
||||
```
|
||||
|
||||
`tro_flow.py` und `tro_annotate.py` definieren keine eigenen Klassen (nur
|
||||
@@ -68,8 +70,11 @@ lib/model.py [Instanz-Ebene / TRO-JSON]
|
||||
├── TroBase(BaseModel)
|
||||
│ └─ definition() --> TroDefinition (gelesen aus tro_catalog, nicht gespeichert)
|
||||
│ └── DerivedTro(TroBase) [einzige echte Vererbung im Projekt]
|
||||
│ └─ slots: list[Slot] (Stellen fuer die Hardwareplanung)
|
||||
├── _Positioned(BaseModel) (Mixin: position {x,y,z}, describe_position)
|
||||
│ ├── TroBase, TroCandidate
|
||||
│ ├── TroBase, TroCandidate, JamArea
|
||||
├── Slot(BaseModel) (separator1/switch1/scanner1/drive + Rollen)
|
||||
├── JamArea(_Positioned) (Staubereich J<Sep>: Eingang eines TRO)
|
||||
├── Connection(BaseModel) (from/to/kind zwischen zwei TRO-IDs)
|
||||
├── TroCandidate(_Positioned) (gemeldete Stelle, an der ein TRO erwartet wird)
|
||||
├── Analysis(BaseModel)
|
||||
@@ -80,7 +85,8 @@ lib/model.py [Instanz-Ebene / TRO-JSON]
|
||||
├─ tros: list[DerivedTro]
|
||||
├─ boundaries: list[DerivedTro]
|
||||
├─ connections: list[Connection]
|
||||
└─ candidates: list[TroCandidate]
|
||||
├─ candidates: list[TroCandidate]
|
||||
└─ jam_areas: list[JamArea] (JSON: jamAreas)
|
||||
|
||||
lib/material_flow.py [CSV-Rohmodell -> Graph, @dataclass]
|
||||
├── Element (1 CSV-Zeile)
|
||||
@@ -132,6 +138,17 @@ lib/scl_context.py [Render-Kontext für die SCL, BaseM
|
||||
|
||||
lib/scl_skeleton.py [SCL-Ausgabe]
|
||||
└── SclTemplates (Ordner mit <fbType>.scl.j2, hält ein jinja2.Environment)
|
||||
|
||||
lib/e_planning.py [Brücke Layout <-> E-Planung]
|
||||
├── EDevice(BaseModel) (ein BMK aus *_positionsdraw.json: VERW, Bezeichnung, Position)
|
||||
├── LayoutPoint (@dataclass: punktartiges Layout-Bauteil in CSV-Koordinaten)
|
||||
├── Rule (@dataclass: eine Regel aus cfg/e_planning.ini)
|
||||
├── Assignment(BaseModel) (BMK in einer Rolle an einem Layout-Bauteil, mit Abstand)
|
||||
├── Drive(BaseModel) (Motor MA ↔ Motorschutz FC)
|
||||
└── EplanDocument(BaseModel) (= <csv>_eplan.json)
|
||||
├─ transform: Transform (aus dxf_registration)
|
||||
├─ assignments: list[Assignment]
|
||||
└─ drives: list[Drive]
|
||||
```
|
||||
|
||||
## Auffälligkeiten für ein mögliches Refactoring
|
||||
@@ -238,13 +255,14 @@ Kantenarten) → Prüfung gegen den Katalog.
|
||||
|
||||
### `TroDocument` — `lib/model.py`
|
||||
|
||||
**Wozu:** Die TRO-JSON `<csv>_tro.json` (Schema `sps_skel-tro-v3`) — die
|
||||
**Wozu:** Die TRO-JSON `<csv>_tro.json` (Schema `sps_skel-tro-v4`) — die
|
||||
Schnittstelle zwischen Ableitung (`tro_flow --json`) und SCL-Ausgabe
|
||||
(`scl_skeleton`). Weil beide Seiten dieselbe Klasse benutzen, kann das Format
|
||||
nicht unbemerkt auseinanderlaufen.
|
||||
|
||||
**Was passiert darin:** `from_analysis()` macht aus einer `Analysis` ein Dokument
|
||||
(Kanten + Kantenarten → `Connection`-Liste). `to_json()` schreibt mit den
|
||||
(Kanten + Kantenarten → `Connection`-Liste, je TRO die `slots` aus
|
||||
`derive_slots()`, die Staubereiche aus `derive_jam_areas()`). `to_json()` schreibt mit den
|
||||
JSON-Aliasen, `from_json()` liest und prüft. `extra="forbid"` sorgt dafür, dass ein
|
||||
umbenannter oder falscher Schlüssel als Fehler auffällt statt still einen
|
||||
Standardwert zu bekommen; `scl_skeleton.main` meldet bei falschem `schema`
|
||||
@@ -414,3 +432,310 @@ generischen Aufbau (`emit_region()`).
|
||||
**Nicht Produktion:** `doc/TRO_Katalog/scl_templates/*.scl` sind die realen
|
||||
Referenz-Aufrufstellen. Gegen sie prüft `tests/test_scl_templates.py` jedes
|
||||
Template im Round-Trip; in die erzeugte SCL fliessen sie nicht ein.
|
||||
|
||||
## Daten
|
||||
|
||||
Bestandsaufnahme aller Daten, die in den Referenz-Aufrufstellen und FB-Schnittstellen
|
||||
unter `doc/TRO_Katalog/scl_templates/*.scl` vorkommen (Stand 2026-10-10), und woher
|
||||
der Generator sie bekommen muss. Grundlage: die sieben Aufrufstellen
|
||||
(`FB_ILS_MTRO_1Sep`, `_1Sep1Swi`, `_1Sep2Swi`, `_1Sep_SSCC`, `_PinStore_Auto`,
|
||||
`_Vario`, `_Vario_workStation_CallSite`) und die `VAR_INPUT/OUTPUT/IN_OUT`-Abschnitte der
|
||||
vier vollständig vorliegenden FBs (`FB_ILS_MTRO_2Sep1Swi`, `FB_ILS_MTRO_Vario_workStation`,
|
||||
`FB_EmptyCarrBuffer`, `FB_LoadingBoom_INBOUND`). Die Beispielwerte stammen aus diesen
|
||||
Dateien.
|
||||
|
||||
**Quellen** (Spalte "Quelle"):
|
||||
|
||||
| Kürzel | Quelle | Was sie liefert |
|
||||
|---|---|---|
|
||||
| **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<n>`, `cSep<n>.<i>`, `"DB_Interface_HMI".stTRO.TRO<n>` …). 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.
|
||||
|
||||
**`<projekt>-<n>_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 |
|
||||
|
||||
**`<projekt>-<n>_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` |
|
||||
|
||||
**`<projekt>-<n>_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 | | |
|
||||
|
||||
**`<zeichnung>_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 |
|
||||
|---|---|---|---|
|
||||
| Existenz, Anzahl, Reihenfolge der TROs | `REGION TRO 100 …` | L | `tro_flow` → `DerivedTro`; REGION-Reihenfolge `scl_context.flow_order()` |
|
||||
| TRO-Typ / FB-Typ | `FB_ILS_MTRO_1Sep1Swi` | L (→ Katalog) | Typ aus Separator-Host (`doc/500573_Mubea/TRO_Identifikation_500573.md`), FB aus `tro_catalog` |
|
||||
| TRO-Nummer, Instanzname | `#TRO107` | L + E | Anzahl aus L; Nummernkreis je Steuerung (100er = UH01, 200er = UH02 …) ist Projektvorgabe |
|
||||
| REGION-Titel | `TRO 267 (1Sep2Switch)+Scanner(BX2100)` | L + E | Typ aus L, Scanner-BMK aus E |
|
||||
| `nInMainTroNo` | `"cMainTro100"` | K | Wert der Konstante in der PLC-Konstantentabelle |
|
||||
| `nOutStateLast` | `"DB_GLOB_TroState".arTroState["cMainTro100"]` | K | |
|
||||
| `stInOutHMI` | `"DB_Interface_HMI".stTRO.TRO100` | K | PinStore/Puffer: eigener UDT `UDT_HMI_TRO_PinStore` |
|
||||
| `xInRelease` | `"DB_TRO_TEST".TRO100`, `TRUE`, WCS-Verbindung aktiv | P | Freigabe-/Testlogik, Inbetriebnahme |
|
||||
| `xInAllRdyToStart`, `xInCancel`, `xInReset` | `TRUE`, `"cTodoFalse"` | P | meist Konstante |
|
||||
| `stInSettings.xIsBorner` (`xIsBorner1/2`) | `TRUE` | L | erster TRO nach Einfahrt in die Anlage (Beladestation / Systemgrenze `SYSn`) |
|
||||
| `stInSettings.nBornerDest(1/2)` | – | P | Standardziel für neu angelegte Carrier (WCS) |
|
||||
| `stInSettings.bSepType` (`bSep1Type/2Type`) | `.%X2 := TRUE` | E + P | X0 erstes Bein halten, X1 Beladekontrolle, X2 Beladeerfassung — hängt an verbauter Sensorik und Prozess |
|
||||
| `stInSettings.nTroStopper1/2`, `nTroSwitchExit2/3` | – | L + K | Nummern der Nachbar-TROs |
|
||||
| `stInSettings.sJamSrc` / `sJamDest` | – | L + K | Namen der benachbarten Staubereiche |
|
||||
| `stInSettings.xCar2NecRight/Left` | – | L | zweiter Kreisel nötig für Richtung rechts/links (Topologie an einer Kreisel-Weiche) |
|
||||
| `tPartSenHigh`, `tInSenHigh`, `tDummyTimeNormal`, `tDummyTimeBorner` | FB-Defaults 500 ms / 3 s / 0 ms | P | Typ-Defaults |
|
||||
|
||||
### Separator (`stInSeparator<n>`, `xOutStopper<n>`)
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Anzahl Separatoren je TRO | `stInSeparator1`, `stInSeparator2` | L | `ILS 2.0 Separator` + `Zuordnung`, Typ-Katalog `items` |
|
||||
| `Settings.nSeparatorNo` | `"cSep107.1"` | K | Layout-Separator-ID (`TeileId`) ist **nicht** diese Nummer |
|
||||
| Sensor im Stopper `stSenInSep` | `"DB_Inputs".Sensors["cInBG3242"]` | E | |
|
||||
| Sensor nach Stopper `stSenSepLeft`, Beladesensor `stSenPart`, Scan-Start `stSenStartScan` | `["cInBG4465"]` | E | nur wenn verbaut |
|
||||
| Stopperventil `xOutStopper<n>` / `xOutStopper` | `=> "MB3242"` | E | BG- und MB-Nummer sind in der E-Planung meist gleich (BG3242/MB3242) |
|
||||
| `Settings.xPluggedJam` | `TRUE` | E | Stausensor verbaut? |
|
||||
| `Settings.xPluggedPart` | `FALSE` | E | Beladesensor verbaut? |
|
||||
| `Settings.xPluggedConfirm`, `xPluggedNullBT` | `FALSE` | E | |
|
||||
| `Settings.xPluggedScanner` | `TRUE` | L | Scanner am Separator (`DerivedTro.scanners`) |
|
||||
| `Settings.tDelayToNextItem` | `"TimeForSepWaiting_Short"` / `_Medium` | P (+ L) | Wahl Short/Medium hängt am Host (Kreisel/Strecke/Gefälle) |
|
||||
| `Settings.tTrailingTime`, `tHandlingTime` | `t#600ms`, `t#200ms`, `"cTimeSepTrailing"` | P | Typ-Default, IBN |
|
||||
| `Settings.tJam` | `"TimeForSepJam"` | P | Projektkonstante |
|
||||
| `Settings.tSenFree`, `tSenWait` | `T#1500ms`, `T#4000ms` | P | |
|
||||
|
||||
### Staubereiche (Jam)
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Anzahl Ein-/Ausgänge und Zuordnung Exit-Nr ↔ Nachbar | `arInOutJamEntr1`, `arInOutJamExit2..4` | L | ein Eingang je eigenem Staubereich (`TroDocument.jamAreas`, Kennung `J<Separator>`; mehrere Vorgänger fahren in denselben ein), je Nachfolger/Weichenabgang ein Ausgang (`SclJam`) |
|
||||
| Gleicher Staubereich auf beiden Seiten einer Kante | Exit von A = Entr von B | L | Identität aus der Topologie |
|
||||
| Staubereichs-DB und -Index | `"DB_JamArea0102".stJam0102_1.arCarrier` / `.stData` | K (+ E) | Nummerierung der Staubereiche ist Projektvorgabe |
|
||||
| Stausensor je Ausgang | `stInSenJam2 := "DB_Inputs".Sensors["cInBG3243"]` | E | |
|
||||
| Übergabe-Staubereich an Steuerungsgrenze | `#arCarrierHandoverJam5001`, `#stJamDataHandoverJam5001` | L + E | Steuerungsaufteilung aus der E-Planung |
|
||||
| `xInJamAtExit2/3` | – | P | NIU |
|
||||
|
||||
### Weiche (`stInSwitch<n>`, `FC_Direction`)
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Anzahl Weichen je TRO | `stInSwitch1`, `stInSwitch2` | L | `ILS Weiche`, Ausschleuselement, Typ-Katalog |
|
||||
| `Settings.nSwitchNo` | `"cSwi107.1"` | K | |
|
||||
| `Settings.nTo1Destinations` | `3` | L | Erreichbarkeit im TRO-Graphen (`reachable_via()`); bei mehreren Weichen Planungsentscheidung |
|
||||
| Zielliste je Abgang | `cDest…` | L + P | welche Ziele: L; Zielnummern: Projekt/WCS |
|
||||
| `Settings.xPluggedExSen3/4`, `stSenExit3/4` | `FALSE` | E | Abgangssensoren verbaut? |
|
||||
| `Settings.xNewSwitch` | `TRUE` | E | Weichenbauart (ggf. über `ARTINR` im CSV prüfbar) |
|
||||
| Weichenventile `xOutSw<n>ExTo3/4`, `xOutSw1EntrTo1/2` | `=> "MB3304"` | E | |
|
||||
| `FC_Direction`-Aufruf | `nInSwitchNo := "cSwi107.1"`, `InOutCarrier := …stJam0102_1.arCarrier[1]` | K + L | Carrier aus dem Eingangs-Staubereich |
|
||||
| Vorfahrt `stInSettings.xPrioDir<n>`, `stInPriorityManagerDir<n>` | `"DB_Prozessdaten".stPriorityManager.udt_TRO107.TroIn` | L + K | Vorfahrt nötig, wo zwei Ströme zusammenlaufen (Kreuzung/Zusammenführung) |
|
||||
| `stInPriorityManager.xReleaseOk` | `TRUE` ("braucht keine Vorfahrtsregelung") | L | TRUE, wenn keine Zusammenführung |
|
||||
|
||||
### Scanner / Barcode / SSCC
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Scanner vorhanden, Anzahl | `stInBarcodeReader`, `stInBarcodeReader1/2` | L | `ILS 2.0 Scanner`, `Anzahl_Scanner` |
|
||||
| Scanner-BMK und Index | `#arCognexInterface["cScannerBX2100"]` | E | |
|
||||
| Cognex-Variablen | `"bx2100-TriggerReady"`, `-TriggerAck`, `-Results Available`, `-General Fault`, `-TriggerEnable`, `-Trigger`, `-ResultsAck` | E | aus dem BMK nach Regel bildbar, wenn die TIA-Variablentabelle dem Muster folgt |
|
||||
| Hardware-Kennung Ergebnisse | `"=A01+UC021-BX2100~Ergebnisse_–_64_Bytes_1"` | E | |
|
||||
| Kein Scanner | `#stCognexInterfaceDummy` | L | |
|
||||
| `Settings.xActivateCheckASCI`, `tTimeout` | `TRUE`, `T#5s` | P | |
|
||||
| `Settings.nStation`, `nScannerPurpose` | `111`, `0` | P | WCS |
|
||||
| Zweck SSCC-Scanner, `xInPluggedSSCC` | `#stCognexIntfTro105` | E + P | Layout kennt den zweiten Scanner, nicht seinen Zweck |
|
||||
| `stSenEndMeasurement` | `["cInBG3281"]` | E | |
|
||||
| `FC_CARR_GLOB_CORRECTION` | `nInStation := 0`, Carrier aus Eingangs-Staubereich | P + L | |
|
||||
| WCS-Telegramm, HMI-SSCC-Ausgabe | `FC_Send_GOHDReqM`, `"DB_Interface_HMI".stSSCC.SSCC1107` | P | WCS-Schnittstelle |
|
||||
|
||||
### Vario (`stInVario`) und Arbeitsplatz
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Vario vorhanden | `FB_ILS_MTRO_Vario` | L | angetriebene Strecke / Variofoerderer |
|
||||
| Sensoren `stSenCarrInPos`, `stSenFinger`, `stSenLastPos`, `stSenJam`, `stSenNextSep`, `stSenSepVario` | `["cInBG3026"]` … | E | |
|
||||
| Motor `xOutVarioMotor`, Motorschutz `xInMotorProtection` | `"MA0145"`, `"FC0145"` | E | |
|
||||
| Finger-Staubereich `arInOutJamFinger` | `"DB_JamArea4103".stJam4103_1` | L + K | |
|
||||
| `Settings.tConvEmpty` | `T#45000ms` | L + P | aus Förderlänge (`L_VF_m`) und Geschwindigkeit ableitbar |
|
||||
| `Settings.nCountCarrier`, `tWaitForJog`, `tWaitForStop`, `tCarrierInPosDelay`, `tCarrierInPosEdgeDelay`, `tRasterHigh/Low`, `xJamSenDelayActive`, `tJamSenDelay`, `xContinousEmptying`, `SettingsVarioFingerMonitoring` | `1`, `T#300ms` … | P | |
|
||||
| Arbeitsplatz `stInStationSensor`, `xInReleaseStation`, `fbConvVario.xBeladenError` | `["cInBG3314"]`, `#"rTrig_Workstation 1".CLK` | E | Taster/Sensor am Arbeitsplatz |
|
||||
|
||||
### Antrieb, Sicherheit, Betriebsart
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Fördertechnik, die den TRO trägt | `xInCarouselRun1 := #fbCarousel0102.xOutConveyorFullSpeed`; Gefälle: `TRUE` | L | Host-Kreisel aus `DerivedTro.hosts`; Instanzname nach K |
|
||||
| `xInCarouselRun2` | zweiter Kreisel | L | TRO an der Berührung zweier Kreisel |
|
||||
| `xInConveyorRunIn/Out` (PinStore) | `#fbSortConv1101`, `#fbExitConv1103` | L + K | |
|
||||
| `xInSftyOk` | `"DB_InterfaceSafety".stFromSafety.EStopMainOF1.Q` | E | Not-Halt-Kreis |
|
||||
| `stInOutMachineState` | `#stInOutControlUnitCabinetOF1` | E | Schaltschrank (OF1/OF2) |
|
||||
| `xInAutomatic`, `xInErrorQuit`, `xInQuitLocal` | `#t_Automatik_OF1 AND "SF0120"`, `"SF0002"`, `"SF0121" OR "SF0117"` | E | Bedienelemente |
|
||||
| `nInTestTarget` | `"IBN".nTestTarget111` | P | |
|
||||
|
||||
### Pin-Lager (`FB_ILS_MTRO_PinStore_Auto`) und Leerträgerpuffer (`FB_EmptyCarrBuffer`)
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Anzahl Lagerlinien | `nNoOfLines := 19`, `arInSep[1..5]` | L | Separatoren auf Kreisel mit Pinband / `Separatorlist` |
|
||||
| Positionen je Linie, Staulänge | `nNoOfPositions := 70`, `nJamLength := 4` / `"cStorage111ExitJam2"` | L + P | aus Linienlänge und Teilung |
|
||||
| Liniensensoren `arInSep[n].stSenTrolley`, `arInJamSensor[n]`, `stInSenJamExit` | `["cInBG3270"]` | E | |
|
||||
| Linienventile `arOutSeparatorStore[n]` | `"MB3270"` | E | |
|
||||
| Pin-Separator `stInSeparatorPin`, `xOutSeparatorPin` | `["cInBG3000"]`, `"MB3000"` | E | |
|
||||
| Referenzsensor "Zappler" `stInSensorReference` | `["cInBG3001"]` | E | |
|
||||
| Encoder `stInEncoderParameter` | `#fbEncoderGF2200.nOutPosActDif` | E | |
|
||||
| `nDestGeneral`, `nConvStations`, `nStationsMax`, `nStorageThreshold` | `"cDest11100"`, `"cHooksSorterMaxPin111"` | P | WCS/Projekt |
|
||||
| `nInBufferNr`, `xInBufferReq/Release/ReleaseNext`, `xInPause` | `101`/`102` | P | Pufferlogik |
|
||||
| Lager-/Stations-DBs | `"DB_Storage1.1.1".arLine`, `"DB_ConveyorStations"`, `"DB_HandshakeStorage"` | K + P | |
|
||||
| Linien-Zeiten, Simulation | `"cTimeSepHandlingStorageLine"`, `stSimu.*` | P | |
|
||||
|
||||
### Ladeschleife (`FB_LoadingBoom_INBOUND`)
|
||||
|
||||
| Daten | SCL-Stelle (Beispiel) | Quelle | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Ladeschleife vorhanden, Lage | – | L | Beladestation (`ILS 2.0 BTMT Beladung`), prüfen |
|
||||
| Bedienelemente `stInControl.*` | Taster, Knebel-/Schlüsselschalter | E | |
|
||||
| Ausleger/Stützfuß `stInBoom.*`, `stInFoot.*` | Endlagen, Motorschutz, Bumper | E | |
|
||||
| Analogwerte `stInTilt.wTilt`, `stInDistance.wDistance` | Neigung, Abstand | E | |
|
||||
| Sensoren `stInSen2mThreshold`, `stInSenJamEntr/Exit1/Exit2`, `stInSenStopper1/2`, `stInSenGrid` | | E | |
|
||||
| Ausgänge `stOutStopper.*`, `stOutBoom.*`, `stOutFoot.*`, `xOutLedMovement`, `xOutLight`, `xOutLedBumper`, `xOutCarousel` | | E | |
|
||||
| Schwellwerte `nDiff`, `nZeroOk`, `nStartSlow/Fast`, `nDistanceZero`, `tDiff`, `tZero`, `nTiltComp` | | P | Inbetriebnahme |
|
||||
| `stInSettings.*` Zeiten | `tBoomInput := T#3500ms` … | P | |
|
||||
| Exit-Staubereich `arInOutCarrierExit`, `stInOutCarrierExit` | | L + K | |
|
||||
|
||||
### Zusammenfassung
|
||||
|
||||
- **Aus dem Hardwarelayout (L)** kommt die **Struktur**: welche TROs es gibt, ihr Typ
|
||||
und damit FB und Anzahl der Parameterblöcke (Separatoren, Weichen, Scanner, Vario,
|
||||
Lagerlinien), Vorgänger/Nachfolger und damit Ein-/Ausgangs-Staubereiche,
|
||||
REGION-Reihenfolge, Ziele je Weichenabgang (`nTo1Destinations`), Vorfahrt ja/nein,
|
||||
Systemgrenzen (`xIsBorner`), die tragende Fördertechnik (`xInCarouselRun`, Gefälle →
|
||||
`TRUE`), ob ein Scanner am Separator sitzt (`xPluggedScanner`) und Längen als
|
||||
Grundlage für Zeiten/Staulängen. Das meiste davon ist heute in `DerivedTro` →
|
||||
`SclTro` abgebildet; Vorfahrt, `xIsBorner` und Längen noch nicht.
|
||||
- **Aus der Elektroplanung (E)** kommen **alle Namen und Adressen**: jeder Sensor
|
||||
(`BG`), jedes Ventil (`MB`), Motor (`MA`), Motorschutz (`FC`), Taster (`SF`), Scanner
|
||||
(`BX`) samt Cognex-Variablen und Hardware-Kennung, die `xPlugged*`-Schalter (was ist
|
||||
tatsächlich verbaut), Weichenbauart, Not-Halt-Kreis, Schaltschrank und
|
||||
Steuerungsgrenzen. Im Render-Kontext sind das die `SclName` mit `todo=True`
|
||||
(`TODO(E-Planung)`). Offen ist die Brücke: die EA-Liste kennt keine Topologie; es
|
||||
braucht eine Zuordnung Layout-Bauteil (Separator-`TeileId`) ↔ BMK (`BG3242`/`MB3242`).
|
||||
Diese Brücke baut `lib/e_planning.py` über die Symbolpositionen in
|
||||
`*_positionsdraw.json` des Kabellängen-Tools (`doc/E-Planung_Bruecke.md`);
|
||||
heute kommen damit Separator-Sensor und Stopperventil in die SCL
|
||||
(`scl_skeleton --eplan`).
|
||||
- **Namenskonvention (K)**: `cMainTro`, `cSep`, `cSwi`, Staubereichs-DBs, HMI- und
|
||||
State-Pfade — sobald Nummernkreise feststehen, ohne weitere Quelle erzeugbar.
|
||||
- **Parameter (P)**: Zeiten, Projektkonstanten, WCS-Ziele/Stationen, Test-/IBN-Signale —
|
||||
weder L noch E; gehören als Typ-Defaults in den Katalog bzw. in eine
|
||||
Projektkonfiguration.
|
||||
|
||||
@@ -0,0 +1,379 @@
|
||||
# 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`.
|
||||
|
||||
**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), 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.
|
||||
|
||||
**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 `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.
|
||||
**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.
|
||||
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: 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.
|
||||
+152
-14
@@ -1,14 +1,16 @@
|
||||
# Python Scripts — CLI Tooling Overview
|
||||
|
||||
**As of:** 2026-10-09
|
||||
**As of:** 2026-10-10
|
||||
|
||||
`lib/` currently holds ten Python modules (five of them runnable CLI tools,
|
||||
`lib/` currently holds eleven Python modules (six of them runnable CLI tools,
|
||||
five supporting libraries), plus one documentation-generator script that lives
|
||||
under `doc/TRO_Katalog/tro_graphs/`. Together the CLI tools turn a CSV export
|
||||
of the mechanical layout (ILS 2.0) into a material-flow graph, a derived TRO
|
||||
list/diagram, a TRO-JSON (shared model `lib/model.py`), an `FB_Main` SCL
|
||||
skeleton generated from that JSON, and an annotated copy of the BricsCAD
|
||||
drawing for visual checking.
|
||||
drawing for visual checking. `e_planning.py` bridges to the electrical
|
||||
planning: it assigns the sensors/valves of the E-planning drawing to the
|
||||
layout parts, so the skeleton can carry their real names.
|
||||
|
||||
This document is the practical "what does each script do and which switches
|
||||
does it take" reference. For the underlying domain model (TRO types, JSON
|
||||
@@ -34,6 +36,11 @@ tro_flow.py ──► <name>_tro_flow.dot / .svg, _tro_doc.md, _tro_error
|
||||
│ scl_skeleton.py ──► <name>_FB_Main.scl
|
||||
│ (validates the JSON against model.py; one REGION per TRO;
|
||||
│ E-planning values left as TODO(E-Planung) gaps)
|
||||
│ ▲
|
||||
│ │ --eplan <name>_eplan.json (optional)
|
||||
│ e_planning.py ◄── <drawing>_positionsdraw.json (kabellaengen)
|
||||
│ (assigns BG/MB of the E-planning drawing to the layout
|
||||
│ parts by position + numbering rule; see §5c)
|
||||
│
|
||||
└── same derivation ──► tro_annotate.py ──► <name>_annotated.dxf (VIEWER ONLY)
|
||||
(also needs the BricsCAD DXF; uses dxf_registration.py for the CSV↔DXF
|
||||
@@ -66,6 +73,10 @@ Supporting libraries (no CLI of their own, imported by the tools above):
|
||||
- **`lib/dxf_registration.py`** — derives, verifies and persists the rigid
|
||||
(rotation + offset) transform between the CSV export's coordinate system and
|
||||
the DXF drawing's.
|
||||
- **`lib/tro_ids.py`** — the per-plant ID file `%SKEL_CFG%\<name>_tro_ids.ini`:
|
||||
reads it, finds each TRO again by the position of its separators, assigns
|
||||
new IDs, writes/extends the file. Used by `tro_flow.py` (read and write) and
|
||||
`tro_annotate.py` (read only). See §4, "TRO-IDs".
|
||||
- **`lib/tro_overrides.py`** — reads the hand-maintained
|
||||
`%SKEL_CFG%\tro_overrides.ini`; only `material_flow.py --connect` still uses
|
||||
it. See §6a.
|
||||
@@ -91,6 +102,8 @@ Each CLI tool is invoked through its `bin/<name>.bat` (Windows) / `bin/<name>.sh
|
||||
bin\material_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --use-cords --doc --json
|
||||
bin\scl_skeleton.bat --json mubea_tro.json
|
||||
bin\e_planning.bat --file mubea.csv --eplan Mubea_positionsdraw.json
|
||||
bin\scl_skeleton.bat --json mubea_tro.json --eplan mubea_eplan.json
|
||||
bin\tro_annotate.bat --file mubea.csv --dxf 500573_60_1.dxf --flow --fb --legend
|
||||
```
|
||||
|
||||
@@ -102,8 +115,9 @@ Conventions shared by the CLI tools:
|
||||
- `--file` / `--dxf` accept either a bare filename — resolved against
|
||||
`%SKEL_DATA%` — or a full path.
|
||||
- All generated output is written to `%SKEL_RESULTS%`.
|
||||
- `tro_annotate.py` additionally persists the verified CSV↔DXF coordinate
|
||||
offset to `%SKEL_CFG%\dxf_registration.json`.
|
||||
- `tro_annotate.py` and `e_planning.py` additionally persist the verified
|
||||
coordinate offset (CSV↔DXF, CSV↔E-planning drawing) to
|
||||
`%SKEL_CFG%\dxf_registration.json`.
|
||||
- Every run prints a `====` bordered report to stdout (counts, warnings,
|
||||
output file paths); non-fatal findings are printed as `?`/`!` lines and also
|
||||
do not stop the run.
|
||||
@@ -294,17 +308,45 @@ colors all come from `lib/tro_catalog.py` — nothing is hard-coded here.
|
||||
| `--doc` | — | off | Also write a Markdown report (`<name>_tro_doc.md`) with the TRO list, connections, findings and the full type catalog. |
|
||||
| `--connect` | — | off | Also write the TRO topology as `<name>_tro_connect.ini` (nodes, connections, system boundaries, predecessors/successors per TRO). Pure output, never read back. |
|
||||
| `--true-scale` | — | off | Only with `--use-cords`: draw to scale. By default empty stretches longer than 1500 mm between nodes are shortened (order and neighbourhood are kept). |
|
||||
| `--json` | — | off | Also write the TRO-JSON `<name>_tro.json` (schema `sps_skel-tro-v3`, model `TroDocument` in `lib/model.py`): TROs, system boundaries (`SYSn`), connections with their kind, findings. Input for `scl_skeleton.py`. |
|
||||
| `--json` | — | off | Also write the TRO-JSON `<name>_tro.json` (schema `sps_skel-tro-v4`, model `TroDocument` in `lib/model.py`): TROs with their `slots`, system boundaries (`SYSn`), connections with their kind, `jamAreas`, findings. Input for `scl_skeleton.py`. |
|
||||
| `--ids` | `DATEI` | `<name>_tro_ids.ini` | ID file of the plant (name in `%SKEL_CFG%`, or a path). Use it to run another export of the same plant against the same IDs, e.g. `--file mubea_export.csv --ids mubea_tro_ids.ini`. |
|
||||
| `--renumber` | — | off | Number all TROs afresh along the material flow and rewrite the `[tro]` section of the ID file (early project phase). Renamed IDs are lost; other sections of the file are kept. |
|
||||
| `--id-tolerance` | `MM` (float) | `100.0` | Maximum distance between an ID-file entry and a separator of a TRO for the TRO to count as found again. |
|
||||
|
||||
TROs, types and connections always come from the layout alone;
|
||||
`cfg/tro_overrides.ini` is not read. Errors in the derivation are fixed in
|
||||
`lib/tro_flow.py`, not in a correction file.
|
||||
|
||||
**TRO-IDs** (`lib/tro_ids.py`). The IDs belong to the SPS programmers and must
|
||||
survive a new layout export; the layout `TeileId` changes between exports, the
|
||||
position does not. So every run reads `%SKEL_CFG%\<name>_tro_ids.ini`:
|
||||
|
||||
```ini
|
||||
[tro]
|
||||
TRO01 = -400.0, 13920.0 ; 1Sep1Swi | Separator 0003 auf Kreisel2 Bahn L | Sep 0003
|
||||
K0302_1 = 10310.0, -440.1 ; renamed by hand
|
||||
```
|
||||
|
||||
- Each entry is `ID = x, y` (mm, CSV coordinates) of the TRO's anchor
|
||||
separator. An entry finds the TRO with a separator within `--id-tolerance`
|
||||
(closest first, one entry per TRO), and that TRO keeps the ID — renamed IDs
|
||||
included. An ID must be unique and a valid SCL identifier; `SYSn` is
|
||||
reserved for system boundaries.
|
||||
- No file yet: the TROs are numbered along the material flow (depth-first from
|
||||
the loading stations over the material-flow graph, on a carousel or Strecke in
|
||||
`TrackIds` order) and the file is created.
|
||||
- A TRO not found gets the next free `TRO<n>` and is appended to `[tro]`;
|
||||
an entry without a TRO is reported ("weggefallen", with the TRO that now
|
||||
holds its separator, e.g. after two TROs merged into a `2Sep2Swi`) and stays
|
||||
in the file; its ID is not reused.
|
||||
- The console report lists found / new / dropped IDs.
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`): `<name>_tro_flow.dot` (always, with `pos`
|
||||
attributes when `--use-cords` was used), `<name>_tro_flow.svg` (with
|
||||
`--tosvg`), `<name>_tro_doc.md` (with `--doc`), `<name>_tro.json` (with
|
||||
`--json`), `<name>_tro_errors.md` (only if TROs are unconnected or of an
|
||||
unknown type).
|
||||
unknown type). In `%SKEL_CFG%`: `<name>_tro_ids.ini` (created, extended or,
|
||||
with `--renumber`, rewritten — see above).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `2` SVG rendering failed
|
||||
(Graphviz) · `3` TRO validation errors found (error file written).
|
||||
@@ -355,6 +397,7 @@ overridden.
|
||||
| `--legend` | — | off | Draw a legend of the color groups. |
|
||||
| `--marker-size` | `MM` (float) | `300.0` | Marker radius in mm. |
|
||||
| `--text-height` | `MM` (float) | `220.0` | Text height in mm. |
|
||||
| `--ids` | `DATEI` | `<csv-stem>_tro_ids.ini` | ID file as for `tro_flow.py`, **read only**: the markers carry the same IDs as the TRO-JSON. Without the file the TROs are numbered along the material flow, as `tro_flow.py` would. |
|
||||
| `--offset` | `DX,DY` | — | Set the CSV↔DXF offset by hand instead of deriving/loading it. For a drawing built with dxfmakros (CSV exported from the same drawing) this is `0,0`. |
|
||||
| `--re-register` | — | off | Re-derive the coordinate offset even if a verified one is already cached in `%SKEL_CFG%`. |
|
||||
| `--check` | — | off | Dry run: only analyze and report, write no output file. |
|
||||
@@ -446,7 +489,8 @@ is missed.
|
||||
|---|---|
|
||||
| REGION order (material flow), instance list, FB type per TRO | sensor/actuator addresses (`cInBG`, `MB`, `MA`) |
|
||||
| number of separator / switch / scanner parameter blocks | separator and switch numbers, `cMainTro` |
|
||||
| `nTo1Destinations` when the TRO has exactly one switch | jam areas (`DB_JamArea…`) |
|
||||
| `nTo1Destinations` when the TRO has exactly one switch | jam-area DB names (`DB_JamArea…`) |
|
||||
| number of jam entries (one per own jam area, not per predecessor) and which jam area each exit leads to (`J<Separator>` in the comment) | |
|
||||
| destination list per switch exit (graph reachability) | times marked "pruefen" |
|
||||
| cross-reference to the layout parts (separator numbers, coordinate) | |
|
||||
|
||||
@@ -460,7 +504,7 @@ than a guess.
|
||||
|
||||
Switches: `--json NAME` (default `export_tro.json`, looked up in
|
||||
`%SKEL_RESULTS%`; written by `tro_flow.py --json`), `--out NAME` (default
|
||||
`<source>_FB_Main.scl`), `--start TRO`. The last one matters while the plant has
|
||||
`<source>_FB_Main.scl`), `--eplan NAME` (see below), `--start TRO`. The last one matters while the plant has
|
||||
no loading/unloading station: the flow is then a closed loop with no entry, so
|
||||
the order has to be broken somewhere arbitrary. The chosen start and the reason
|
||||
are recorded in the file header.
|
||||
@@ -494,6 +538,16 @@ by a PLC engineer (`doc/SCL_Templates.md` §6). `2Sep1Swi`, `EmptyCarrBuffer`,
|
||||
`LoadingBoom` and `2Sep2Swi` have no call site yet and stay generic. `--strict` stops (exit `1`, no SCL) if any FB type has no
|
||||
template. Without `--templates` the output is unchanged.
|
||||
|
||||
**Names from the E-planning (opt-in, `--eplan NAME`).** Reads the assignment
|
||||
`<csv>_eplan.json` written by `e_planning.py` (§5c; bare name looked up in
|
||||
`%SKEL_RESULTS%`). For every separator it assigns, the separator sensor
|
||||
(`stSenInSep := "DB_Inputs".Sensors["cInBG0642"]`) and the stopper valve
|
||||
(`xOutStopper<n> => "MB0643"`) are filled in and lose their `TODO(E-Planung)`
|
||||
marker (`SclName.todo = False`); everything else stays open. The header names
|
||||
the E-planning file. An assignment made for a different CSV (`csv_file` ≠ the
|
||||
TRO-JSON's `source`) stops the run with exit `1` — separator numbers are only
|
||||
unique within one export. Without `--eplan` the output is unchanged.
|
||||
|
||||
Tests: `tests/test_scl_context.py` (the derivations one by one),
|
||||
`tests/test_scl_templates.py` (each template rendered with the real values of
|
||||
its reference call site must equal that call site, comments and whitespace
|
||||
@@ -502,6 +556,86 @@ HundM05 byte for byte against `tests/fixtures/scl/*_FB_Main.scl` and
|
||||
`*_FB_Main_templates.scl`, timestamp masked; an intended change is written
|
||||
back with `SKEL_UPDATE_GOLDEN=1`).
|
||||
|
||||
## 5c. `e_planning.py` — assign the E-planning to the layout parts
|
||||
|
||||
The bridge between layout and electrical planning (background and findings:
|
||||
[`E-Planung_Bruecke.md`](E-Planung_Bruecke.md)). The layout knows which
|
||||
separators, switches and outfeed elements exist and where; the E-planning knows
|
||||
what their sensors and valves are called. The I/O list alone has no topology —
|
||||
but the E-planning is drawn as a layer over the hardware layout, every sensor or
|
||||
actuator symbol sits next to its part, and the cable-length tool
|
||||
(`kabellaengen/lib/getpositions.py`) writes those symbols with position and
|
||||
attributes to `<drawing>_positionsdraw.json`.
|
||||
|
||||
```
|
||||
<name>.csv (layout) + <drawing>_positionsdraw.json (E-planning)
|
||||
│
|
||||
▼
|
||||
e_planning.py ──► <name>_eplan.json (EplanDocument, schema sps_skel-eplan-v1)
|
||||
──► <name>_eplan.md (report: assignments, gaps, drives)
|
||||
│
|
||||
▼
|
||||
scl_skeleton.py --eplan <name>_eplan.json
|
||||
```
|
||||
|
||||
Steps:
|
||||
|
||||
1. **Read** `sensors` (field devices) and `schaltschrank_elemente` (cabinet) of
|
||||
the positionsdraw file into `EDevice` (BMK, `VERW`, `BEZEICHNUNG`,
|
||||
`KENNZEICHNUNG` → controller `UH01` / I/O station `KF107`, position). A BMK
|
||||
listed twice keeps the entry that has a `VERW`.
|
||||
2. **Registration** E-planning drawing → CSV with `dxf_registration.py`: the
|
||||
E symbols matching `[Registrierung] anker` (default `IN SEP`, the sensor that
|
||||
sits on the separator) against the CSV separators. Stored under the key
|
||||
`<csv>|<positionsdraw>` in `%SKEL_CFG%\dxf_registration.json` and re-verified
|
||||
on every run; `--re-register` forces a new derivation.
|
||||
3. **Rules** from `%SKEL_CFG%\e_planning.ini`, one section `<kind>.<role>` per
|
||||
rule, applied in file order; each E device is given out at most once, each
|
||||
role of a layout part filled at most once:
|
||||
|
||||
| key | meaning |
|
||||
|---|---|
|
||||
| `layout` | layout kind pattern (default: the part before the dot): `Separator`, `Ausschleus`, `Einschleus`, `Weiche`, `Scanner`, `Beladung`, `Entladung` |
|
||||
| `verw`, `praefix` | pattern(s) for the E attribute `VERW`, BMK prefix (`BG`, `MB`) |
|
||||
| `max_mm` | spatial: maximum distance after registration |
|
||||
| `soll_mm`, `toleranz_mm` | spatial: the symbol always sits this far from the part; candidates are ranked by their deviation from it, not by the smallest distance |
|
||||
| `nummer_von`, `nummer_versatz` | numbering rule: BMK number = number of the given role + offset (Mubea: valve = sensor + 1) — tried first, distance only for the rest |
|
||||
|
||||
Shipped rules (tuned on Mubea): `Separator.sensor`, `Separator.stopper`,
|
||||
`Ausschleus.stau`, `Ausschleus.ventil`, `Weiche.ventil`. `VERW` texts and the
|
||||
numbering rule are project-specific — in the reference SCL (UH01..UH05)
|
||||
sensor and stopper share the number (BG3242/MB3242), i.e. offset `0`.
|
||||
4. **Drives**: motor `MAnnnn` ↔ motor protection `FCnnnn` (same number), for the
|
||||
report.
|
||||
|
||||
Uncertain cases stay open on purpose: a gap is better than a plausible wrong
|
||||
name. The report lists, per role, the layout parts without a match, the field
|
||||
devices without a match, and distance and runner-up distance of every match
|
||||
(close values = check by hand).
|
||||
|
||||
Switches: `--file NAME` (CSV, default `export.csv`), `--eplan NAME`
|
||||
(positionsdraw JSON, required; bare name resolved against `%SKEL_DATA%`, or a
|
||||
full path), `--rules FILE` (default `%SKEL_CFG%\e_planning.ini`),
|
||||
`--re-register`. Exit `0` also when not everything was assigned; `1` on input
|
||||
errors or when the registration cannot be proven.
|
||||
|
||||
**Today only separator sensor and stopper reach the SCL.** Jam sensors and
|
||||
outfeed/switch valves are assigned in the JSON/report, but the TRO-JSON does not
|
||||
yet say which outfeed element or switch belongs to which TRO exit, so
|
||||
`scl_skeleton` cannot place them. The same holds for the storage lines of a
|
||||
`PinStore` TRO (`arInSep[n]`): their sensors are assigned but the generator does
|
||||
not emit per-line parameters yet.
|
||||
|
||||
Result on Mubea (`mubea.csv` + `Mubea_positionsdraw.json`): registration
|
||||
dx +50613.6 / dy +8555.8 mm; separator sensor 21/38, stopper 22/38 (all 20
|
||||
storage lines exact, 0–1 mm), jam sensor 20/23, outfeed valve 20/23, switch
|
||||
valve 1/1. The open separators are on the carousels K0102/K0104/K0105, where
|
||||
the E-planning drawing and the CSV apparently differ.
|
||||
|
||||
Tests: `tests/test_e_planning.py` (reading, rules, numbering vs. distance on a
|
||||
storage-line grid, target distance, uniqueness, registration, drives, the path
|
||||
into `scl_context` and `scl_skeleton --eplan`).
|
||||
|
||||
## 6. `tro_catalog.py` — TRO type catalog (library, no CLI)
|
||||
|
||||
The single source of truth for everything needed to generate or draw a TRO
|
||||
@@ -535,8 +669,8 @@ TRO in a plant, and the whole TRO-JSON, look like. It imports only the catalog.
|
||||
```
|
||||
tro_catalog.py type level TroDefinition (items, FB block, color, symbol)
|
||||
▲ get_tro()
|
||||
model.py instance level TroBase ─► DerivedTro, Connection, TroCandidate,
|
||||
Analysis, TroDocument
|
||||
model.py instance level TroBase ─► DerivedTro, Slot, JamArea, Connection,
|
||||
TroCandidate, Analysis, TroDocument
|
||||
▲
|
||||
tro_flow.py (writes) · scl_skeleton.py (reads) · tro_annotate.py (draws)
|
||||
```
|
||||
@@ -544,11 +678,13 @@ tro_flow.py (writes) · scl_skeleton.py (reads) · tro_annotate.py (draws)
|
||||
| Class | What it is |
|
||||
|---|---|
|
||||
| `TroBase` | Core of every TRO: `id`, `type`, `confidence`, `separators`, `predecessors`, `successors`, `position` (`{x,y,z}` in JSON). `definition()`, `fb_block` (JSON `fbType`) and `items` are **read from the catalog** on every access, never stored — so they follow a type change and cannot go stale. |
|
||||
| `DerivedTro` | `TroBase` + what `tro_flow.py` knows from the derivation: `label`, `hosts`, `scanners`, `reason`, `colocated`, `positionFrom`, `positionPoints`. Also used for the system boundaries `SYSn`. |
|
||||
| `DerivedTro` | `TroBase` + what `tro_flow.py` knows from the derivation: `label`, `hosts`, `scanners`, `reason`, `colocated`, `positionFrom`, `positionPoints`, `slots`. Also used for the system boundaries `SYSn` (no slots). |
|
||||
| `Slot` | A place on a TRO where hardware belongs: `slot` (`separator1`, `switch1`, `scanner1`, `drive` — the stable key together with the TRO-ID), `layoutId` (TeileId in the current export, for tracing only; empty for switches, whose element `tro_flow` does not keep yet), `roles` the hardware planning must fill (`sensor`, `stopper`, `jamSensor?` …; `?` = optional). Built by `derive_slots()` from the catalog type. |
|
||||
| `JamArea` | A jam area = the queue in front of a separator, the entry of exactly one TRO: `id` (`J<Separator>`, e.g. `J0042`), `tro`, `entry` (1, 2 for 2Sep types), `separator`, `host`, `predecessors` (all TROs/stations feeding it — merges have several), `note`, `position`. Built by `derive_jam_areas()`; the SCL name `"DB_JamArea<NNNN>".stJam<NNNN>_<k>` needs the conveyor number from the hardware planning and is not stored. |
|
||||
| `Connection` | Directed edge `from` → `to` with its `kind` (transfer / umlauf / weiche / unbestimmt / normal / bahn). |
|
||||
| `TroCandidate` | A spot reported in a review where a TRO is **expected** but not derived (formerly `OpenPoint`): `name`, `type` (the expected catalog type), `position`, `belongsTo` (the TRO that holds the part today), `note`. Not a TRO — no separators, no connections, no SCL. Built by `tro_overrides.py` from `[<csv>.openpoint.<Name>]`; empty in the TRO-JSON for now. |
|
||||
| `Analysis` | Working result of `tro_flow.analyse_tros` (moved here from `tro_flow.py`). |
|
||||
| `TroDocument` | The TRO-JSON: `schema` (`sps_skel-tro-v3`), `source`, `created`, `note`, `tros`, `boundaries`, `connections`, `candidates`, `findings`. `from_analysis()`, `to_json()`, `from_json()`. |
|
||||
| `TroDocument` | The TRO-JSON: `schema` (`sps_skel-tro-v4`), `source`, `created`, `note`, `tros`, `boundaries`, `connections`, `candidates`, `jamAreas`, `findings`. `from_analysis()` (derives slots and jam areas), `to_json()`, `from_json()`, `jam_areas_or_derived()` (a v3 file without `jamAreas` still renders). |
|
||||
|
||||
`TroBase` and `TroCandidate` share the `position` handling (JSON `{x,y,z}`,
|
||||
`x`/`y`/`z`, `describe_position()`) through the private mixin `_Positioned`.
|
||||
@@ -560,7 +696,9 @@ All models validate on creation and assignment and reject unknown keys
|
||||
(`extra="forbid"`). JSON keys keep the camelCase names of the TRO-JSON (`id`,
|
||||
`type`, `fbType`, `belongsTo` …); Python code uses the field names
|
||||
(`tro_id`, `type_name`, `fb_block`, `belongs_to`) — both are accepted on input.
|
||||
Schema v3 differs from v2 only in `candidates` replacing `openPoints`.
|
||||
Schema v3 differs from v2 only in `candidates` replacing `openPoints`; v4 adds
|
||||
`slots` per TRO and `jamAreas`. A v3 file still reads (both default to empty;
|
||||
`scl_skeleton` then derives the jam areas while rendering).
|
||||
|
||||
Tests: `tests/test_model.py` (round trip, catalog-backed fields, rejection of
|
||||
wrong keys/items, SCL rendering from a document) — run with
|
||||
|
||||
@@ -14,7 +14,7 @@ It is written so that it fits the existing main path unchanged:
|
||||
```
|
||||
export.csv ─► tro_flow --json ─► <name>_tro.json ─► scl_skeleton ─► <name>_FB_Main.scl
|
||||
(dxfmakros (derive) (TroDocument, (render) (skeleton with
|
||||
EXPORTCSV) sps_skel-tro-v3) TODO(E-Planung))
|
||||
EXPORTCSV) sps_skel-tro-v4) TODO(E-Planung))
|
||||
```
|
||||
|
||||
Nothing upstream of `scl_skeleton` changes. The TRO-JSON stays the only input, and the
|
||||
@@ -274,11 +274,11 @@ reference line":
|
||||
| Template (reference) | Decisions to confirm |
|
||||
|---|---|
|
||||
| `1Sep` (TRO100) | times 600/200 ms and `tSenFree`/`tSenWait` 1500/4000 ms as in the reference (`pruefen`); `xInCarouselRun` always written as TODO; `xInRelease := "DB_TRO_TEST".<id>` as in the reference |
|
||||
| `Vario` (TRO115) | times 800/300 ms, `xPluggedJam FALSE`, `tSenFree`/`tSenWait` 2000/5000 ms, `tRasterHigh/Low` 5 s (`pruefen`); `stInSettings.xIsBorner := TRUE` marked TODO (meaning unclear); `JamEntr` = first predecessor, `JamFinger` = first successor; `xInErrorQuit`/`xInAutomatic` open |
|
||||
| `Vario` (TRO115) | times 800/300 ms, `xPluggedJam FALSE`, `tSenFree`/`tSenWait` 2000/5000 ms, `tRasterHigh/Low` 5 s (`pruefen`); `stInSettings.xIsBorner := TRUE` marked TODO (meaning unclear); `JamEntr` = the TRO's own entry jam area (TRO-JSON v4: several predecessors merge into it), `JamFinger` = the entry jam area of the first successor; `xInErrorQuit`/`xInAutomatic` open |
|
||||
| `Vario_workStation` (TRO421) | `xPluggedScanner FALSE` although the catalog lists a scanner (it sits at the work station, not the separator — `pruefen`); work-station sensor, release and `xBeladenError` sensor open |
|
||||
| `1Sep2Swi` (TRO267) | separator without times, `xPluggedPart TRUE` + `stSenPart` as in the reference; **switch 2 has no `nSwitchNo` in the reference** — written as a commented-out proposal; `nTo1Destinations` per switch open (split of the exits); `bSepType.%X2 := TRUE` marked `pruefen`; one `xInCarouselRun<n>` per switch; **no `FC_Direction`** at this place in the reference — only the destination list as a comment; no `nOutStateLast` (not in the reference) |
|
||||
| `1Sep_SSCC` (TRO105) | second (SSCC) camera with its own interface structure, end-measurement sensor and HMI key open; `xInRelease` written as `"DB_TRO_TEST".<id>` with a TODO (the reference releases via the WCS connection); `FC_CARR_GLOB_CORRECTION` with `nInStation` open; the WCS telegram region of the reference is only noted as TODO |
|
||||
| `PinStore_Auto` (TRO208) | **number of lines from the layout** (one per storage lane, `nNoOfLines`), not the 19 of the reference; all plant constants (encoder, destinations, stations, thresholds, storage DB, removal handshake) open; pin separator times 0/50 ms (`pruefen`); simulation settings `stSimu` of the reference not written; the FB has one `JamEntr`/`JamExit` — a store with more feeds/exits (mubea: 2/2) gets a TODO in the REGION header |
|
||||
| `PinStore_Auto` (TRO208) | **number of lines from the layout** (one per storage lane, `nNoOfLines`), not the 19 of the reference; all plant constants (encoder, destinations, stations, thresholds, storage DB, removal handshake) open; pin separator times 0/50 ms (`pruefen`); simulation settings `stSimu` of the reference not written; the FB has one `JamEntr`/`JamExit` — since v4 several feeds merge into the one entry jam area (mubea: 2 feeds → 1 entry); a store with more than one entry or exit jam area (mubea: 2 exits) gets a TODO in the REGION header |
|
||||
|
||||
New context fields for these templates (`lib/scl_context.py`): Cognex wiring per scanner
|
||||
(`interface`, `tag`, `hw_results`), `part_sensor` per separator, `carriers`/`data` per jam
|
||||
@@ -290,7 +290,8 @@ path does not use them — its golden files are unchanged.
|
||||
Effect on the open-value count with `--templates`: with the pilot only, mubea 282 → 302
|
||||
and HundM05 323 → 377; with all seven templates mubea → 489 and HundM05 → 475
|
||||
`TODO(E-Planung)` (HundM05 now comes completely from templates, mubea except the
|
||||
`2Sep2Swi`). More reference lines are written and every open value is marked; the count
|
||||
`2Sep2Swi`). Since TRO-JSON v4 (one entry jam area per TRO instead of one per
|
||||
predecessor) it is: mubea 277 generic → 482 with templates, HundM05 316 → 461. More reference lines are written and every open value is marked; the count
|
||||
drops again with the naming rules (step 4).
|
||||
|
||||
---
|
||||
@@ -420,7 +421,7 @@ With `--templates` the console summary gets a `Templates` line (implemented); th
|
||||
|
||||
```
|
||||
Templates = 4 von 5 Typen (generisch: FB_ILS_MTRO_2Sep2Swi)
|
||||
Offene Stellen = 489 (Marker 'TODO(E-Planung)')
|
||||
Offene Stellen = 482 (Marker 'TODO(E-Planung)')
|
||||
```
|
||||
|
||||
---
|
||||
@@ -478,7 +479,7 @@ bin\scl_skeleton.bat --json <name>_tro.json [--templates [DIR]] [--strict] [--na
|
||||
| File | Where | Who writes it |
|
||||
|---|---|---|
|
||||
| `<name>.csv` | `%SKEL_DATA%` | dxfmakros `EXPORTCSV` |
|
||||
| `<name>_tro.json` | `%SKEL_RESULTS%` | `tro_flow --json` (schema `sps_skel-tro-v3`) |
|
||||
| `<name>_tro.json` | `%SKEL_RESULTS%` | `tro_flow --json` (schema `sps_skel-tro-v4`) |
|
||||
| `scl_naming.ini`, `<name>_scl_naming.ini` | `%SKEL_CFG%` | you, once per project (optional) |
|
||||
| `lib/scl_templates/*.scl.j2` | repo | maintained with the PLC engineers |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user