Topic: Point to point wire/cable list generator
This python script takes a qet project file and produces a point to point wiring list as a CSV file. It includes Foilo referencing of coming and going arrows but it will not work well with crosses, splices and other wire joins which were not of interest to my end use case anyway
An example of the CSV loaded in to excel is provided.
The propose was to provide a list of wires for wiring a machine/panel so the correct size an color of wire can be selected and correctly labeled and it is very obvious which terminals it connects to
and thus the list contains,
Start location, part, designator, terminal ID
End location, part designator, terminal ID
conductor_section, conductor_function, conductor color, and conductor number
Clearly the more you fill in for conductor details, and if you edit the symbols to actually use the terminal names you will get more out but it works for my purpose and may be it is of use to others?
import zipfile
import xml.etree.ElementTree as ET
import os
import tempfile
import csv
def extract_content_qet(file_path):
"""Unzip .qetz or return .qet path"""
if zipfile.is_zipfile(file_path):
with zipfile.ZipFile(file_path, 'r') as zip_ref:
temp_dir = tempfile.mkdtemp()
zip_ref.extract('content.qet', temp_dir)
return os.path.join(temp_dir, 'content.qet')
return file_path
def build_terminal_uuid_map(root):
"""Builds a dict mapping terminal UUIDs to their names"""
terminal_map = {}
for terminal in root.iter('terminal'):
uuid = terminal.get('uuid')
name = terminal.get('name')
if uuid and name:
terminal_map[uuid] = name
return terminal_map
def build_link_uuid_map(root):
"""Builds a dict mapping link UUIDs to their associated element UUIDs"""
link_map = {}
for element in root.iter('element'):
element_uuid = element.get('uuid')
links_node = element.find('links_uuids')
if links_node is not None:
for link in links_node.findall('link_uuid'):
link_uuid = link.get('uuid')
if link_uuid:
print(f"{element_uuid} -> {link_uuid}")
link_map[link_uuid] = element_uuid # You can also store the full element if needed
return link_map
def find_element_by_uuid(root, target_uuid):
"""Finds the <element> with the given UUID"""
for element in root.iter('element'):
if element.get('uuid') == target_uuid:
return element
return None
def find_parent_by_uuid(root, target_uuid):
"""Finds the parent of the <element> with the given UUID"""
for parent in root.iter('diagram'):
for child in parent.iter('element'):
if child.get("uuid") == target_uuid:
return parent
return None
def extract_conductors_with_terminal_names(root, terminal_map,link_map):
"""Extracts conductor data and resolves terminal UUIDs to names"""
conductors = []
seenlinks = []
for conductor in root.iter('conductor'):
start_uuid = conductor.get('terminal1')
end_uuid = conductor.get('terminal2')
element1_name = conductor.get('element1_name')
element1_label = conductor.get('element1_label')
element1_uuid =conductor.get('element1')
element2_name = conductor.get('element2_name')
element2_label = conductor.get('element2_label')
element2_uuid =conductor.get('element2')
seen = False
if(conductor.get('element1_name') == "Going arrow" or conductor.get('element1_name') == "Coming arrow"):
element1_name = "*****";
print("Element 1 is a reference")
print(f"Element 1 uuid = {element1_uuid}")
ele = find_element_by_uuid(root,element1_uuid )
if ele is not None:
links_node = ele.find('links_uuids')
if links_node is not None:
for link in links_node.findall('link_uuid'):
link_uuid = link.get('uuid')
if link_uuid:
if link_uuid in seenlinks:
print(f"link uuuid {link_uuid} already seen")
seen=True
else:
print(f"Element 1 link uuuid {link_uuid}")
for conductor2 in root.iter('conductor'):
if conductor2.get('element2') == link_uuid:
print(f"adding {element1_uuid}")
seenlinks.append(element1_uuid)
element1_name = conductor2.get('element1_name')
element1_label = conductor2.get('element1_label')
element1_uuid = conductor2.get('element1')
start_uuid = conductor2.get('terminal1')
if conductor2.get('element1') == link_uuid:
print(f"adding {element2_uuid}")
seenlinks.append(element2_uuid)
element1_name = conductor2.get('element2_name')
element1_label = conductor2.get('element2_label')
element1_uuid = conductor2.get('element2')
start_uuid = conductor2.get('terminal2')
if(conductor.get('element2_name') == "Going arrow" or conductor.get('element2_name') == "Coming arrow"):
print("Element 2 is a reference")
print(f"Element 2 uuid = {element2_uuid}")
ele = find_element_by_uuid(root,element2_uuid )
if ele is not None:
links_node = ele.find('links_uuids')
if links_node is not None:
for link in links_node.findall('link_uuid'):
link_uuid = link.get('uuid')
if link_uuid:
if link_uuid in seenlinks:
print(f"link uuuid {link_uuid} already seen")
seen=True
else:
print(f"Element 2 link uuuid {link_uuid}")
for conductor2 in root.iter('conductor'):
if conductor2.get('element1') == link_uuid:
print(f"adding {element2_uuid}")
seenlinks.append(element2_uuid)
element2_name = conductor2.get('element2_name')
element2_label = conductor2.get('element2_label')
element2_uuid = conductor2.get('element2')
end_uuid = conductor2.get('terminal2')
if conductor2.get('element2') == link_uuid:
print(f"adding {element1_uuid}")
seenlinks.append(element1_uuid)
element2_name = conductor2.get('element1_name')
element2_label = conductor2.get('element1_label')
element2_uuid = conductor2.get('element1')
end_uuid = conductor2.get('terminal1')
ele1 = find_element_by_uuid(root,element1_uuid )
ele2 = find_element_by_uuid(root,element2_uuid )
element1_loc = ""
element2_loc = ""
info_container = ele1.find('elementInformations')
if info_container is not None:
for elem in info_container.findall('elementInformation'):
if elem.attrib.get('name') == 'location':
element1_loc = elem.text
info_container = ele2.find('elementInformations')
if info_container is not None:
for elem in info_container.findall('elementInformation'):
if elem.attrib.get('name') == 'location':
element2_loc = elem.text
if seen == False :
if not element1_loc:
print(f"Element1 loc is empty")
parent = find_parent_by_uuid(root,element1_uuid)
if parent:
element1_loc = "+"+parent.get('locmach')
if not element2_loc:
print(f"Element2 loc is empty")
parent = find_parent_by_uuid(root,element2_uuid)
if parent:
element2_loc = "+"+parent.get('locmach')
conductors.append({
'S LOC': element1_loc,
'S PART': element1_name,
'S DESIGNATOR': element1_label,
'S TERMINAL': terminal_map.get(start_uuid),
'E LOC': element2_loc,
'E PART': element2_name,
'E DESIGNATOR': element2_label,
'E TERMINAL': terminal_map.get(end_uuid),
'Conductor Section': conductor.get('conductor_section'),
'Conductor Function': conductor.get('function'),
'Color': conductor.get('conductor_color'),
'Designator': conductor.get('num')
})
return conductors
def process_qet_file(file_path, output_csv='conductors_named.csv'):
qet_path = extract_content_qet(file_path)
tree = ET.parse(qet_path)
root = tree.getroot()
terminal_map = build_terminal_uuid_map(root)
link_map = build_link_uuid_map(root)
conductors = extract_conductors_with_terminal_names(root, terminal_map,link_map)
# Output to CSV
if conductors:
with open(output_csv, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=conductors[0].keys())
writer.writeheader()
writer.writerows(conductors)
print(f"Exported {len(conductors)} conductors to {output_csv}")
else:
print("No conductors found.")
# Example usage
if __name__ == "__main__":
process_qet_file("c:\\yourfile.qet")