Schalter von -o auf -w geändert. Nimmt Parameter json File. Prints in getpositions entfernt.

This commit is contained in:
2025-05-20 11:33:20 +02:00
parent eb175ea768
commit a48c39018c
6 changed files with 237 additions and 71 deletions
+2 -1
View File
@@ -50,7 +50,8 @@
"--sensors", "--sensors",
"--rack", "--rack",
"--console", "--console",
"--write" "--write",
"easy"
] ]
}, },
{ {
+12 -3
View File
@@ -1,6 +1,15 @@
@echo off REM @echo off
if [%1]==[] goto usage
goto :doit
:usage
@echo Usage: %0 ^<dxfinWorkOrdner.dxf^>
REM exit /B 1
goto :eof
:doit
for /F %%i in ("%1") do set FILENAME=%%~ni for /F %%i in ("%1") do set FILENAME=%%~ni
getpositions.bat --filename %1 -s -d -r -w -o temp.json getpositions.bat --filename %1 -s -r -w %1
REM routing.bat --filename temp.json -o todraw.json routing.bat --filename %FILENAME%.json -w todraw.json
REM draw.bat --filename todraw.json --new -o %FILENAME%_cables.dxf REM draw.bat --filename todraw.json --new -o %FILENAME%_cables.dxf
+9 -21
View File
@@ -56,7 +56,7 @@ def get_input_positions(msp: ezdxf.document.Drawing.modelspace):
ld[attrib.dxf.tag] = attrib.dxf.text ld[attrib.dxf.tag] = attrib.dxf.text
if attrib.dxf.tag == "IO": if attrib.dxf.tag == "IO":
id = attrib.dxf.text 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 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)) ld["pos"] = (round(pos.x, 1), round(pos.y, 1))
@@ -93,7 +93,7 @@ def create_mappings(positions:dict) -> dict:
warnings = list() warnings = list()
for sensorname,v in positions.items(): for sensorname,v in positions.items():
unterverteiler_pfad = v["KENNZEICHNUNG"] unterverteiler_pfad = v["KENNZEICHNUNG"]
print(unterverteiler_pfad) #print(unterverteiler_pfad)
# PFad zur Karte splitten. Dieser hat z.B. den Inhalt "=AH01+UH02-KF1FDI7" # PFad zur Karte splitten. Dieser hat z.B. den Inhalt "=AH01+UH02-KF1FDI7"
pattern = r"^=([A-Z]+\d+)([+\-])([A-Z]+\d+)([+\-])([A-Z0-9]+)$" 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: for distname in all_distributors:
selectstr = f'MTEXT[layer=="{layer}"]' selectstr = f'MTEXT[layer=="{layer}"]'
for text in msp.query(selectstr): 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) match = re.search("-"+distname, text.dxf.text)
if match: if match:
ret[distname] = (round(text.dxf.insert[0],1), round(text.dxf.insert[1],1)) #nur x und y Koordinate in Json schreiben 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')) all_layers = list(config.items('Layer_Pritschen'))
for (layer,v) in all_layers: for (layer,v) in all_layers:
selectstr = f'LWPOLYLINEMTEXT[layer=="{layer}"]' selectstr = f'LWPOLYLINE[layer=="{layer}"]'
for e in msp.query(selectstr): for e in msp.query(selectstr):
#print_polyline(e) #print_polyline(e)
rack_key = f"Rack_{rack_counter}" rack_key = f"Rack_{rack_counter}"
@@ -228,10 +228,10 @@ def check_file_in_work(work_dir, filename):
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description='fetches the x/y positions from a dxf file', prog='getpositions') 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('-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('-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') 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") config_dir = os.environ.get("PROJECT_CFG")
filename = args.filename filename = args.filename
if not os.path.exists(filename): (dxf_path, dexists) = check_file_in_work(work_dir, 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)
doc = get_dxf_file(dxf_path) # type: ignore doc = get_dxf_file(dxf_path) # type: ignore
msp = doc.modelspace() msp = doc.modelspace()
@@ -292,8 +280,8 @@ if __name__ == '__main__':
if args.console: if args.console:
print(to_json(res_rac)) print(to_json(res_rac))
if args.write: if args.write:
basename = os.path.splitext(args.filename)[0] basename = os.path.splitext(args.write)[0]
write_results(to_json(output_results), work_dir, basename+"_positions.json") write_results(to_json(output_results), work_dir, f"{basename}.json")
else: else:
parser.print_help() parser.print_help()
+12 -12
View File
@@ -634,11 +634,12 @@ class TestLinesweep(unittest.TestCase):
rack = RackIDs() rack = RackIDs()
# Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf
rack.add_racks(racks_data) 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() rack.join_racks()
self.assertEqual(rack.get_points_from_rack("Rack_1-1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) self.assertEqual(rack.get_points_from_rack("Rack_1-1"), [Point(0, 0), Point(0, 5), Point (0, 10)])
def test_snap_segments(self): def test_snap_segments(self):
''' Verlängert Anfangs und Endpunkte von Racks, sodass sie auf naheliegenden Racks liegen''' ''' Verlängert Anfangs und Endpunkte von Racks, sodass sie auf naheliegenden Racks liegen'''
racks_data = { racks_data = {
@@ -646,15 +647,17 @@ class TestLinesweep(unittest.TestCase):
'Rack_2': [Point(1, 5), Point(5, 5)], 'Rack_2': [Point(1, 5), Point(5, 5)],
'Rack_3': [Point(1.5, 7.5), Point(5,7.5)] 'Rack_3': [Point(1.5, 7.5), Point(5,7.5)]
} }
# Initialisiere Racks # Initialisiere Racks
rack = RackIDs() rack = RackIDs()
# Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf # Füge Racks aus gegebenen Daten hinzu und teile Rack_1 bestehend aus 3 Punkten in 2 Racks auf
rack.add_racks(racks_data) 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() rack.join_racks()
self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)]) self.assertEqual(rack.get_points_from_rack("Rack_1"), [Point(0, 0), Point(0, 5), Point (0, 10)])
def test_ids_to_point(self): def test_ids_to_point(self):
''' Testet, ob gefragter Punkt auf Racks a, b, c liegt''' ''' Testet, ob gefragter Punkt auf Racks a, b, c liegt'''
@@ -671,7 +674,7 @@ class TestLinesweep(unittest.TestCase):
def test_add_point_interim(self): 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)], res_rack_seg = {'Rack_1-0': [Point(1, 0), Point(5, 6)],
'Rack_2-0': [Point(1, 8), Point(1, 0)], 'Rack_2-0': [Point(1, 8), Point(1, 0)],
@@ -710,7 +713,8 @@ class TestLinesweep(unittest.TestCase):
def test_generate_graph(self): 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_segs = {'Rack_1-0': [Point(0, 0), Point(0, 10)],
'Rack_2-0': [Point(10, -2), Point(10, 5)], 'Rack_2-0': [Point(10, -2), Point(10, 5)],
'Rack_2-1': [Point(0, 3), Point(10, 3)]} 'Rack_2-1': [Point(0, 3), Point(10, 3)]}
@@ -733,31 +737,27 @@ class TestLinesweep(unittest.TestCase):
an.add_sensors(sensors) an.add_sensors(sensors)
an.connect_sensors_to_racks() an.connect_sensors_to_racks()
G2 = nx.Graph() G2 = nx.Graph()
pos = an.generate_graph(G2) pos = an.generate_graph(G2)
edge_colors = [G2[u][v].get('color', 'black') for u, v in G2.edges()] 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) nx.draw(G2, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors)
plt.show() plt.show()
an.add_distributors(distributors) an.add_distributors(distributors)
an.connect_distributor_to_racks() an.connect_distributor_to_racks()
G3 = nx.Graph() G3 = nx.Graph()
pos = an.generate_graph(G3) pos = an.generate_graph(G3)
edge_colors = [G3[u][v].get('color', 'black') for u, v in G3.edges()] 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) nx.draw(G3, pos, with_labels=False, node_size=10, font_size=8, edge_color=edge_colors)
plt.show() plt.show()
def test_Wegsuche(self): def test_Wegsuche(self):
''' Erstellt Graphen mit Racks, Sensoren und Unterverteilern und sucht kürzeste Wege von Unterverteiler zu zugehörigen Sensoren''' ''' 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_segs = {'Rack_1': [Point(0, 0), Point(0, 10)],
'Rack_2-1': [Point(0, 3), Point(10, 3)]} 'Rack_2': [Point(10, -2), Point(10, 5)],
'Rack_2': [Point(0, 3), Point(10, 3)]}
sensors = {'Sens_1': Point(1, 1), sensors = {'Sens_1': Point(1, 1),
'Sens_2': Point(2, 4), 'Sens_2': Point(2, 4),
+28 -9
View File
@@ -13,6 +13,18 @@ from plant import Anlage
def load_json(jsonfilename): def load_json(jsonfilename):
with open(jsonfilename, encoding='utf-8') as fh: with open(jsonfilename, encoding='utf-8') as fh:
return json.load(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): 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: if args.graph:
draw_graph(G,an) draw_graph(G,an)
return paths
def draw_graph(G:nx.Graph, an:Anlage): def draw_graph(G:nx.Graph, an:Anlage):
pos = an.get_node_positions() pos = an.get_node_positions()
@@ -75,10 +89,10 @@ def draw_graph(G:nx.Graph, an:Anlage):
plt.show() plt.show()
def prepare_data(rawdata:dict): def prepare_data(rawdata:dict):
sensors = data["sensors"] sensors = rawdata["sensors"]
subdists = data["distributors"] subdists = rawdata["distributors"]
racks = data["racks"] racks = rawdata["racks"]
mapping = data["mapping"] mapping = rawdata["mapping"]
dracks = dict() dracks = dict()
for rname,lp in racks: for rname,lp in racks:
if rname not in dracks: 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('-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('-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('-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() args = parser.parse_args()
@@ -104,16 +119,20 @@ if __name__ == "__main__":
jsonfilename = args.filename jsonfilename = args.filename
sensors_path = os.path.join(work_dir, jsonfilename) sensors_path = os.path.join(work_dir, jsonfilename)
# Einlesen # Einlesen und Vorbereiten der Daten
rawdata = load_json(sensors_path) rawdata = load_json(sensors_path)
(racks, sensors, subdists, mapping) = prepare_data(rawdata) (racks, sensors, subdists, mapping) = prepare_data(rawdata)
# virtuelle Anlage erstellen
plant = create_plant(racks, sensors, subdists, mapping) 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")
+174 -25
View File
@@ -1,29 +1,178 @@
{ {
"kabel": [ "sensors": {
{ "BG3241": {
"id": "BG3241-UC0101", "IO": "BG3241",
"coords": [ "pos": [
{ "x": 45, "y": 1235 }, { "x": 40, "y": 4000 } ] 38.8,
} , 1280.2
{ ],
"id": "BG3240-UC0101", "ID": "",
"coords": [ "VERW": "Jam detector",
{ "x": 4950,"y": 5595 },{ "x": 4946,"y": 5595 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } "BEZEICHNUNG": "Stausensor 1 (ILS-CV M0108)",
"KENNZEICHNUNG": "=A01+UC0101-KF1DI1",
] "TEXT-E": "",
"TEXT-ES": "",
"TEXT-F": "",
"SPS": "1",
"REALE_POSITION": "x"
}, },
{ "BG3240": {
"id": "FC0062-UC0101", "IO": "BG3240",
"coords": [ "pos": [
{ "x": 4975,"y": 8068 },{ "x": 4946,"y": 8068 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } 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"
}, },
{ "MA0062": {
"id": "MA0062-UC0101", "IO": "MA0062",
"coords": [ "pos": [
{ "x": 4975,"y": 8068 },{ "x": 4946,"y": 8068 },{ "x": 4946,"y": 3879 },{ "x": 40,"y": 3879 },{ "x": 40,"y": 4000 } 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
]
]
}
}