hw_import + merge_hw_layout: Hardwareplanung einlesen und mit dem Layout zusammenfuehren
Stufen 2 und 3 aus doc/Konzept_Layout_Hardware_SCL.md: - lib/hw_import.py: TIA-Import (*_TIA.xlsx, ohne openpyxl gelesen) + Positionsdatei (*_positionsconv.json) -> <projekt>_hw.json: je BMK Adresse, Index-Konstante, VERW, Station, Lage, Foerderer (K0102, #106 -> K0106); Antriebe MA/FC/GF; Gegenpruefung beider Quellen. - lib/merge_hw_layout.py: <csv>_tro.json + <projekt>_hw.json -> <csv>_anlage.json (model.AnlageDocument): bindings je TRO-ID + Slot + Rolle mit Konstante und Adresse, Foerderer per Mehrheit (Mubea: K0102 = Kreisel3, K0104 = Kreisel2, K0105 = Kreisel1), Handkorrekturen cfg/hw_overrides.ini. Zuordnungslogik aus e_planning.py hierher verschoben; e_planning re-exportiert sie, Ergebnis unveraendert. - TRO-JSON traegt optional `parts` (Lage/Huellbox, tro_flow --json), PinStore bekommt Slots line<n>. - Gespeicherter Lagebezug mit SHA-256 der Positionsdatei; Unterordner in Eingabenamen relativ zu SKEL_DATA. - Doku: Python_Scripts.md 5d/5e, Konzept, E-Planung_Bruecke (Abgleich mubea_layout.dxf / CSV / E-Planung). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c4122b4497
commit
df24cf5adb
+143
-14
@@ -1,9 +1,11 @@
|
||||
# Brücke Layout ↔ E-Planung über `*_positionsdraw.json`
|
||||
|
||||
Stand 2026-10-10. Erst Machbarkeitsprüfung, inzwischen umgesetzt als
|
||||
Stand 2026-10-15. 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.
|
||||
Umsetzung unten. Am 2026-10-15 mit dem neuen Mubea-Datensatz in `data/Mubea/`
|
||||
(TIA-Import + Positionsdatei) nachgeprüft; Ergebnisse unter "Nachprüfung
|
||||
2026-10-15".
|
||||
|
||||
## Problem
|
||||
|
||||
@@ -34,16 +36,47 @@ passender Art.
|
||||
|
||||
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),
|
||||
Dateien mit `BG`/`MB`/`MA`: `Mubea_positionsdraw.json` (158 Feld-BMK, davon 157
|
||||
in `mappings` unter UH01 — `BG0514` hat eine leere `KENNZEICHNUNG`),
|
||||
`ST500592_ILS_positionsdraw.json` (~3100), `ST500592_10_5-10_Omniflo_…` (~900),
|
||||
`ST-Fortna_positions_.json` (mit 38 Scannern `BX`).
|
||||
|
||||
`*_positionsconv.json` und `*_positionsdraw.json` sind bei Mubea byte-gleich;
|
||||
eine von beiden genügt.
|
||||
|
||||
## Datenquelle TIA-Import `*_TIA.xlsx`
|
||||
|
||||
Die zweite nötige Quelle. Blatt **PLC Tags**: je Signal Name (`BG0542`),
|
||||
Absolutadresse (`%E…`/`%A…`), Kommentar. Blatt **Constants**: je Signal eine
|
||||
Index-Konstante `cIn<BMK>`/`cOut<BMK>` (laufender Index, **nicht** aus der
|
||||
Adresse berechenbar).
|
||||
|
||||
| Nutzen | Warum |
|
||||
|---|---|
|
||||
| SCL übersetzbar | Sensoren stehen im SCL als `"DB_Inputs".Sensors["cInBG…"]`, Ventile als `"MB…"`; beides muss im TIA-Projekt existieren — der TIA-Import liefert genau diese Tags und Konstanten |
|
||||
| Prüfliste | jeder Name im erzeugten SCL muss im TIA-Import stehen |
|
||||
| `FB_CallSensors`, Größe `DB_Inputs` | alle `cIn…`-Konstanten mit Wert (noch nicht generiert) |
|
||||
| Schrank- und Antriebssignale | `SF…` (Taster, Not-Halt), `PF…` (Leuchten), `MA…`/`FC…` (Motor/Motorschutz), `GF…` (Geber), `BP…`, `DI…` |
|
||||
|
||||
Mubea: 237 Tags (105 BG, 64 MB, 26 SF, 17 PF, 11 MA, 11 FC, je 1 BP/DI/GF) und
|
||||
237 Konstanten (144 `cIn`, 93 `cOut`). Alle 158 Feld-BMK und 80 von 81
|
||||
Schrankelementen (fehlt: `QA7000`) der Positionsdatei stehen im TIA-Import, die
|
||||
Kommentare sind 1:1 gleich der `BEZEICHNUNG`.
|
||||
|
||||
**Nicht nötig** (Mubea): `*_EA.xlsx` (dieselben 237 Signale, nur Adresse und
|
||||
Kommentar, keine Namen), `*_WSCAD.xlsx` (zusätzlich nur die E/A-Baugruppe je
|
||||
Kanal, die `KENNZEICHNUNG` der Positionsdatei schon trägt, und 259 freie Kanäle),
|
||||
`*_BOM.xlsx`, `*_cables.*`, `*_todraw.json`, `*_errors.json` (Kabel, Stückliste,
|
||||
Trassen; die Qualitätswarnungen stehen auch in der Positionsdatei). Eingaben für
|
||||
die Brücke also: **CSV + TIA-Import + eine Positionsdatei**.
|
||||
|
||||
## 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.
|
||||
`kabellaengen/work/Mubea_positionsdraw.json` (E-Planung, alter Stand). Die Zahlen
|
||||
in diesem Abschnitt stammen aus der ersten Untersuchung (Umkreis 700 mm, ohne
|
||||
Regeln); das Ergebnis der Umsetzung und die Nachprüfung mit dem neuen Stand
|
||||
`data/Mubea/Mubea_positionsdraw.json` stehen unten.
|
||||
|
||||
### 1. Lagebezug
|
||||
|
||||
@@ -57,10 +90,15 @@ mubea.csv <- Mubea_positionsdraw.json: dx +50613.6 mm, dy +8555.8 mm, Drehung 0
|
||||
```
|
||||
|
||||
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
|
||||
(dx +50833.7, dy +8414.5) bis auf ~250 mm: diese (alte) E-Zeichnung lag 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.
|
||||
bestehende Mechanismus; als Schlüssel in `cfg/dxf_registration.json` dient
|
||||
`<csv>|<positionsdraw.json>`.
|
||||
|
||||
Das gilt **nicht allgemein**: der neue Stand in `data/Mubea/` liegt in einem
|
||||
anderen Koordinatensystem (dx −151.4, dy −696.6, siehe "Nachprüfung
|
||||
2026-10-15"). Der Lagebezug ist je Datei neu zu ermitteln, nicht von der
|
||||
Layoutzeichnung zu übernehmen.
|
||||
|
||||
### 2. Was sich zuordnen lässt
|
||||
|
||||
@@ -121,13 +159,20 @@ ist ein anderes Projekt nötig (`ST-Fortna_positions_.json`, `ILS-Baugruppe`).
|
||||
| `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 |
|
||||
| `xInCarouselRun` (welcher Antrieb) | FC/MA-`BEZEICHNUNG` "KREISEL-K0102", "CONVEYOR #100" | **räumlich**, nicht über Text: das CSV nennt die Kreisel `Kreisel1/2/3`, die E-Planung `K0102/K0104/K0105`. Alle Symbole, deren `BEZEICHNUNG` einen Kreisel nennt, per Mehrheit dem nächsten CSV-Kreisel zuordnen (siehe Nachprüfung) |
|
||||
| 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`).
|
||||
Nicht aus dieser Quelle: Scanner-Hardwarekennungen, Weichenbauart (`xNewSwitch`).
|
||||
|
||||
Auch nicht aus den E/A-Daten, aber **je Projekt nur ein Wert**: `xInSftyOk`,
|
||||
`stInOutMachineState`, `xInAutomatic`, `xInErrorQuit`. Der TIA-Import enthält
|
||||
zwar die Not-Halt-Kanäle (`SF5000…SF6006`) und `SF0001` "ANLAGE EIN" / `SF0002`
|
||||
"START NACH STÖRUNG", die Referenz-SCL verdrahtet diese Parameter aber nicht mit
|
||||
E/A-Signalen, sondern mit dem Sicherheitsprogramm
|
||||
(`"DB_InterfaceSafety".stFromSafety.EStopMain….Q`) bzw. der Schrank-Struktur
|
||||
(`#stInOutControlUnitCabinet…`). Sie gehören als Projektkonstanten in eine
|
||||
Konfiguration (bei Mubea ~39 der offenen Stellen), nicht in die Brücke.
|
||||
|
||||
## Umsetzung (Stand 2026-10-10)
|
||||
|
||||
@@ -144,11 +189,59 @@ Weichenbauart (`xNewSwitch`).
|
||||
`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,
|
||||
Ergebnis Mubea (alter Stand) 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.
|
||||
|
||||
## Nachprüfung 2026-10-15 (neuer Stand `data/Mubea/`)
|
||||
|
||||
Lauf: `e_planning --file mubea.csv --eplan <voller Pfad>\data\Mubea\Mubea_positionsdraw.json`,
|
||||
dann `tro_flow --json` und `scl_skeleton --eplan --templates`.
|
||||
|
||||
| | alter Stand | neuer Stand |
|
||||
|---|---|---|
|
||||
| Lagebezug | dx +50613.6, dy +8555.8 | **dx −151.4, dy −696.6**, Drehung 0, 23/38 Punkte, Restfehler max 541 mm |
|
||||
| Separator-Sensor | 21/38 | 21/38 |
|
||||
| Stopper | 22/38 | 22/38 |
|
||||
| Stausensor | 20/23 | **21/23** |
|
||||
| Ausschleusventil | 20/23 | **19/23** |
|
||||
| Weichenventil | 1/1 | 1/1 |
|
||||
| Antriebe | — | 11, alle mit Motorschutz |
|
||||
|
||||
Im erzeugten `FB_Main` (18 TROs): 43 Namen aus der E-Planung, 440 Stellen
|
||||
`TODO(E-Planung)`. Alle 21 Konstanten und 22 Tags im SCL stehen im TIA-Import.
|
||||
|
||||
Befunde:
|
||||
|
||||
- **Pfad:** `--eplan Mubea/Mubea_positionsdraw.json` (Unterordner relativ zu
|
||||
`%SKEL_DATA%`) wird nicht gefunden; nur ein Dateiname direkt in `%SKEL_DATA%`
|
||||
oder ein voller Pfad geht.
|
||||
- **Gespeicherter Lagebezug:** der Schlüssel `<csv>|<positionsdraw.json>` in
|
||||
`cfg/dxf_registration.json` enthält nur den Dateinamen. Ein neuer Stand mit
|
||||
gleichem Namen übernimmt ohne `--re-register` still den alten Bezug — beim
|
||||
Mubea-Wechsel wären das ~51 m Versatz gewesen.
|
||||
- **Kreisel-Zuordnung räumlich möglich:** die Symbole, deren `BEZEICHNUNG` einen
|
||||
Kreisel nennt (nach dem Lagebezug, Abstand zur Boundingbox), liegen eindeutig
|
||||
auf einem CSV-Kreisel — **K0102 = Kreisel3 (0010)**, **K0104 = Kreisel2 (0002)**,
|
||||
**K0105 = Kreisel1 (0001)**; ein Ausreißer (`BG0725` "BANDBRUCHÜBERWACHUNG
|
||||
KR-K0105" an Kreisel2). Damit erhält jeder Kreisel seinen Antrieb
|
||||
(`MA0202`/`FC0202`, `MA0205`/`FC0205`, `MA0206`/`FC0206`) und K0102 seinen Geber
|
||||
`GF20000`.
|
||||
|
||||
Was sich mit TIA-Import + Positionsdatei noch schließen lässt:
|
||||
|
||||
| Offene Stellen (Mubea) | Anzahl | Weg |
|
||||
|---|---|---|
|
||||
| `stInSenJam<n>` | ~17 | schon zugeordnet; fehlt nur TRO-Ausgang → Ausschleuselement (siehe "Offen") |
|
||||
| `xInCarouselRun` | ~13 | Kreisel-Zuordnung oben + Motorpaar |
|
||||
| Vario-Sensoren (`stSenLastPos`, `stSenJam`, `stSenFinger`, `stSenCarrInPos`), `xOutVarioMotor`, `xInMotorProtection` | ~18 | wahrscheinlich, neue Regeln über `VERW` (`SYNC P1..4`, `ZAPPLER`, `ABFR.FINGER`, `BT BELADEN`) und die Motorpaare; zu prüfen |
|
||||
| `xInSftyOk`, `stInOutMachineState`, `xInAutomatic`, `xInErrorQuit` | ~39 | Projektkonstante (oben), nicht aus diesen Dateien |
|
||||
| `nSeparatorNo`/`nSwitchNo`, Zeiten, Staubereichs-Verdrahtung | Rest | weder TIA noch Positionsdatei |
|
||||
|
||||
Die 17 nicht zugeordneten Separatoren an den Kreiseln sind ein Standunterschied
|
||||
Layout ↔ E-Zeichnung, keine fehlenden Daten.
|
||||
|
||||
Offen:
|
||||
|
||||
- Stausensoren und Ausschleus-/Weichenventile stehen in JSON und Bericht, kommen
|
||||
@@ -159,3 +252,39 @@ Offen:
|
||||
- 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.
|
||||
- ~~TIA-Import einlesen~~ — **erledigt** 2026-10-15: `lib/hw_import.py`
|
||||
(`<projekt>_hw.json`); `FB_CallSensors` daraus steht noch aus.
|
||||
- ~~Kreisel ↔ E-Kreisel (`K01xx`) räumlich zuordnen~~ — **erledigt** in
|
||||
`lib/merge_hw_layout.py` (Mehrheit, nur Förderer der genannten Art); in die SCL
|
||||
(`xInCarouselRun`) kommt es mit der Umstellung von `scl_skeleton` auf die
|
||||
Anlagen-JSON.
|
||||
- ~~Gespeicherten Lagebezug absichern~~ — **erledigt**: SHA-256 der
|
||||
Positionsdatei im Eintrag von `cfg/dxf_registration.json`.
|
||||
- ~~Unterordner in `--eplan`~~ — **erledigt** (`material_flow.resolve_input`).
|
||||
|
||||
## Abgleich Layoutzeichnung ↔ CSV ↔ E-Planung (2026-10-15)
|
||||
|
||||
Zeichnung `data/mubea_layout.dxf` (aus `mubea_layout.dwg`), gelesen über alle
|
||||
Blockebenen mit vollständiger Blocktransformation (die `Staustrecke…`-Blöcke
|
||||
der Gefällestrecken sind mit gekippter Extrusionsrichtung eingefügt; ohne
|
||||
OCS liegen ihre Separatoren falsch).
|
||||
|
||||
| Vergleich | Ergebnis |
|
||||
|---|---|
|
||||
| DXF ↔ `mubea.csv` | **gleiches Koordinatensystem, kein Versatz.** 38/38 Separatoren je 60–70 mm (Einfügepunkt `Separator_SP_3D` gegen CSV-Punkt, in Blockrichtung), 8/8 Scanner je 360 mm, Aus-/Einschleuselemente 22/23 bzw. 22/23 auf 0 mm (`0061`, `0064` und die Weiche `0125` sind keine eigenen Blöcke) |
|
||||
| E-Planung ↔ DXF | (−211, −697) mm; Speicherlinien 20/20 auf **1 mm** |
|
||||
| E-Planung ↔ CSV | (−151, −697) mm; 23/38 im Toleranzband |
|
||||
|
||||
Die 20 Separatoren der Gefällestrecken passen mit dem Versatz exakt (ohne ihn
|
||||
liegt jeder Sensor eine Speicherlinie daneben, 235 mm). Die 12 Separatoren an
|
||||
Kreiseln/Strecken und die 6 Vario-Separatoren passen in **keiner** Lage
|
||||
(155–3438 mm, mit und ohne Versatz). Es gibt also keine starre Transformation
|
||||
für die ganze Anlage: der Speicher ist in der E-Zeichnung als Ganzes
|
||||
verschoben, der Bereich um die Kreisel ist ein anderer Planungsstand.
|
||||
Folge: die Kreisel-Separatoren bleiben offen, bis E-Zeichnung und Layout zum
|
||||
selben Stand gehören; `merge_hw_layout` warnt deshalb (23/38 = 61 %).
|
||||
|
||||
Nebenbefund für `tro_annotate` (Kontrollansicht): es liest nur die
|
||||
Modellbereichs-Blöcke (12 der 38 Separatoren, die übrigen stecken in
|
||||
`GF_n`/`VF_n`), und der Lagebezug übernimmt den 60-mm-Einfügeversatz als
|
||||
scheinbare Verschiebung (dx +59.8).
|
||||
|
||||
@@ -23,11 +23,11 @@ Hardware später nachtragen können, ohne Layout-Arbeit zu wiederholen.
|
||||
|
||||
```text
|
||||
Abteilung 1: Anlagenlayout Abteilung 2: Hardwareplanung (später)
|
||||
CSV ──tro_flow──> <csv>_tro.json EA/TIA/WSCAD.xlsx, positionsdraw.json
|
||||
CSV ──tro_flow──> <csv>_tro.json TIA.xlsx, positionsdraw.json
|
||||
(TROs, Abfolge, ──hw_import──> <projekt>_hw.json
|
||||
Staubereiche, Slots) (globale Variablen, Geräte)
|
||||
│ │
|
||||
└──────────── hw_assign ─────────────────┘
|
||||
└──────────── merge_hw_layout ─────────────────┘
|
||||
│
|
||||
<csv>_anlage.json (Layout + Zuordnungen)
|
||||
│
|
||||
@@ -37,8 +37,8 @@ CSV ──tro_flow──> <csv>_tro.json EA/TIA/WSCAD.xlsx, positionsd
|
||||
| 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`) |
|
||||
| 2 Hardware | `hw_import.py` | `*_TIA.xlsx`, `*_positionsdraw.json` (optional `*_EA.xlsx`/`*_WSCAD.xlsx` ohne Positionsdatei) | `<projekt>_hw.json` | vorhanden (2026-10-15), ohne EA/WSCAD |
|
||||
| 3 Zuordnung | `merge_hw_layout.py` | `<csv>_tro.json`, `<projekt>_hw.json`, Regeln, `cfg/hw_overrides.ini` | `<csv>_anlage.json`, Bericht `.md` | vorhanden (2026-10-15, Logik aus `e_planning.py`) |
|
||||
| 4 SCL | `scl_skeleton.py` | `<csv>_anlage.json` (oder nur `<csv>_tro.json`) | `.scl` | vorhanden, wird umgestellt |
|
||||
|
||||
Grundsätze:
|
||||
@@ -109,8 +109,12 @@ Weichenventile (`doc/E-Planung_Bruecke.md`, "Offen").
|
||||
|
||||
### 2. Neues Skript `hw_import.py` (Stufe 2)
|
||||
|
||||
- Liest TIA-Import (PLC Tags + Constants), EA-Liste, WSCAD-Import und optional
|
||||
`positionsdraw.json`.
|
||||
- Liest TIA-Import (PLC Tags + Constants) und `positionsdraw.json`. Das genügt:
|
||||
bei Mubea stehen alle BMK der Positionsdatei im TIA-Import, die Kommentare sind
|
||||
gleich; EA-Liste und WSCAD-Import bringen nichts dazu (EA ohne Namen, WSCAD nur
|
||||
die E/A-Baugruppe, die `KENNZEICHNUNG` schon trägt). EA/WSCAD nur als Ersatz,
|
||||
wenn keine Positionsdatei vorliegt (Weg "nur EA-Liste" in Stufe 3). Befund in
|
||||
`doc/E-Planung_Bruecke.md`, "Nachprüfung 2026-10-15".
|
||||
- Schreibt ein neues Modell `HardwareDocument`:
|
||||
- **Geräte** je BMK: Adresse, Index-Konstante (`cInBG3306`), Kommentar, VERW,
|
||||
Steuerung, Station/Schrank, Position (falls vorhanden);
|
||||
@@ -122,7 +126,7 @@ Weichenventile (`doc/E-Planung_Bruecke.md`, "Offen").
|
||||
- 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)
|
||||
### 3. Neues Skript `merge_hw_layout.py` (Stufe 3)
|
||||
|
||||
- Eingabe: `<csv>_tro.json` + `<projekt>_hw.json`; das CSV wird nicht mehr gelesen.
|
||||
- Zuordnungswege, als Regeln in einer INI (heute `cfg/e_planning.ini`):
|
||||
@@ -152,6 +156,36 @@ Weichenventile (`doc/E-Planung_Bruecke.md`, "Offen").
|
||||
- **Gegenprüfung** beider Quellen (Anzahl Separatoren vs. `IN SEP`, Weichen vs.
|
||||
`AE ABZWEIG`, angetriebene Strecken vs. `MA`) in den Bericht.
|
||||
|
||||
**Stand Umbau 2/3 (2026-10-15), umgesetzt:**
|
||||
|
||||
- `lib/hw_import.py` (`bin/hw_import.bat`): TIA-Import (Blätter an der
|
||||
Kopfzeile erkannt, xlsx ohne openpyxl gelesen) + Positionsdatei →
|
||||
`<projekt>_hw.json` (`HardwareDocument`, `sps_skel-hw-v1`): je BMK Adresse,
|
||||
Richtung, Index-Konstante, VERW, Station, Lage, Förderer; Antriebe mit
|
||||
Motorschutz und Geber; Gegenprüfung beider Quellen. EA-Liste/WSCAD nicht
|
||||
gelesen (Weg "nur EA-Liste" bleibt offen).
|
||||
- `lib/merge_hw_layout.py` (`bin/merge_hw_layout.bat`): `<csv>_tro.json` +
|
||||
`<projekt>_hw.json` → `<csv>_anlage.json` (`model.AnlageDocument`,
|
||||
`sps_skel-anlage-v1`): Layout unverändert unter `layout`, daneben
|
||||
`bindings[]` (Schlüssel TRO-ID + Slot + Rolle, mit Konstante und Adresse aus
|
||||
dem TIA-Import, Status `zugeordnet`/`offen`/`widerspruch`/`ohne_slot`) und
|
||||
`conveyors[]`. Handkorrekturen `cfg/hw_overrides.ini`, Zahlenwerte
|
||||
`cfg/parameter.ini [merge_hw_layout]`.
|
||||
- Damit `merge_hw_layout` kein CSV liest, trägt die TRO-JSON jetzt `parts` (Lage und
|
||||
Hüllbox der Layout-Bauteile, von `tro_flow --json`; Schema bleibt v4, eine
|
||||
Datei ohne `parts` liest sich weiter). Ein `PinStore_Auto` hat je Lagerlinie
|
||||
einen Slot `line<n>`.
|
||||
- **Förderernummer:** die E-Planung nennt Förderer im Klartext als `K0102` bzw.
|
||||
`#106` (beides dieselbe Nummer, `CONVEYOR-#103` = `CONVEYOR-K0103`).
|
||||
`merge_hw_layout` ordnet sie per Mehrheit der Feldgeräte einem Layout-Förderer zu
|
||||
(Mubea: K0102 = Kreisel3, K0104 = Kreisel2, K0105 = Kreisel1). Das ist die in
|
||||
"Staubereiche" gesuchte Quelle für `<NNNN>` und für `xInCarouselRun`.
|
||||
- Gespeicherter Lagebezug mit SHA-256 der Positionsdatei; ein neuer Stand
|
||||
gleichen Namens wird neu ermittelt.
|
||||
- Noch offen: Weichen-/Ausschleus-Slots mit Layout-ID (sonst bleiben
|
||||
Stausensoren und Ausschleusventile `ohne_slot`), Scanner (`BX`), Weg "nur
|
||||
EA-Liste", Umstellung von `scl_skeleton` (Umbau 4).
|
||||
|
||||
### 4. `scl_skeleton.py` / `scl_context.py` (Stufe 4)
|
||||
|
||||
- Liest **eine** Eingabe: `<csv>_anlage.json`; ohne Hardwareteil wie heute
|
||||
@@ -180,16 +214,16 @@ Projektdatei `cfg/defaults.ini`.
|
||||
| `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`
|
||||
### `e_planning.py` → `hw_import` + `merge_hw_layout`
|
||||
|
||||
| Teil heute | Wohin |
|
||||
|---|---|
|
||||
| `load_positionsdraw`, `EDevice`, `pair_drives` | `hw_import.py` |
|
||||
| `resolve_transform`, `load_rules`, `_assign_spatial`, `_assign_by_number`, Bericht | `hw_assign.py`, Ziele = Slots statt CSV-Bauteile |
|
||||
| `cfg/e_planning.ini` | Regeldatei von `hw_assign` |
|
||||
| `resolve_transform`, `load_rules`, `_assign_spatial`, `_assign_by_number`, Bericht | `merge_hw_layout.py`, Ziele = Slots statt CSV-Bauteile |
|
||||
| `cfg/e_planning.ini` | Regeldatei von `merge_hw_layout` |
|
||||
| `EplanDocument` / `<csv>_eplan.json` | entfällt, ersetzt durch `bindings[]` |
|
||||
|
||||
Übergang: `e_planning.py` bleibt kurz als Hülle, die `hw_import` und `hw_assign`
|
||||
Übergang: `e_planning.py` bleibt kurz als Hülle, die `hw_import` und `merge_hw_layout`
|
||||
nacheinander aufruft, damit `bin/e_planning.bat` weiter funktioniert; danach
|
||||
löschen.
|
||||
|
||||
@@ -276,7 +310,7 @@ Einzelheiten in `doc/Python_Scripts.md` §4 "TRO-IDs"):**
|
||||
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.
|
||||
`cfg/tro_overrides.ini` und die Zuordnungen von `merge_hw_layout` stabil.
|
||||
|
||||
### Staubereiche
|
||||
|
||||
@@ -356,9 +390,12 @@ unverändert.
|
||||
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.
|
||||
3. `hw_import` mit dem TIA-Import als erster Quelle. **Erledigt** (2026-10-15,
|
||||
siehe unten "Stand Umbau 2/3").
|
||||
4. `merge_hw_layout` mit der räumlichen Logik aus `e_planning.py`; `e_planning.py` als
|
||||
Übergangshülle. **Erledigt bis auf die Hülle** (2026-10-15): die Logik liegt
|
||||
in `merge_hw_layout.py`, `e_planning.py` importiert sie und bleibt vollständig,
|
||||
solange `scl_skeleton --eplan` die `<csv>_eplan.json` liest (Schritt 5).
|
||||
5. `scl_skeleton` auf `<csv>_anlage.json` umstellen, `--eplan` entfernen;
|
||||
`tro_annotate` auf JSON umstellen.
|
||||
6. Defaults (`cfg/defaults.ini`), `FB_CallSensors`, EA-Liste ohne Positionen.
|
||||
|
||||
+161
-12
@@ -1,16 +1,20 @@
|
||||
# Python Scripts — CLI Tooling Overview
|
||||
|
||||
**As of:** 2026-10-10
|
||||
**As of:** 2026-10-15
|
||||
|
||||
`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. `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.
|
||||
`lib/` currently holds sixteen Python modules (eight of them runnable CLI
|
||||
tools, eight 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. `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.
|
||||
`hw_import.py` and `merge_hw_layout.py` are the new path for that bridge
|
||||
(`doc/Konzept_Layout_Hardware_SCL.md`, stages 2 and 3): TIA import +
|
||||
positions file → `<project>_hw.json`, merged with the TRO-JSON into
|
||||
`<csv>_anlage.json` (§5d, §5e).
|
||||
|
||||
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
|
||||
@@ -42,6 +46,12 @@ tro_flow.py ──► <name>_tro_flow.dot / .svg, _tro_doc.md, _tro_error
|
||||
│ (assigns BG/MB of the E-planning drawing to the layout
|
||||
│ parts by position + numbering rule; see §5c)
|
||||
│
|
||||
│ NEW PATH (stages 2/3, scl_skeleton does not read it yet):
|
||||
│ <name>_tro.json ──┐
|
||||
│ ├─► merge_hw_layout.py ──► <name>_anlage.json + .md (§5e)
|
||||
│ hw_import.py ─────┘ (TRO slots <- BMK, conveyors K0102 -> Kreisel3)
|
||||
│ ▲ *_TIA.xlsx + *_positionsconv.json (§5d)
|
||||
│
|
||||
└── same derivation ──► tro_annotate.py ──► <name>_annotated.dxf (VIEWER ONLY)
|
||||
(also needs the BricsCAD DXF; uses dxf_registration.py for the CSV↔DXF
|
||||
coordinate offset and tro_catalog.py for marker shape/color per TRO type)
|
||||
@@ -655,6 +665,141 @@ 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`).
|
||||
|
||||
> **Since 2026-10-15** the E model (`EDevice`, `load_positionsdraw`,
|
||||
> `pair_drives`) lives in `hw_import.py` and the assignment logic (rules,
|
||||
> spatial, numbering rule, registration) in `merge_hw_layout.py`; `e_planning.py`
|
||||
> imports and re-exports them and keeps only `EplanDocument`, the CSV path,
|
||||
> report and CLI. Results are unchanged (Mubea: 43 names in the SCL). It stays
|
||||
> until `scl_skeleton` reads `<csv>_anlage.json`. The stored registration now
|
||||
> carries a SHA-256 of the positions file: a new file with the same name is
|
||||
> registered anew instead of silently reusing the old offset. `--eplan` (and
|
||||
> every `--file`-style input) also resolves a relative sub-folder against
|
||||
> `%SKEL_DATA%` (`Mubea/Mubea_positionsdraw.json`).
|
||||
|
||||
## 5d. `hw_import.py` — read the hardware planning (TIA import + positions file)
|
||||
|
||||
Stage 2 of [`Konzept_Layout_Hardware_SCL.md`](Konzept_Layout_Hardware_SCL.md).
|
||||
Two sources are enough (finding in [`E-Planung_Bruecke.md`](E-Planung_Bruecke.md),
|
||||
"Nachprüfung 2026-10-15"); the EA list and the WSCAD import add nothing once a
|
||||
positions file exists.
|
||||
|
||||
```
|
||||
*_TIA.xlsx (PLC Tags + Constants) ─┐
|
||||
├─► hw_import.py ──► <project>_hw.json (HardwareDocument, sps_skel-hw-v1)
|
||||
*_positionsconv.json (optional) ────┘ ──► <project>_hw.md (report: devices, drives, checks)
|
||||
```
|
||||
|
||||
- **TIA import**: sheets are recognised by their header row, not their name
|
||||
(English and German TIA exports): a sheet with `Logical Address` /
|
||||
`Logische Adresse` holds tags, one with `Value` / `Wert` constants. Read with
|
||||
`zipfile` + XML — no openpyxl dependency.
|
||||
- **Per BMK one `HwDevice`** (an `EDevice` plus): `direction` (`in`/`out` from
|
||||
`%E`/`%I` vs. `%A`/`%Q`), `address`, `dataType`, `comment`, the index constant
|
||||
`constant` (`cInBG0532` / `cOutMB0533` — what the SCL references) with its
|
||||
`constantValue`, `conveyor` + `conveyorKind`, and `sources` (`tia`,
|
||||
`positions`).
|
||||
- **Conveyor from the plain text**: `KREISEL-K0102`, `KR-K0104` → `K0102`,
|
||||
`K0104` (kind `Kreisel`); `CONVEYOR-#103` and `CONVEYOR-K0103` are the same
|
||||
conveyor and both become `K0103` (kind `Strecke`) — the four-digit conveyor
|
||||
number of the SCL naming scheme (`DB_JamArea0103`, `fbCarousel0102`).
|
||||
- **Drives**: motor `MA` ↔ motor protection `FC` (same number), conveyor and
|
||||
kind from their texts, encoder `GF…` of the same conveyor.
|
||||
- **Cross-check** (`checks`, also printed as `?` lines): BMK only in the
|
||||
positions file / field device (`BG`/`MB`/`MA`/`BX`) only in TIA, TIA comment ≠
|
||||
`BEZEICHNUNG`, signal without index constant, index constant without signal,
|
||||
duplicate addresses, duplicate constant values, field device without
|
||||
controller in `KENNZEICHNUNG`. The positions file's own `warnings` are passed
|
||||
through.
|
||||
|
||||
Switches: `--tia NAME` (required), `--positions NAME` (optional; without it no
|
||||
positions), `--project NAME` (default from the positions file name:
|
||||
`Mubea_positionsconv.json` → `Mubea`). Names resolve against `%SKEL_DATA%`,
|
||||
also with a sub-folder. Exit `0` (findings are in the report), `1` on input or
|
||||
read errors.
|
||||
|
||||
Result on Mubea (`mubea-1_TIA.xlsx` + `Mubea_positionsconv.json`): 238 devices,
|
||||
237 in both sources, 237 index constants, 158 field devices with position,
|
||||
11 drives all with motor protection and conveyor (encoder `GF20000` at K0102);
|
||||
checks: `QA7000` only in the positions file, `BG0514` without controller.
|
||||
|
||||
Tests: `tests/test_hw_import.py` (xlsx reader with shared/inline strings,
|
||||
header-based sheet detection, conveyor texts, merge per BMK, drives, every
|
||||
cross-check, TIA-only run, JSON round trip, CLI with a sub-folder in
|
||||
`%SKEL_DATA%`). The test builds its own small TIA xlsx.
|
||||
|
||||
## 5e. `merge_hw_layout.py` — merge layout and hardware planning into the plant JSON
|
||||
|
||||
Stage 3 of the concept. Reads **no CSV**: the TRO-JSON carries the TRO slots
|
||||
and, since 2026-10-15, the positions and bounding boxes of the layout parts
|
||||
(`parts`, written by `tro_flow --json`).
|
||||
|
||||
```
|
||||
<name>_tro.json + <project>_hw.json
|
||||
└──────┬──────┘
|
||||
merge_hw_layout.py rules %SKEL_CFG%\e_planning.ini, corrections %SKEL_CFG%\hw_overrides.ini
|
||||
│
|
||||
├─► <name>_anlage.json (AnlageDocument, sps_skel-anlage-v1:
|
||||
│ layout unchanged + bindings[] + conveyors[])
|
||||
└─► <name>_anlage.md (report)
|
||||
```
|
||||
|
||||
Steps:
|
||||
|
||||
1. **Registration** E drawing → layout as in §5c (`IN SEP` sensors against the
|
||||
layout separators), stored with the SHA-256 of the positions file. Warning
|
||||
when fewer than `registration_min_share` of the separators find a partner —
|
||||
a sign that layout and E drawing are different planning states.
|
||||
2. **Rules** from `e_planning.ini`, unchanged logic (spatial with maximum /
|
||||
target distance, numbering rule `MB = BG + 1`).
|
||||
3. **Slots**: each assignment goes to the slot role of the TRO that holds the
|
||||
part — key **TRO-ID + slot + role**. A `PinStore_Auto` now has a slot per
|
||||
storage line (`line1` … `lineN`, same split as `scl_context._store`);
|
||||
`separator1` and `line1` can be the same part and both get the binding.
|
||||
Parts without a slot (outfeed elements, switches — `tro_flow` does not keep
|
||||
them on the TRO yet) stay visible as `ohne_slot`.
|
||||
4. **Conveyors**: the E-planning names (`K0102`) and the layout names
|
||||
(`Kreisel3`) do not match, so every field device whose text names a conveyor
|
||||
votes for the nearest layout conveyor (distance to its bounding box, at most
|
||||
`conveyor_max_mm`). Only conveyors of the named kind vote — the bounding
|
||||
boxes overlap (storage lines reach the Kreisel). Assigned at
|
||||
`conveyor_min_votes` votes and `conveyor_min_share` share; one E conveyor per
|
||||
layout conveyor. This gives motor, motor protection and encoder per layout
|
||||
conveyor (`AnlageDocument.conveyor_for("0010-R")` → the TROs on that
|
||||
Kreisel, i.e. `xInCarouselRun`) and fills `drive.motor` /
|
||||
`drive.motorProtection` of Vario TROs.
|
||||
5. **Corrections** from `hw_overrides.ini` (last):
|
||||
`[<csv>.bindings] TRO01.separator1.sensor = BG0532` (or `= -` to clear) and
|
||||
`[<csv>.conveyors] K0102 = 0010`.
|
||||
6. **Status** per binding: `zugeordnet`; `offen` (required role without BMK →
|
||||
later `TODO(E-Planung)`; optional `?` roles are not listed); `widerspruch`
|
||||
(BMK not in the TIA import, unknown, or given to two parts); `ohne_slot`.
|
||||
Every binding carries `constant` and `address` from the TIA import.
|
||||
|
||||
Switches: `--tro NAME`, `--hw NAME` (both required, resolved against
|
||||
`%SKEL_RESULTS%`), `--rules FILE`, `--overrides FILE`, `--re-register`. Exit
|
||||
`0` also when not everything was assigned; `1` on input errors, an old
|
||||
TRO-JSON without `parts`, or an unprovable registration. Parameters:
|
||||
`cfg/parameter.ini [merge_hw_layout]`.
|
||||
|
||||
Result on Mubea (`mubea.csv` → `mubea_tro.json`, `Mubea_hw.json`): registration
|
||||
dx −151.4 / dy −696.6 mm (23/38, warning); 45 slot roles assigned (all 20
|
||||
storage-line sensors, 19 stoppers, separator sensor/stopper at TRO03/04/05/18),
|
||||
58 open, 0 contradictions; 41 assignments at outfeed elements/switch without a
|
||||
slot; conveyors **K0102 = Kreisel3 (21/23 votes), K0104 = Kreisel2 (8/8),
|
||||
K0105 = Kreisel1 (2/3)**, each with motor and motor protection. The other
|
||||
conveyors (Aufgabestation #100/#101, Vario #106–#109) are outside the CSV or
|
||||
have a single vote and stay open.
|
||||
|
||||
**Not yet:** `scl_skeleton` still reads `<csv>_eplan.json` (`--eplan`);
|
||||
switching it to `<csv>_anlage.json` is stage 4 of the concept, and only then
|
||||
`e_planning.py` becomes the thin wrapper and is removed.
|
||||
|
||||
Tests: `tests/test_merge_hw_layout.py` (sensor spatial / stopper by number,
|
||||
contradiction, open roles, part without slot, conveyor majority with
|
||||
overlapping boxes, Vario drive, too few votes, corrections incl. moving a BMK
|
||||
and clearing a conveyor, storage-line slots, missing `parts`, JSON round trip,
|
||||
fingerprint of the stored registration, CLI end to end with a real offset).
|
||||
|
||||
## 6. `tro_catalog.py` — TRO type catalog (library, no CLI)
|
||||
|
||||
The single source of truth for everything needed to generate or draw a TRO
|
||||
@@ -701,12 +846,16 @@ tro_flow.py (writes) · scl_skeleton.py (reads) · tro_annotate.py (draws)
|
||||
|---|---|
|
||||
| `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`, `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. |
|
||||
| `Slot` | A place on a TRO where hardware belongs: `slot` (`separator1`, `switch1`, `scanner1`, `drive`, `line<n>` for the storage lines of a store — 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-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). |
|
||||
| `TroDocument` | The TRO-JSON: `schema` (`sps_skel-tro-v4`), `source`, `created`, `note`, `tros`, `boundaries`, `connections`, `candidates`, `jamAreas`, `parts`, `findings`. `from_analysis()` (derives slots and jam areas, takes `parts`), `to_json()`, `from_json()`, `jam_areas_or_derived()` (a v3 file without `jamAreas` still renders), `part()` (layout part by TeileId, lane suffix ignored). |
|
||||
| `LayoutPart` | A layout part with position (`layoutId`, `kind`, `name`, `position`, `bbox`) — the target of the spatial assignment in `merge_hw_layout.py`, so that it never reads the CSV. `distance_to_box()`. Optional in v4; a file without `parts` still reads. |
|
||||
| `Binding` | One assignment hardware → slot role: `tro`, `slot`, `role`, `layoutId`, `bmk`, `constant`, `address`, `source`, `rule` (`raeumlich`/`nummer`/`mehrheit`/`hand`), `distance`, `runnerUp`, `status` (`zugeordnet`/`offen`/`widerspruch`/`ohne_slot`), `note`. |
|
||||
| `ConveyorBinding` | A conveyor of the E-planning (`K0102`) at a layout conveyor: `eplanName`, `layoutId`, `layoutName`, `votes`/`total`, `motor`, `protection`, `encoder`, `rule`, `status`, `note`. |
|
||||
| `AnlageDocument` | The plant JSON `<csv>_anlage.json` (`sps_skel-anlage-v1`): `layout` (the TRO-JSON unchanged), `registration`, `bindings`, `conveyors`, `unassigned`, `warnings`. `binding(tro, slot, role)`, `conveyor_for(layout_id)`. Written by `merge_hw_layout.py`; the future single input of `scl_skeleton`. |
|
||||
|
||||
`TroBase` and `TroCandidate` share the `position` handling (JSON `{x,y,z}`,
|
||||
`x`/`y`/`z`, `describe_position()`) through the private mixin `_Positioned`.
|
||||
|
||||
Reference in New Issue
Block a user