E-Planung -> Layout: e_planning.py, scl_skeleton --eplan, Kapitel Daten
- doc/Klassenhierarchie.md: Kapitel "Daten" - alle Daten der SCL-Referenzen nach Quelle (Layout, E-Planung, Namenskonvention, Parameter) - doc/E-Planung_Bruecke.md: Bruecke ueber *_positionsdraw.json des Kabellaengen-Tools, Befunde an Mubea - lib/e_planning.py + cfg/e_planning.ini + bin/e_planning.bat/.sh: Lagebezug E-Zeichnung -> CSV, Zuordnung BMK -> Layout-Bauteil nach Regeln (Abstand, Sollabstand, Nummernregel MB = BG + 1), <csv>_eplan.json + Bericht - scl_skeleton --eplan: Separator-Sensor und Stopperventil eingesetzt, ohne Schalter unveraenderte Ausgabe (Golden-Files gleich) - tests/test_e_planning.py Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5764df1ac8
commit
c736288476
@@ -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.
|
||||
@@ -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
|
||||
@@ -132,6 +134,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
|
||||
@@ -414,3 +427,188 @@ 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** | Hardwarelayout (CSV-Export ILS 2.0, `data/*.csv`) | Bauteile (`TeileArt`: Separator, Scanner, Weiche, Kreisel, Strecke, Gefällestrecke, BTMT Be-/Entladung, Ein-/Ausschleuselement), `Nachbarn`/`TrackIds`, `Merkmale` (Drehrichtung, Antriebfahrtrichtung, Höhen, Längen, Anzahl Separatoren/Scanner, Zuordnung). Daraus abgeleitet: TRO-Typ, Topologie, Reihenfolge, Ziele. |
|
||||
| **E** | Elektroplanung (EA-Liste/WSCAD/TIA-Variablentabelle, siehe `doc/HundM/EA-Listen-Analyse.md`) | Betriebsmittelkennzeichen und Variablennamen (`BG…` Sensoren, `MB…` Ventile, `MA…` Motoren, `FC…` Motorschutz, `SF…` Taster, `BX…` Scanner), Hardware-Kennungen, welche optionalen Sensoren verbaut sind, Zuordnung zu Schaltschrank und Not-Halt-Kreis. |
|
||||
| **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.
|
||||
|
||||
### 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 | je Vorgänger ein Eingang, 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.
|
||||
|
||||
+106
-6
@@ -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
|
||||
@@ -91,6 +98,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 +111,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.
|
||||
@@ -460,7 +470,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.
|
||||
@@ -492,6 +502,16 @@ times 100/50 ms), and every value that is still open carries
|
||||
`TODO(E-Planung)`. `--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
|
||||
@@ -500,6 +520,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
|
||||
|
||||
Reference in New Issue
Block a user