DocStrings bei "komplexeren" Methoden hinzugefügt
This commit is contained in:
+150
-12
@@ -75,7 +75,12 @@ def add_polyline(msp, points:Polyline, dxf_attribs):
|
|||||||
pline.rgb = (255, 128, 0)
|
pline.rgb = (255, 128, 0)
|
||||||
|
|
||||||
def new_dxf(plines, out_path):
|
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 = ezdxf.new('R2018', setup=True)
|
||||||
draw_cables(plines, doc)
|
draw_cables(plines, doc)
|
||||||
@@ -87,7 +92,12 @@ def new_dxf(plines, out_path):
|
|||||||
print("Cable-Routes exported to new dxf-file")
|
print("Cable-Routes exported to new dxf-file")
|
||||||
|
|
||||||
def modify_original_dxf(plines, originaldxf):
|
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 ..")
|
print("adding cables into original .dxf ..")
|
||||||
|
|
||||||
@@ -99,6 +109,13 @@ def modify_original_dxf(plines, originaldxf):
|
|||||||
|
|
||||||
|
|
||||||
def draw_cables(plines, doc):
|
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()
|
msp = doc.modelspace()
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||||
cable_layer = f"cables_{timestamp}"
|
cable_layer = f"cables_{timestamp}"
|
||||||
@@ -115,6 +132,13 @@ def draw_cables(plines, doc):
|
|||||||
add_polyline(msp, pl, dxfattribs_cable)
|
add_polyline(msp, pl, dxfattribs_cable)
|
||||||
|
|
||||||
def draw_racks(plines, doc):
|
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()
|
msp = doc.modelspace()
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||||
rack_layer = f"racks_{timestamp}"
|
rack_layer = f"racks_{timestamp}"
|
||||||
@@ -185,6 +209,13 @@ def find_close_key(pos2sensors, x, y, tolerance=10): # !!! Toleranz nicht
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def draw_sensors(plines, doc):
|
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()
|
msp = doc.modelspace()
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||||
sensor_layer = f"sensors_{timestamp}"
|
sensor_layer = f"sensors_{timestamp}"
|
||||||
@@ -219,6 +250,13 @@ def draw_sensors(plines, doc):
|
|||||||
text.set_placement(placement_info["placement"])
|
text.set_placement(placement_info["placement"])
|
||||||
|
|
||||||
def draw_subdists(plines, doc):
|
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()
|
msp = doc.modelspace()
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
||||||
subdist_layer = f"subdists_{timestamp}"
|
subdist_layer = f"subdists_{timestamp}"
|
||||||
@@ -296,6 +334,15 @@ def _calculate_text_placement(pt1, pt2, text_type='sensor', item_index=0, total_
|
|||||||
}
|
}
|
||||||
|
|
||||||
def model_from_json(json_file):
|
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:
|
with open(json_file, encoding='utf-8') as fh:
|
||||||
data = json.load(fh)
|
data = json.load(fh)
|
||||||
|
|
||||||
@@ -306,6 +353,15 @@ def model_from_json(json_file):
|
|||||||
return plines
|
return plines
|
||||||
|
|
||||||
def parse_sensors_from_json(positions_json):
|
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:
|
with open(positions_json, encoding='utf-8') as fh:
|
||||||
data = json.load(fh)
|
data = json.load(fh)
|
||||||
|
|
||||||
@@ -320,6 +376,16 @@ def parse_sensors_from_json(positions_json):
|
|||||||
return sensors
|
return sensors
|
||||||
|
|
||||||
def get_all_artnrs(plines: Polylines, sens2cable: dict) -> set:
|
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()
|
all_artnrs = set()
|
||||||
for pl in plines.kabel:
|
for pl in plines.kabel:
|
||||||
if pl.s_artinr:
|
if pl.s_artinr:
|
||||||
@@ -332,6 +398,12 @@ def get_all_artnrs(plines: Polylines, sens2cable: dict) -> set:
|
|||||||
return all_artnrs
|
return all_artnrs
|
||||||
|
|
||||||
def mark_missings(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:
|
if "Sivasnummern" not in bezeichner_cfg:
|
||||||
bezeichner_cfg["Sivasnummern"] = {}
|
bezeichner_cfg["Sivasnummern"] = {}
|
||||||
if "Missing" not in bezeichner_cfg:
|
if "Missing" not in bezeichner_cfg:
|
||||||
@@ -343,7 +415,13 @@ def mark_missings(all_artnrs):
|
|||||||
|
|
||||||
def write_excel_from_json(plines: Polylines, sens2cable: dict, outpath: str, with_bom=True):
|
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
|
# 1. Daten aggregieren und für die Reports vorbereiten
|
||||||
processed_data = _process_cable_data(plines, sens2cable)
|
processed_data = _process_cable_data(plines, sens2cable)
|
||||||
@@ -375,8 +453,14 @@ def _get_sivas_name(artnr, bezeichner_cfg):
|
|||||||
|
|
||||||
def _process_cable_data(plines: Polylines, sens2cable: dict):
|
def _process_cable_data(plines: Polylines, sens2cable: dict):
|
||||||
"""
|
"""
|
||||||
Verarbeitet die Kabeldaten und aggregiert sie für die Excel-Ausgabe.
|
Aggregiert und bereitet die Kabeldaten für die Excel-Ausgabe auf.
|
||||||
Gibt mehrere Dictionaries mit zusammengefassten Daten zurück.
|
|
||||||
|
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
|
# Globale Zusammenfassungen
|
||||||
artnr_to_stückware_count = defaultdict(int)
|
artnr_to_stückware_count = defaultdict(int)
|
||||||
@@ -430,7 +514,15 @@ def _process_cable_data(plines: Polylines, sens2cable: dict):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _create_cable_list_sheet(ws, plines, sens2cable, bezeichner_cfg):
|
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.title = "Length by ID"
|
||||||
ws.append(["Cable-ID", "True Length (m)", "Cable-ArtNr", "Cable-Name (short)"])
|
ws.append(["Cable-ID", "True Length (m)", "Cable-ArtNr", "Cable-Name (short)"])
|
||||||
ws.column_dimensions['A'].width = 18
|
ws.column_dimensions['A'].width = 18
|
||||||
@@ -445,7 +537,13 @@ def _create_cable_list_sheet(ws, plines, sens2cable, bezeichner_cfg):
|
|||||||
ws.append([pl.id, length, artnr, cable_name])
|
ws.append([pl.id, length, artnr, cable_name])
|
||||||
|
|
||||||
def _create_cable_summary_sheet(ws, processed_data):
|
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.title = "Cables SIVAS"
|
||||||
ws.append(["Cable-ArtNr", "Amount (pcs)", "Cumm. Length (m)"])
|
ws.append(["Cable-ArtNr", "Amount (pcs)", "Cumm. Length (m)"])
|
||||||
ws.column_dimensions['A'].width = 20
|
ws.column_dimensions['A'].width = 20
|
||||||
@@ -464,7 +562,13 @@ def _create_cable_summary_sheet(ws, processed_data):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def _create_rack_lengths_sheet(ws, plines):
|
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.title = "Rack-Lengths"
|
||||||
ws.append(["Rack-ID", "Length (m)"])
|
ws.append(["Rack-ID", "Length (m)"])
|
||||||
ws.column_dimensions['A'].width = 18
|
ws.column_dimensions['A'].width = 18
|
||||||
@@ -478,7 +582,13 @@ def _create_rack_lengths_sheet(ws, plines):
|
|||||||
ws.append([rackname, rack_geom.length])
|
ws.append([rackname, rack_geom.length])
|
||||||
|
|
||||||
def _create_error_sheets(wb, plines):
|
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
|
# Sheet: ERR-Equipment-Connection
|
||||||
if plines.errors_sensors or plines.errors_dists:
|
if plines.errors_sensors or plines.errors_dists:
|
||||||
ws = wb.create_sheet("ERR-Equipment-Connection")
|
ws = wb.create_sheet("ERR-Equipment-Connection")
|
||||||
@@ -519,7 +629,14 @@ def _create_error_sheets(wb, plines):
|
|||||||
ws.append([sname, err_msg])
|
ws.append([sname, err_msg])
|
||||||
|
|
||||||
def _create_bom_workbook(outpath, processed_data, bezeichner_cfg):
|
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()
|
wb = Workbook()
|
||||||
|
|
||||||
# Daten aus dem verarbeiteten Dictionary extrahieren
|
# Daten aus dem verarbeiteten Dictionary extrahieren
|
||||||
@@ -599,6 +716,13 @@ def check_file_in_work(work_dir, filename):
|
|||||||
return (mypath, fexists)
|
return (mypath, fexists)
|
||||||
|
|
||||||
def copy_layers_into_dxf_by_filter(dxf_source: ezdxf.document.Drawing, dxf_target:ezdxf.document.Drawing):
|
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_source = dxf_source.modelspace()
|
||||||
msp_target = dxf_target.modelspace()
|
msp_target = dxf_target.modelspace()
|
||||||
@@ -658,8 +782,13 @@ def copy_layers_into_dxf_by_filter(dxf_source: ezdxf.document.Drawing, dxf_targe
|
|||||||
def get_cable_artnr(section, length):
|
def get_cable_artnr(section, length):
|
||||||
"""
|
"""
|
||||||
Sucht in der angegebenen Config-Section die passende Kabel-Artikelnr. für die gegebene Länge.
|
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?
|
# Existiert über BMK vergebene Kabel-Kennzeichnung in kabel.cfg?
|
||||||
if section not in cable_cfg:
|
if section not in cable_cfg:
|
||||||
@@ -675,6 +804,15 @@ def get_cable_artnr(section, length):
|
|||||||
return False, f"Kabel länger als max. Kabellänge in Sektion '{section}'"
|
return False, f"Kabel länger als max. Kabellänge in Sektion '{section}'"
|
||||||
|
|
||||||
def map_sensor_to_cable_cfg(plines):
|
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)
|
sens2cable = defaultdict(list)
|
||||||
|
|
||||||
mapping = config_BMK["Cable-Mapping"]
|
mapping = config_BMK["Cable-Mapping"]
|
||||||
|
|||||||
Reference in New Issue
Block a user