# Symbole und Benennungen im DXF-Layout Diese Dokumentation beschreibt, wie Symbole und Texte in der DXF-Zeichnung benannt und strukturiert sein muessen, damit sie vom System erkannt werden. --- ## 1. Sensoren / Aktoren / Motoren (Equipment) Equipment wird ueber **INSERT-Bloecke mit Attributen** erkannt. ### Block-Attribute | Attribut-Tag | Bedeutung | Beispiel | Pflicht | |---|---|---|---| | `NAME` | Geraete-ID (moderner Block) | `MA0062`, `BG3240` | Ja (oder IO+B) | | `IO` | Geraete-ID (I/O-Block, Legacy) | `MA0062` | Alternativ zu NAME | | `B` | Geraete-ID (Technik-Block, Legacy) | `MA0062` | Alternativ zu NAME | | `ARTINR` | SIVAS-Artikelnummer | `790902001` | Ja | | `KENNZEICHNUNG` | Routing-Adresse | `=A01+UH01-KF1DQ04` | Ja | | `SPS` | SPS-Praefix / Anlage | `1` | Ja (fuer Zuordnung) | | `VERW` | Verwendung/Beschreibung | `CV-M0062_0,75` | Nein | | `REALE_POSITION` | Marker fuer tatsaechliche Position | `x` | Nein | ### Geraete-Praefix (erste 2 Zeichen der ID) Welche Geraete geroutet werden, bestimmt die `cfg/BMK.cfg`: **Routing-Include** (werden geroutet): | Praefix | Typ | |---|---| | `MA` | Motoren | | `MB` | Ventile | | `QM` | Ventile/Pumpen | | `BG` | Sensoren/Naeherungsschalter | | `BP` | Naeherungsschalter | | `BX` | Mehrzweckgeraete, z.B. Scanner | | `PO` | Pneumatik-Elemente | | `SF` | Sicherheitselemente | | `PF` | Programmierbare Logik | | `GF` | Encoder | **Routing-Ignore** (Schaltschrankelemente, nicht geroutet): | Praefix | Typ | |---|---| | `FC` | Steuerungselemente | | `UH` | Unterverteiler | | `UC` | Unterverteiler | | `UZ` | Spezialverteiler | | `DI` | Digitale Eingaenge | | `DQ` | Digitale Ausgaenge | | `QA` | Ausgabegeraete | ### KENNZEICHNUNG-Format ``` =ANLAGE+VERTEILER-KARTE ``` **Beispiel:** `=A01+UH01-KF1DQ04` | Teil | Bedeutung | Beispiel | |---|---|---| | ANLAGE | Anlagengruppe | `A01` | | VERTEILER | Unterverteiler-ID | `UH01` | | KARTE | Karte/Kanal | `KF1DQ04` | Trennzeichen: `=` (Start), `+` (zwischen Anlage und Verteiler), `-` (zwischen Verteiler und Karte) ### Block-Zusammenfuehrung (Legacy Dual-Block) Bei der alten Dual-Block-Struktur werden zwei Bloecke mit gleicher ID (z.B. `MA0062`) zusammengefuehrt, wenn: - Beide innerhalb von **1000mm** Abstand liegen - Einer das `SPS`-Attribut hat, der andere nicht - Ergebnis-ID: `{id}@{sps}` (z.B. `MA0062@1`) --- ## 2. Unterverteiler (Distributoren) Unterverteiler koennen auf **zwei Arten** definiert werden: als Text oder als Symbol. ### Variante A: Text (MTEXT) Ein MTEXT-Element auf einem erlaubten Layer mit folgendem Muster: ``` -UH01 (Minus vor dem Namen) +UH01 (Plus vor dem Namen) ``` Der Text muss den Verteilernamen als Teilstring enthalten, mit `-` oder `+` davor. **Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Distributors`): - `Busverteiler-Kennzeichnung` - `0-0_ILS_Busverteiler-Kennzeichnung` - `0-0_ILS_UNTERVERTEILER` - `0-0_ILS_Unterverteiler` - `0-0_Omniflo_UNTERVERTEILER` - `0-0_Omniflo_Unterverteiler` - `UNTERVERTEILER` - `0-0_Omniflo_Busverteiler-Kennzeichnung` - `Schaltschrank-ILS` ### Variante B: Symbol (INSERT-Block) Ein INSERT-Block mit dem Attribut `NAME`, dessen Wert einem **Cabinet-Pattern** entspricht. **Cabinet-Patterns** (Regex, konfiguriert in `cfg/BMK.cfg`, Sektion `Cabinet-Pattern`): | Pattern | Beispiel-Match | Extrahierte ID | |---|---|---| | `A\d\d\+(UH0\d)` | `A01+UH01` | `UH01` | | `A\d\d\+(UC\d\d\d)` | `A01+UC001` | `UC001` | | `\+(UC\d\d\d\d)` | `+UC0101` | `UC0101` | | `\+(UH\d\d)` | `+UH01` | `UH01` | Die Klammer-Gruppe im Regex bestimmt die extrahierte Verteiler-ID. **Optionale Attribute:** - `REALE_POSITION` = `x` : Position wird aus Attribut-Position berechnet (Mittelpunkt des Markers) - `SPS` : SPS-Zuordnung --- ## 3. Tunnel Tunnel koennen ebenfalls als **Text** oder **Symbol** definiert werden. ### Variante A: Text (MTEXT) Ein MTEXT-Element auf einem erlaubten Layer mit folgendem Muster: ``` TUNNEL1-5 (Tunnelname-Laenge) TUNNEL2-10 ``` **Regex:** `(TUNNEL\d+)-(\d+)` | Teil | Bedeutung | Beispiel | |---|---|---| | Gruppe 1 | Tunnelname | `TUNNEL1` | | Gruppe 2 | Laenge in Metern | `5` | Pro Tunnel muessen genau **2 MTEXT-Elemente** vorhanden sein (Ein- und Ausgang). **Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Tunnel`): - `Busverteiler-Kennzeichnung` - `0-0_Tunnel` ### Variante B: Symbol (INSERT-Block) Ein INSERT-Block mit dem Attribut `NAME`, dessen Wert einem **Tunnel-Pattern** entspricht. **Tunnel-Patterns** (Regex, konfiguriert in `cfg/BMK.cfg`, Sektion `Tunnel-Pattern`): | Pattern | Beispiel | |---|---| | `Tunnel\d+` | `Tunnel1`, `Tunnel2` | | `Tunnel_\d+` | `Tunnel_1`, `Tunnel_2` | | `Tunnel-\d+` | `Tunnel-1`, `Tunnel-2` | | `TUNNEL\d+` | `TUNNEL1`, `TUNNEL2` | **Attribute:** | Attribut-Tag | Bedeutung | Beispiel | Pflicht | |---|---|---|---| | `NAME` | Tunnelname | `Tunnel1` | Ja | | `LAENGE` | Tunnellaenge in Metern | `5` | Nein (Default: 5) | | `REALE_POSITION` | Positionsmarker | `x` | Nein | Pro Tunnel muessen genau **2 Symbole** platziert werden (Ein- und Ausgang). **Fehler bei Tunnel-Definition:** - Weniger als 2 Positionen: Fehler `missing_tunnel` - Mehr als 2 Positionen: Fehler `overdefined_tunnel` - Fehlende Laenge: Warnung, Default 5m wird verwendet --- ## 4. Kabelpritschen (Racks) Kabelpritschen werden als **LWPOLYLINE** oder **POLYLINE** auf bestimmten Layern erkannt. Es sind keine Attribute oder Texte noetig - nur der **Layer** entscheidet. **Erlaubte Layer** (konfiguriert in `cfg/allgemein.cfg`, Sektion `GetPos-Layer_Racks`): | Layer | Beschreibung | |---|---| | `PRITSCHE_100-60` | Standard 100x60 | | `PRITSCHE_100-60-SCHRAFF` | Standard 100x60 schraffiert | | `PRITSCHE_200-60` | Standard 200x60 | | `PRITSCHE_200-60_ILS` | ILS 200x60 | | `PRITSCHE_200-60_OMNIFLO` | Omniflo 200x60 | | `0-0_ILS_PRITSCHE_200-60_storage_Level1` | ILS Storage Level 1 | | `0-0_ILS_PRITSCHE_200-60_storage_Level2` | ILS Storage Level 2 | | `0-0_ILS_PRITSCHE_200-60_Workstation` | ILS Workstation | | `0-0_ILS_Pritsche_200-60_AMR` | ILS AMR | | `0-0_ILS_PRITSCHE_200-60_Highway` | ILS Highway | | `0-0_ILS_Pritsche_200-60_Inbound` | ILS Inbound | | `0-0_Omniflo_Pritsche_200-60_Workstation-Outbound` | Omniflo Workstation Outbound | | `0-0_Omniflo_Pritsche_200-60_outbound` | Omniflo Outbound | | `0-0_Omniflo_Pritsche_200-60_AMR` | Omniflo AMR | | `0-0_Omniflo_Pritsche_200-60_Highway` | Omniflo Highway | **Validierung:** Wenn die Z-Koordinaten aller Racks mehr als 2000mm auseinanderliegen, wird eine Warnung ausgegeben (Schwellwert konfigurierbar in `cfg/allgemein.cfg`, Sektion `Racks`, Schluessel `MaximalTotalHeightDifferences`). --- ## 5. Zusammenfassung: Was muss im Layout vorhanden sein? | Element | Erkennungsart | Mindestangaben | |---|---|---| | **Sensor/Motor** | INSERT-Block | `NAME` (oder `IO`+`B`), `ARTINR`, `KENNZEICHNUNG` | | **Unterverteiler** | MTEXT **oder** INSERT-Block | Text: `-UH01` auf richtigem Layer / Block: `NAME` = `A01+UH01` | | **Tunnel** | MTEXT **oder** INSERT-Block | Text: `TUNNEL1-5` (2x) / Block: `NAME` = `Tunnel1`, `LAENGE` = `5` (2x) | | **Kabelpritsche** | LWPOLYLINE/POLYLINE | Auf richtigem Layer gezeichnet | --- ## 6. Funktionsreferenz (getpositions.py) Uebersicht der zentralen Funktionen, die die Erkennung durchfuehren. ### Sensoren / Equipment | Funktion | Zeile | Aufgabe | |---|---|---| | `get_attributes_of_insert(d_insert, d_pos)` | ~76 | Extrahiert ID, Typ und Position aus einem einzelnen INSERT-Block. Prueft zuerst `IO`, dann `NAME`, dann `B`. Bei `REALE_POSITION='x'` wird der Mittelpunkt aus Marker-Geometrie berechnet (Breite/Hoehe aus Config). Gibt `(dict, id, typ)` zurueck. | | `extract_input_positions(all_inserts, all_positions, error_collector)` | ~221 | Hauptfunktion: Iteriert ueber alle Bloecke, ruft `get_attributes_of_insert()` auf, trennt Sensoren von Schaltschrankelementen anhand des Praefixes. Fuehrt Block-Zusammenfuehrung via `CompareBuffer` durch. | | `allocate_blocks_together(...)` | ~329 | Fuehrt die Zusammenfuehrung von Dual-Bloecken durch (Legacy). Nutzt `CompareBuffer.positions_are_close()` mit 1000mm Toleranz. | ### Unterverteiler | Funktion | Zeile | Aufgabe | |---|---|---| | `get_subdistributor_positions_from_entities(entities, dist2sensors)` | ~547 | **Text-Erkennung:** Iteriert ueber MTEXT-Entities auf erlaubten Layern. Sucht nach `-{name}` oder `+{name}` im Text. Gibt `{distname: (x, y)}` zurueck. | | `get_subdistributor_positions_from_symbols(all_inserts, all_positions, dist2sensors)` | ~472 | **Symbol-Erkennung:** Iteriert ueber alle INSERT-Bloecke mit `NAME`-Attribut. Prueft NAME gegen Cabinet-Patterns aus BMK.cfg. Ruft `get_subdistributor_position_of_symbol()` fuer die Positionsextraktion auf. | | `get_subdistributor_position_of_symbol(d_insert, d_pos)` | ~413 | Hilfsfunktion: Extrahiert Position aus einem einzelnen Unterverteiler-Block. Beruecksichtigt `REALE_POSITION` fuer Mittelpunktberechnung. Gibt `(dict, id)` zurueck. | ### Tunnel | Funktion | Zeile | Aufgabe | |---|---|---| | `get_tunnel_positions_from_entities(entities)` | ~574 | **Text-Erkennung:** Iteriert ueber MTEXT-Entities auf erlaubten Layern. Regex `(TUNNEL\d+)-(\d+)` extrahiert Name und Laenge. Sammelt alle Positionen pro Tunnelname. | | `get_tunnel_positions_from_symbols(all_inserts, all_positions, error_collector)` | ~493 | **Symbol-Erkennung:** Iteriert ueber alle INSERT-Bloecke mit `NAME`-Attribut. Prueft NAME gegen Tunnel-Patterns aus BMK.cfg. Liest `LAENGE`-Attribut (Default: 5m). Warnung bei fehlender Laenge. | | `get_tunnel_position_of_symbol(d_insert, d_pos)` | ~441 | Hilfsfunktion: Extrahiert Position und Laenge aus einem einzelnen Tunnel-Block. Beruecksichtigt `REALE_POSITION`. Gibt `(dict, id)` zurueck. | ### Kabelpritschen | Funktion | Zeile | Aufgabe | |---|---|---| | `get_rack_positions(msp)` | ~614 | Sucht LWPOLYLINE und POLYLINE auf erlaubten Layern. Nummeriert Racks automatisch (`Rack_1`, `Rack_2`, ...). Delegiert an `handle_lwpolyline()` bzw. `handle_polyline()`. | | `handle_lwpolyline(entity, rack_key, ret)` | ~636 | Verarbeitet 2D-Polylinien. Z-Wert kommt global aus `elevation`. | | `handle_polyline(entity, rack_key, ret)` | ~644 | Verarbeitet 3D-Polylinien. Jeder Vertex hat individuelle x/y/z-Koordinaten. | | `check_rack_z_coordinates(res_racks, error_collector, config)` | ~654 | Validierung: Prueft ob Z-Koordinaten-Differenz den Schwellwert uebersteigt. | ### Erkennungsablauf im Hauptprogramm ``` 1. DXF laden: get_dxf_file() -> msp 2. Alle Bloecke extrahieren: attribs_to_dicts(msp) -> all_inserts, all_positions 3. Sensoren: extract_input_positions(all_inserts, all_positions) 4. Mappings: create_mappings(res_sens) -> sensor2unterverteiler 5. Unterverteiler (Text): get_subdistributor_positions_from_entities(msp.query('MTEXT')) 6. Unterverteiler (Symbol): get_subdistributor_positions_from_symbols(all_inserts, all_positions) 7. Tunnel (Text): get_tunnel_positions_from_entities(msp.query('MTEXT')) 8. Tunnel (Symbol): get_tunnel_positions_from_symbols(all_inserts, all_positions) 9. Racks: get_rack_positions(msp) ``` --- ## 7. Konfigurationsdateien | Datei | Inhalt | |---|---| | `cfg/allgemein.cfg` | Layer-Zuordnungen, Geometrie-Parameter, Toleranzen | | `cfg/BMK.cfg` | Geraete-Praefixe, Cabinet-Patterns, Tunnel-Patterns, Kabelzuordnungen | | `cfg/kabel.cfg` | SIVAS-Artikelnummern nach Kabeltyp und Laenge | | `cfg/bezeichner.cfg` | Artikelnummer-Beschreibungen |