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:
Samer AyadiandClaude Opus 5.5 committed 2026-10-15 16:16:10 +02:00
1 parent c4122b4497
commit df24cf5adb
21 files changed
+3226 -442

No files matched your search

+143 -14
View File
@@ -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).