Files
sps_skel/doc/Konzept_Layout_Hardware_SCL.md
T
Michael StanglandClaude Opus 5.5 ef57a2218e Konzept: Staubereiche nach Separator, SCL-Namen nach UH01-UH05
- Kennung der Staubereiche in der JSON nach ihrem Separator (J<Sep>,
  wie im Mubea-Layout J1024 fuer Sep1024)
- SCL-Name festgelegt auf den Standard UH01-UH05:
  "DB_JamArea<NNNN>".stJam<NNNN>_<k> (Foerderernummer, Reihenfolge
  entlang des Materialflusses)
- Separator- und Foerderernummern wie TRO-IDs in der ID-Datei

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:51:04 +02:00

17 KiB
Raw Blame History

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

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.

    "slots": [
      {"slot": "separator1", "layoutId": "0008", "roles": ["sensor", "stopper", "jamSensor?", "partSensor?"]},
      {"slot": "switch1",    "layoutId": "0037", "exit": 3, "roles": ["valve", "exitSensor?"]},
      {"slot": "drive",      "layoutId": "0002", "roles": ["carouselRun"]}
    ]
    

    Die Slots ergeben sich aus dem Katalogtyp (items) und der Topologie; ? = optional, fehlt das Gerät, wird der zugehörige xPlugged*-Schalter FALSE.

  • Staubereiche als eigene Liste jamAreas[]: ein Staubereich je TRO-Eingang, mit allen Vorgängern, dem Förderer, auf dem er liegt, und seiner Lage auf dem Förderer (siehe "Staubereiche" unten). Heute nur abgeleitet beim Rendern (scl_context.SclJam). Dabei korrigieren: scl_skeleton erzeugt heute je Vorgänger einen eigenen Eingang (arInOutJamEntr1, …Entr2); in den Referenzen laufen mehrere Vorgänger in einem Staubereich zusammen, der TRO hat einen Eingang (Ausnahme 2Sep1Swi, PinStore).

  • Weitere Layout-Angaben: xIsBorner, Vorfahrt ja/nein, tragender Förderer mit Rolle (heute hosts ohne Rolle), Längen für tConvEmpty und Staulängen.

  • Ableitungen aus scl_context nach tro_flow/model verschieben, damit die JSON sie trägt und nicht erst das Rendern sie kennt.

  • Schema sps_skel-tro-v4.

2. Neues Skript hw_import.py (Stufe 2)

  • Liest TIA-Import (PLC Tags + Constants), EA-Liste, WSCAD-Import und optional positionsdraw.json.
  • Schreibt ein neues Modell HardwareDocument:
    • Geräte je BMK: Adresse, Index-Konstante (cInBG3306), Kommentar, VERW, Steuerung, Station/Schrank, Position (falls vorhanden);
    • globale Variablen: alle Tags und Konstanten, Motor↔Motorschutz-Paare, Taster, Not-Halt.
  • Prüft die Exporte gegeneinander: BMK fehlt in einer Liste, doppelte BMK, Adresse ohne Tag.
  • Übernimmt aus e_planning.py: load_positionsdraw, EDevice, pair_drives.
  • Erste Quelle: der TIA-Import, weil er Namen und Konstanten 1:1 liefert und die spätere Prüfung des SCL ermöglicht.

3. Neues Skript hw_assign.py (Stufe 3)

  • Eingabe: <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

    "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.

Vorschlag:

  • Eine versionierte ID-Datei je Anlage, z. B. cfg/<anlage>_tro_ids.ini: je TRO die ID und die Lage seines Anker-Separators (x, y in mm), optional ein Name. Von tro_flow angelegt, von den SPS-Programmierern umbenannt.

    ; Beispiel, Werte erfunden
    [mubea]
    TRO107 = 12450.0, 3310.0   ; Kreisel 2 vor Beladung
    TRO108 = 13250.0, 3310.0
    
  • Standard (IDs halten): tro_flow liest die ID-Datei und findet jeden TRO über die Lage des Anker-Separators wieder (Toleranz einstellbar). Gefundene TROs behalten ihre ID. Neue TROs bekommen eine vorläufige ID (nächste freie Nummer entlang des Materialflusses) und stehen im Bericht; weggefallene TROs stehen im Bericht, ihre ID wird nicht automatisch wiederverwendet.

  • Programmschalter --renumber (frühe Phase): alle IDs neu entlang des Materialflusses vergeben und die ID-Datei neu schreiben.

  • Dadurch werden auch die Abschnitte [<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):

"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.
  2. Slots und jamAreas in die TRO-JSON (Umbau 1), ein Eingangs-Staubereich je TRO — ohne Slots hat die Zuordnung kein Ziel.
  3. hw_import mit dem TIA-Import als erster Quelle.
  4. hw_assign mit der räumlichen Logik aus e_planning.py; e_planning.py als Übergangshülle.
  5. scl_skeleton auf <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; Verhalten, wenn ein Separator weiter verschoben wurde (Vorschlag: als "neu" + "weggefallen" melden, der Programmierer übernimmt die ID von Hand).
  • Korrekturen in BricsCAD oder in der JSON: zurückgestellt.