Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/kabellaengen
This commit is contained in:
+17
-1
@@ -64,7 +64,23 @@
|
||||
827072013 = STATISCHE TROLLEYABFRAGE L=700 FÜR AP110
|
||||
827072111 = Traversenabfrage AP110 mit Lichttaster
|
||||
827072112 = Traversenabfrage ST kpl. mit Lichttaster
|
||||
|
||||
827072113 = Traversenabfrage KF kpl. mit Lichttaster
|
||||
829422026 = INDUKT. SENSOR LP KPL.
|
||||
720002011 = Sensor Induk. M18 8mm bündig/PNP-NO/ST M12
|
||||
703001017 = HILFSCHALTER MIT ZUGFEDERANSCHLUSS F. 3RV2011
|
||||
725000161 = 4G1,5 mm², Steuerleitung Halogenfrei
|
||||
725000163 = 7G1,5 mm², Steuerleitung Halogenfrei
|
||||
725000164 = 12G1,5 mm², Steuerleitung Halogenfrei
|
||||
790000057 = Sirius act Tableau 4 F "LM-GN+PDT-GE+LDT-BL+NA"
|
||||
790801501 = Busverteiler kpl. ET 200SP DI+DQ, Exact -BG
|
||||
790820400 = Unterverteiler 1 800x2100x400 -BG
|
||||
790821106 = SCHALTSCHRANK 2000X2100X400 (HGF) -BG
|
||||
829434314 = PINABFRAGE LI MECHANISCH KPL.
|
||||
829534306 = Camera DM280 m. Halter (ILS) - BG
|
||||
829624040 = UMLENKFLANSCH-c 800 MIT INKEMENTALGEBER KPL.
|
||||
929012655 = DRUCKSCHALTER PM1-M3-G014
|
||||
200000375 = Halter mit Sensor für Abfrage VARIO Finger
|
||||
829434306 = INKREMENTALGEBER 800 5V KPL.
|
||||
|
||||
[Missing]
|
||||
827072111 =
|
||||
|
||||
+150
-12
@@ -75,7 +75,12 @@ def add_polyline(msp, points:Polyline, dxf_attribs):
|
||||
pline.rgb = (255, 128, 0)
|
||||
|
||||
def new_dxf(plines, out_path):
|
||||
""" creates a new dxf file with a polyline inside which is created by the given json file
|
||||
"""
|
||||
Erstellt eine neue DXF-Datei mit den gegebenen Polylinien und speichert sie unter dem angegebenen Pfad.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten, die gezeichnet werden sollen.
|
||||
out_path (str): Der Pfad, unter dem die neue DXF-Datei gespeichert wird.
|
||||
"""
|
||||
doc = ezdxf.new('R2018', setup=True)
|
||||
doc.header['$INSUNITS'] = 4 # Millimeter
|
||||
@@ -88,7 +93,12 @@ def new_dxf(plines, out_path):
|
||||
print("Cable-Routes exported to new dxf-file")
|
||||
|
||||
def modify_original_dxf(plines, originaldxf):
|
||||
""" adds new layer to original .dxf-file that contains cables
|
||||
"""
|
||||
Fügt einer bestehenden DXF-Datei einen neuen Layer mit Kabeln hinzu und speichert das Ergebnis.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten, die gezeichnet werden sollen.
|
||||
originaldxf (str): Pfad zur bestehenden DXF-Datei, die modifiziert werden soll.
|
||||
"""
|
||||
print("adding cables into original .dxf ..")
|
||||
|
||||
@@ -100,6 +110,13 @@ def modify_original_dxf(plines, originaldxf):
|
||||
|
||||
|
||||
def draw_cables(plines, doc):
|
||||
"""
|
||||
Zeichnet alle Kabel-Polylinien in das DXF-Dokument auf einen eigenen Layer.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
doc (ezdxf.document.Drawing): Das zu bearbeitende DXF-Dokument.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||
cable_layer = f"cables_{timestamp}"
|
||||
@@ -116,6 +133,13 @@ def draw_cables(plines, doc):
|
||||
add_polyline(msp, pl, dxfattribs_cable)
|
||||
|
||||
def draw_racks(plines, doc):
|
||||
"""
|
||||
Zeichnet die Racks als 3D-Polylinien und platziert Rack-Namen als Text im DXF-Dokument.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
doc (ezdxf.document.Drawing): Das zu bearbeitende DXF-Dokument.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||
rack_layer = f"racks_{timestamp}"
|
||||
@@ -186,6 +210,13 @@ def find_close_key(pos2sensors, x, y, tolerance=10): # !!! Toleranz nicht
|
||||
return None
|
||||
|
||||
def draw_sensors(plines, doc):
|
||||
"""
|
||||
Zeichnet die Sensoren als Textobjekte an den Endpunkten der Kabel und gruppiert sie ggf. gestaffelt.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
doc (ezdxf.document.Drawing): Das zu bearbeitende DXF-Dokument.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||
sensor_layer = f"sensors_{timestamp}"
|
||||
@@ -220,6 +251,13 @@ def draw_sensors(plines, doc):
|
||||
text.set_placement(placement_info["placement"])
|
||||
|
||||
def draw_subdists(plines, doc):
|
||||
"""
|
||||
Zeichnet die Unterverteiler (Subdistributoren) als Textobjekte an den Startpunkten der Kabel.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
doc (ezdxf.document.Drawing): Das zu bearbeitende DXF-Dokument.
|
||||
"""
|
||||
msp = doc.modelspace()
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||
subdist_layer = f"subdists_{timestamp}"
|
||||
@@ -297,6 +335,15 @@ def _calculate_text_placement(pt1, pt2, text_type='sensor', item_index=0, total_
|
||||
}
|
||||
|
||||
def model_from_json(json_file):
|
||||
"""
|
||||
Lädt die Polylinien- und Geometriedaten aus einer JSON-Datei und gibt ein Polylines-Objekt zurück.
|
||||
|
||||
Args:
|
||||
json_file (str): Pfad zur JSON-Datei.
|
||||
|
||||
Returns:
|
||||
Polylines: Das geladene Polylinien-Objekt.
|
||||
"""
|
||||
with open(json_file, encoding='utf-8') as fh:
|
||||
data = json.load(fh)
|
||||
|
||||
@@ -307,6 +354,15 @@ def model_from_json(json_file):
|
||||
return plines
|
||||
|
||||
def parse_sensors_from_json(positions_json):
|
||||
"""
|
||||
Liest Sensordaten aus einer JSON-Datei und gibt ein Dictionary mit Sensorobjekten zurück.
|
||||
|
||||
Args:
|
||||
positions_json (str): Pfad zur JSON-Datei mit Sensorpositionen.
|
||||
|
||||
Returns:
|
||||
dict: Dictionary mit Sensorname als Key und Sensorobjekt als Value.
|
||||
"""
|
||||
with open(positions_json, encoding='utf-8') as fh:
|
||||
data = json.load(fh)
|
||||
|
||||
@@ -321,6 +377,16 @@ def parse_sensors_from_json(positions_json):
|
||||
return sensors
|
||||
|
||||
def get_all_artnrs(plines: Polylines, sens2cable: dict) -> set:
|
||||
"""
|
||||
Sammelt alle verwendeten Artikelnummern aus den Polylinien und der Sensor-Kabel-Zuordnung.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
sens2cable (dict): Mapping von Sensor-IDs zu Kabel-Artikelnummern.
|
||||
|
||||
Returns:
|
||||
set: Menge aller gefundenen Artikelnummern.
|
||||
"""
|
||||
all_artnrs = set()
|
||||
for pl in plines.kabel:
|
||||
if pl.s_artinr:
|
||||
@@ -333,6 +399,12 @@ def get_all_artnrs(plines: Polylines, sens2cable: dict) -> set:
|
||||
return all_artnrs
|
||||
|
||||
def mark_missings(all_artnrs):
|
||||
"""
|
||||
Markiert fehlende Artikelnummern im Bezeichner-Config, falls sie nicht vorhanden sind.
|
||||
|
||||
Args:
|
||||
all_artnrs (set): Menge aller verwendeten Artikelnummern.
|
||||
"""
|
||||
if "Sivasnummern" not in bezeichner_cfg:
|
||||
bezeichner_cfg["Sivasnummern"] = {}
|
||||
if "Missing" not in bezeichner_cfg:
|
||||
@@ -344,7 +416,13 @@ def mark_missings(all_artnrs):
|
||||
|
||||
def write_excel_from_json(plines: Polylines, sens2cable: dict, outpath: str, with_bom=True):
|
||||
"""
|
||||
Steuert die Erstellung der Excel-Reports (Kabelübersicht und Stückliste).
|
||||
Erstellt Excel-Reports (Kabelübersicht, Fehlerlisten, Stückliste) aus den Polylinien- und Zuordnungsdaten.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
sens2cable (dict): Mapping von Sensor-IDs zu Kabel-Artikelnummern.
|
||||
outpath (str): Pfad zur Ausgabedatei.
|
||||
with_bom (bool, optional): Ob zusätzlich eine Stückliste (BOM) erzeugt werden soll. Default: True.
|
||||
"""
|
||||
# 1. Daten aggregieren und für die Reports vorbereiten
|
||||
processed_data = _process_cable_data(plines, sens2cable)
|
||||
@@ -376,8 +454,14 @@ def _get_sivas_name(artnr, bezeichner_cfg):
|
||||
|
||||
def _process_cable_data(plines: Polylines, sens2cable: dict):
|
||||
"""
|
||||
Verarbeitet die Kabeldaten und aggregiert sie für die Excel-Ausgabe.
|
||||
Gibt mehrere Dictionaries mit zusammengefassten Daten zurück.
|
||||
Aggregiert und bereitet die Kabeldaten für die Excel-Ausgabe auf.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
sens2cable (dict): Mapping von Sensor-IDs zu Kabel-Artikelnummern.
|
||||
|
||||
Returns:
|
||||
dict: Verschiedene aggregierte Auswertungen für die Excel-Ausgabe.
|
||||
"""
|
||||
# Globale Zusammenfassungen
|
||||
artnr_to_stückware_count = defaultdict(int)
|
||||
@@ -431,7 +515,15 @@ def _process_cable_data(plines: Polylines, sens2cable: dict):
|
||||
}
|
||||
|
||||
def _create_cable_list_sheet(ws, plines, sens2cable, bezeichner_cfg):
|
||||
"""Erstellt das Arbeitsblatt 'Length by ID'."""
|
||||
"""
|
||||
Erstellt das Arbeitsblatt 'Length by ID' mit allen Kabeln und deren Längen.
|
||||
|
||||
Args:
|
||||
ws (Worksheet): Das Excel-Arbeitsblatt.
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
sens2cable (dict): Mapping von Sensor-IDs zu Kabel-Artikelnummern.
|
||||
bezeichner_cfg (ConfigParser): Konfiguration mit Artikelnummern-Namen.
|
||||
"""
|
||||
ws.title = "Length by ID"
|
||||
ws.append(["Cable-ID", "True Length (m)", "Cable-ArtNr", "Cable-Name (short)"])
|
||||
ws.column_dimensions['A'].width = 18
|
||||
@@ -446,7 +538,13 @@ def _create_cable_list_sheet(ws, plines, sens2cable, bezeichner_cfg):
|
||||
ws.append([pl.id, length, artnr, cable_name])
|
||||
|
||||
def _create_cable_summary_sheet(ws, processed_data):
|
||||
"""Erstellt das Arbeitsblatt 'Cables SIVAS'."""
|
||||
"""
|
||||
Erstellt das Arbeitsblatt 'Cables SIVAS' mit einer Zusammenfassung der Kabel nach Artikelnummer.
|
||||
|
||||
Args:
|
||||
ws (Worksheet): Das Excel-Arbeitsblatt.
|
||||
processed_data (dict): Aggregierte Kabeldaten.
|
||||
"""
|
||||
ws.title = "Cables SIVAS"
|
||||
ws.append(["Cable-ArtNr", "Amount (pcs)", "Cumm. Length (m)"])
|
||||
ws.column_dimensions['A'].width = 20
|
||||
@@ -465,7 +563,13 @@ def _create_cable_summary_sheet(ws, processed_data):
|
||||
])
|
||||
|
||||
def _create_rack_lengths_sheet(ws, plines):
|
||||
"""Erstellt das Arbeitsblatt 'Rack-Lengths'."""
|
||||
"""
|
||||
Erstellt das Arbeitsblatt 'Rack-Lengths' mit den Längen der Racks.
|
||||
|
||||
Args:
|
||||
ws (Worksheet): Das Excel-Arbeitsblatt.
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
"""
|
||||
ws.title = "Rack-Lengths"
|
||||
ws.append(["Rack-ID", "Length (m)"])
|
||||
ws.column_dimensions['A'].width = 18
|
||||
@@ -479,7 +583,13 @@ def _create_rack_lengths_sheet(ws, plines):
|
||||
ws.append([rackname, rack_geom.length])
|
||||
|
||||
def _create_error_sheets(wb, plines):
|
||||
"""Erstellt die Arbeitsblätter für alle aufgetretenen Fehler."""
|
||||
"""
|
||||
Erstellt die Arbeitsblätter für alle aufgetretenen Fehler (Equipment-Connection, Routing, Attribute).
|
||||
|
||||
Args:
|
||||
wb (Workbook): Das Excel-Workbook.
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
"""
|
||||
# Sheet: ERR-Equipment-Connection
|
||||
if plines.errors_sensors or plines.errors_dists:
|
||||
ws = wb.create_sheet("ERR-Equipment-Connection")
|
||||
@@ -520,7 +630,14 @@ def _create_error_sheets(wb, plines):
|
||||
ws.append([sname, err_msg])
|
||||
|
||||
def _create_bom_workbook(outpath, processed_data, bezeichner_cfg):
|
||||
"""Erstellt eine separate Excel-Arbeitsmappe für die Stückliste (BOM)."""
|
||||
"""
|
||||
Erstellt eine separate Excel-Arbeitsmappe für die Stückliste (BOM) und speichert sie ab.
|
||||
|
||||
Args:
|
||||
outpath (str): Basis-Pfad für die Ausgabedatei.
|
||||
processed_data (dict): Aggregierte Kabel- und Sensor-Daten.
|
||||
bezeichner_cfg (ConfigParser): Konfiguration mit Artikelnummern-Namen.
|
||||
"""
|
||||
wb = Workbook()
|
||||
|
||||
# Daten aus dem verarbeiteten Dictionary extrahieren
|
||||
@@ -600,6 +717,13 @@ def check_file_in_work(work_dir, filename):
|
||||
return (mypath, fexists)
|
||||
|
||||
def copy_layers_into_dxf_by_filter(dxf_source: ezdxf.document.Drawing, dxf_target:ezdxf.document.Drawing):
|
||||
"""
|
||||
Kopiert bestimmte Layer (nach Filter) von einer Quell-DXF in eine Ziel-DXF.
|
||||
|
||||
Args:
|
||||
dxf_source (ezdxf.document.Drawing): Quell-DXF-Dokument.
|
||||
dxf_target (ezdxf.document.Drawing): Ziel-DXF-Dokument.
|
||||
"""
|
||||
|
||||
msp_source = dxf_source.modelspace()
|
||||
msp_target = dxf_target.modelspace()
|
||||
@@ -659,8 +783,13 @@ def copy_layers_into_dxf_by_filter(dxf_source: ezdxf.document.Drawing, dxf_targe
|
||||
def get_cable_artnr(section, length):
|
||||
"""
|
||||
Sucht in der angegebenen Config-Section die passende Kabel-Artikelnr. für die gegebene Länge.
|
||||
Übergibt bei Treffer True, artnr
|
||||
bei Fehler: False, errmsg
|
||||
|
||||
Args:
|
||||
section (str): Name der Kabel-Section in der Config.
|
||||
length (float): Kabellänge in Metern.
|
||||
|
||||
Returns:
|
||||
tuple: (True, artnr) bei Erfolg, (False, Fehlermeldung) bei Fehler.
|
||||
"""
|
||||
# Existiert über BMK vergebene Kabel-Kennzeichnung in kabel.cfg?
|
||||
if section not in cable_cfg:
|
||||
@@ -676,6 +805,15 @@ def get_cable_artnr(section, length):
|
||||
return False, f"Kabel länger als max. Kabellänge in Sektion '{section}'"
|
||||
|
||||
def map_sensor_to_cable_cfg(plines):
|
||||
"""
|
||||
Ordnet jedem Sensor/Kabel die passende Kabel-Artikelnummer gemäß BMK-Config und Kabel-Config zu.
|
||||
|
||||
Args:
|
||||
plines (Polylines): Die Polylinien- und Geometriedaten.
|
||||
|
||||
Returns:
|
||||
dict: Mapping von Kabel-IDs zu Artikelnummern.
|
||||
"""
|
||||
sens2cable = defaultdict(list)
|
||||
|
||||
mapping = config_BMK["Cable-Mapping"]
|
||||
|
||||
Reference in New Issue
Block a user