From a48c39018c3c78a31b4f564c2df53bfdd3b52616 Mon Sep 17 00:00:00 2001 From: lertlmaier Date: Tue, 20 May 2025 11:33:20 +0200 Subject: [PATCH] =?UTF-8?q?Schalter=20von=20-o=20auf=20-w=20ge=C3=A4ndert.?= =?UTF-8?q?=20Nimmt=20Parameter=20json=20File.=20Prints=20in=20getposition?= =?UTF-8?q?s=20entfernt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/launch.json | 3 +- bin/getexdraw.bat | 15 +++- lib/getpositions.py | 30 ++----- lib/plant.py | 24 +++--- lib/routing.py | 37 ++++++-- work/easy.json | 199 ++++++++++++++++++++++++++++++++++++++------ 6 files changed, 237 insertions(+), 71 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 22cb63b..0ab08b6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -50,7 +50,8 @@ "--sensors", "--rack", "--console", - "--write" + "--write", + "easy" ] }, { diff --git a/bin/getexdraw.bat b/bin/getexdraw.bat index d780afc..1eb6a1e 100644 --- a/bin/getexdraw.bat +++ b/bin/getexdraw.bat @@ -1,6 +1,15 @@ -@echo off +REM @echo off + +if [%1]==[] goto usage +goto :doit +:usage +@echo Usage: %0 ^ +REM exit /B 1 +goto :eof + +:doit for /F %%i in ("%1") do set FILENAME=%%~ni -getpositions.bat --filename %1 -s -d -r -w -o temp.json -REM routing.bat --filename temp.json -o todraw.json +getpositions.bat --filename %1 -s -r -w %1 +routing.bat --filename %FILENAME%.json -w todraw.json REM draw.bat --filename todraw.json --new -o %FILENAME%_cables.dxf diff --git a/lib/getpositions.py b/lib/getpositions.py index 24a6a32..fae81ad 100644 --- a/lib/getpositions.py +++ b/lib/getpositions.py @@ -56,7 +56,7 @@ def get_input_positions(msp: ezdxf.document.Drawing.modelspace): ld[attrib.dxf.tag] = attrib.dxf.text if attrib.dxf.tag == "IO": id = attrib.dxf.text - print(f"-- coord io {id}--: {attrib.dxf.insert}") # position des Blocks + #print(f"-- coord io {id}--: {attrib.dxf.insert}") # position des Blocks pos = attrib.dxf.insert #Position aufzeichnen und bei Bedarf später mit REAL_POS überschreiben ld["pos"] = (round(pos.x, 1), round(pos.y, 1)) @@ -93,7 +93,7 @@ def create_mappings(positions:dict) -> dict: warnings = list() for sensorname,v in positions.items(): unterverteiler_pfad = v["KENNZEICHNUNG"] - print(unterverteiler_pfad) + #print(unterverteiler_pfad) # PFad zur Karte splitten. Dieser hat z.B. den Inhalt "=AH01+UH02-KF1FDI7" pattern = r"^=([A-Z]+\d+)([+\-])([A-Z]+\d+)([+\-])([A-Z0-9]+)$" @@ -148,7 +148,7 @@ def get_subdistributor_positions(msp, dist2sensors): for distname in all_distributors: selectstr = f'MTEXT[layer=="{layer}"]' for text in msp.query(selectstr): - print(f"Text auf Layer 'Busverteiler-Kennzeichnung': {text.dxf.text}") + #print(f"Text auf Layer 'Busverteiler-Kennzeichnung': {text.dxf.text}") match = re.search("-"+distname, text.dxf.text) if match: ret[distname] = (round(text.dxf.insert[0],1), round(text.dxf.insert[1],1)) #nur x und y Koordinate in Json schreiben @@ -181,7 +181,7 @@ def get_rack_positions(msp): all_layers = list(config.items('Layer_Pritschen')) for (layer,v) in all_layers: - selectstr = f'LWPOLYLINEMTEXT[layer=="{layer}"]' + selectstr = f'LWPOLYLINE[layer=="{layer}"]' for e in msp.query(selectstr): #print_polyline(e) rack_key = f"Rack_{rack_counter}" @@ -228,10 +228,10 @@ def check_file_in_work(work_dir, filename): if __name__ == '__main__': parser = argparse.ArgumentParser(description='fetches the x/y positions from a dxf file', prog='getpositions') - parser.add_argument('-f', '--filename', action='store', required=True, default="ST_6300_Steuerungstestlayout1_neueBloecke.dwg", help='which file should be fetched', metavar='myfile.dwg') + parser.add_argument('-f', '--filename', action='store', required=True, default="ST_6300_Steuerungstestlayout1_neueBloecke.dwg", help='which file should be fetched', metavar='myfile.dxf') parser.add_argument('-s', '--sensors', action='store_true', help='fetch all position of sensors, motors, actors and subdistributors') parser.add_argument('-r', '--rack', action='store_true', help='fetch all positions of all cable racks') - parser.add_argument('-w', '--write', action='store_true', help='write results into a json file') + parser.add_argument('-w', '--write', action='store', help='write results into a json file') parser.add_argument('-c', '--console', action='store_true', help='print results to output') @@ -242,19 +242,7 @@ if __name__ == '__main__': config_dir = os.environ.get("PROJECT_CFG") filename = args.filename - if not os.path.exists(filename): - dxf_path = os.path.join(work_dir, filename) - if not os.path.exists(dxf_path): - print(f'no such file {dxf_path}') - raise FileExistsError - else: - dxf_path = filename - if not os.path.exists(dxf_path): - print(f'no such file {dxf_path}') - raise FileExistsError - - dxf_file = args.dxf - (dxf_path, dexists) = check_file_in_work(work_dir, dxf_file) + (dxf_path, dexists) = check_file_in_work(work_dir, filename) doc = get_dxf_file(dxf_path) # type: ignore msp = doc.modelspace() @@ -292,8 +280,8 @@ if __name__ == '__main__': if args.console: print(to_json(res_rac)) if args.write: - basename = os.path.splitext(args.filename)[0] - write_results(to_json(output_results), work_dir, basename+"_positions.json") + basename = os.path.splitext(args.write)[0] + write_results(to_json(output_results), work_dir, f"{basename}.json") else: parser.print_help() diff --git a/lib/plant.py b/lib/plant.py index 25a9bd6..9eda10e 100644 --- a/lib/plant.py +++ b/lib/plant.py @@ -634,11 +634,12 @@ class TestLinesweep(unittest.TestCase): rack = RackIDs() # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf rack.add_racks(racks_data) - # Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu + # Verknüpfe Racks mit echten Schnittpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu rack.join_racks() self.assertEqual(rack.get_points_from_rack("Rack_1-1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) + def test_snap_segments(self): ''' Verlängert Anfangs und Endpunkte von Racks, sodass sie auf naheliegenden Racks liegen''' racks_data = { @@ -646,15 +647,17 @@ class TestLinesweep(unittest.TestCase): 'Rack_2': [Point(1, 5), Point(5, 5)], 'Rack_3': [Point(1.5, 7.5), Point(5,7.5)] } + # Initialisiere Racks rack = RackIDs() # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf rack.add_racks(racks_data) - # Verknüpfe Racks mit echten Schniuttpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu + # Verknüpfe Racks mit echten Schnittpunkten und füge Schnittpunkte (exakt & beinahe) zu jeweiligem Rack hinzu rack.join_racks() self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) + def test_ids_to_point(self): ''' Testet, ob gefragter Punkt auf Racks a, b, c liegt''' @@ -671,7 +674,7 @@ class TestLinesweep(unittest.TestCase): def test_add_point_interim(self): - ''' Testet das inzufügen und einsortieren eines Zwischenpunktes zwische nRack-Anfang und Rack-Ende''' + ''' Testet das hinzufügen und einsortieren eines Zwischenpunktes zwischen Rack-Anfang und Rack-Ende''' res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)], 'Rack_2-0': [Point(1, 8), Point(1, 0)], @@ -710,7 +713,8 @@ class TestLinesweep(unittest.TestCase): def test_generate_graph(self): - '''Generiert einen Graphen in 3 unterschiedlichen Ausbauestufen (nur Racks, Racks+Sensoren, Racks+Sensoren+Unterverteiler)''' + '''Generiert einen Graphen in 3 unterschiedlichen Ausbaustufen (nur Racks, Racks+Sensoren, Racks+Sensoren+Unterverteiler)''' + rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], 'Rack_2-0': [Point(10, -2), Point(10, 5)], 'Rack_2-1': [Point(0, 3), Point(10, 3)]} @@ -733,31 +737,27 @@ class TestLinesweep(unittest.TestCase): an.add_sensors(sensors) an.connect_sensors_to_racks() - G2 = nx.Graph() pos = an.generate_graph(G2) - edge_colors = [G2[u][v].get('color', 'black') for u, v in G2.edges()] nx.draw(G2, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) plt.show() an.add_distributors(distributors) an.connect_distributor_to_racks() - G3 = nx.Graph() pos = an.generate_graph(G3) - edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] - nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors) plt.show() def test_Wegsuche(self): ''' Erstellt Graphen mit Racks, Sensoren und Unterverteilern und sucht kürzeste Wege von Unterverteiler zu zugehörigen Sensoren''' - rack_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)], - 'Rack_2-0': [Point(10, -2), Point(10, 5)], - 'Rack_2-1': [Point(0, 3), Point(10, 3)]} + + rack_segs = {'Rack_1': [Point(0, 0), Point(0, 10)], + 'Rack_2': [Point(10, -2), Point(10, 5)], + 'Rack_2': [Point(0, 3), Point(10, 3)]} sensors = {'Sens_1': Point(1, 1), 'Sens_2': Point(2, 4), diff --git a/lib/routing.py b/lib/routing.py index bf79ee4..b0b9d07 100644 --- a/lib/routing.py +++ b/lib/routing.py @@ -13,6 +13,18 @@ from plant import Anlage def load_json(jsonfilename): with open(jsonfilename, encoding='utf-8') as fh: return json.load(fh) + +def write_results(jsnResults, outdir, filename): + """ write results to a json file + """ + print("writing results to a json file ...") + outfile = os.path.join(outdir, filename) + with open(outfile, 'w', encoding='utf-8') as fh: + fh.write(jsnResults) + print("done") + +def to_json(d, pretty: bool = True) -> str: + return json.dumps(d, indent=2 if pretty else None, ensure_ascii=False, default=str) #ensure_ascii false für darstellung von "ue" def create_plant(racks:dict, sensors:dict, distributors:dict, mapping:dict): @@ -66,6 +78,8 @@ def create_plant(racks:dict, sensors:dict, distributors:dict, mapping:dict): if args.graph: draw_graph(G,an) + return paths + def draw_graph(G:nx.Graph, an:Anlage): pos = an.get_node_positions() @@ -75,10 +89,10 @@ def draw_graph(G:nx.Graph, an:Anlage): plt.show() def prepare_data(rawdata:dict): - sensors = data["sensors"] - subdists = data["distributors"] - racks = data["racks"] - mapping = data["mapping"] + sensors = rawdata["sensors"] + subdists = rawdata["distributors"] + racks = rawdata["racks"] + mapping = rawdata["mapping"] dracks = dict() for rname,lp in racks: if rname not in dracks: @@ -93,6 +107,7 @@ if __name__ == "__main__": parser.add_argument('-f', '--filename', action='store', required=True, default="easy_position.json", help='file with all informations about positions gathered from getpositions', metavar='my_positions.json') parser.add_argument('-c', '--console', action='store_true', help='Ausgabe auf Konsole') parser.add_argument('-g', '--graph', action='store_true', help='Zeichnet den Graphen der Anlage') + parser.add_argument('-w', '--write', action='store', help='erstellt Ausgabe-file für das Zeichnen von Kabeln in drawdxf') args = parser.parse_args() @@ -104,16 +119,20 @@ if __name__ == "__main__": jsonfilename = args.filename sensors_path = os.path.join(work_dir, jsonfilename) - # Einlesen + # Einlesen und Vorbereiten der Daten rawdata = load_json(sensors_path) - (racks, sensors, subdists, mapping) = prepare_data(rawdata) - + # virtuelle Anlage erstellen plant = create_plant(racks, sensors, subdists, mapping) - # Erstelle Anlage - + cable_paths = plant + + # Ausgabe schreiben + if args.write: + basename = os.path.splitext(args.write)[0] + write_results(to_json(cable_paths), work_dir, f"{basename}.json") + diff --git a/work/easy.json b/work/easy.json index b0bf967..48317cd 100644 --- a/work/easy.json +++ b/work/easy.json @@ -1,29 +1,178 @@ { - "kabel": [ - { - "id": "BG3241-UC0101", - "coords": [ - { "x": 45, "y": 1235 }, { "x": 40, "y": 4000 } ] - } , - { - "id": "BG3240-UC0101", - "coords": [ - { "x": 4950,"y": 5595 },{ "x": 4946,"y": 5595 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } - - ] + "sensors": { + "BG3241": { + "IO": "BG3241", + "pos": [ + 38.8, + 1280.2 + ], + "ID": "", + "VERW": "Jam detector", + "BEZEICHNUNG": "Stausensor 1 (ILS-CV M0108)", + "KENNZEICHNUNG": "=A01+UC0101-KF1DI1", + "TEXT-E": "", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "x" }, - { - "id": "FC0062-UC0101", - "coords": [ - { "x": 4975,"y": 8068 },{ "x": 4946,"y": 8068 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } - ] + "BG3240": { + "IO": "BG3240", + "pos": [ + 4961.9, + 5609.0 + ], + "ID": "", + "VERW": "Jam detector", + "BEZEICHNUNG": "Stausensor 1 (ILS-CV M0108)", + "KENNZEICHNUNG": "=A01+UC0101-KF1DI1", + "TEXT-E": "conveyor full", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "x" }, - { - "id": "MA0062-UC0101", - "coords": [ - { "x": 4975,"y": 8068 },{ "x": 4946,"y": 8068 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } - ] + "MA0062": { + "IO": "MA0062", + "pos": [ + 4967.0, + 8072.5 + ], + "ID": "", + "VERW": "CV-M0062_0,75", + "BEZEICHNUNG": "Motor MA0062", + "KENNZEICHNUNG": "=A01+UH01-KF1DQ04", + "TEXT-E": "Motor MA0062", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "x" + }, + "FC0062": { + "IO": "FC0062", + "pos": [ + 4973.9, + 8072.5 + ], + "ID": "", + "VERW": "MS FC0062", + "BEZEICHNUNG": "Meldekontakt Motorschutzschalter FC0062", + "KENNZEICHNUNG": "=A01+UH01-KF1DI2", + "TEXT-E": "Motor protection switch signaling contact FC0062", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "x" + }, + "BG3260": { + "IO": "BG3260", + "pos": [ + 9598.8, + 12907.4 + ], + "ID": "", + "VERW": "Jam detector", + "BEZEICHNUNG": "Stausensor 1 (ILS-CV M0108)", + "KENNZEICHNUNG": "=A01+UC0101-KF1DI1", + "TEXT-E": "conveyor full", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "x" + }, + "BG3270": { + "IO": "BG3270", + "pos": [ + 5893.0, + 12968.1 + ], + "ID": "", + "VERW": "Jam detector", + "BEZEICHNUNG": "Stausensor 1 (ILS-CV M0108)", + "KENNZEICHNUNG": "=A01+UC0101-KF1DI1", + "TEXT-E": "conveyor full", + "TEXT-ES": "", + "TEXT-F": "", + "SPS": "1", + "REALE_POSITION": "" } - ] -} - + }, + "mappings": { + "UC0101": [ + "BG3241", + "BG3240", + "BG3260", + "BG3270" + ], + "UH01": [ + "MA0062", + "FC0062" + ] + }, + "distributors": { + "UC0101": [ + 0.0, + 4162.8 + ], + "UH01": [ + 6719.0, + 16600.1 + ] + }, + "racks": { + "Rack_1": [ + [ + 4946.5, + 15774.4 + ], + [ + 4946.5, + 3879.4 + ] + ], + "Rack_2": [ + [ + 0.1, + 57.6 + ], + [ + 0.1, + 3777.6 + ], + [ + 14755.1, + 3777.6 + ] + ], + "Rack_3": [ + [ + 185.1, + 15865.5 + ], + [ + 12450.7, + 15865.5 + ] + ], + "Rack_4": [ + [ + 2866.6, + 15774.4 + ], + [ + 2866.6, + 3880.4 + ] + ], + "Rack_5": [ + [ + 8866.1, + 15774.4 + ], + [ + 8866.1, + 3878.4 + ] + ] + } +} \ No newline at end of file