Add href attribute to connectors, cables, and additional_bom_items
This commit is contained in:
parent
dec64abaf5
commit
ab077bce67
@ -2,12 +2,14 @@ templates: # defining templates to be used later on
|
||||
- &molex_f
|
||||
type: Molex KK 254
|
||||
subtype: female
|
||||
href: "https://www.molex.com/molex/products/family/kk_254_rpc_connector_system"
|
||||
- &con_i2c
|
||||
pinlabels: [GND, +5V, SCL, SDA]
|
||||
- &wire_i2c
|
||||
category: bundle
|
||||
gauge: 0.14 mm2
|
||||
colors: [BK, RD, YE, GN]
|
||||
href: [a, b, c, d]
|
||||
|
||||
connectors:
|
||||
X1:
|
||||
@ -67,3 +69,15 @@ connections:
|
||||
- ferrule_crimp
|
||||
- W4: [1,2]
|
||||
- X4: [1,2]
|
||||
|
||||
additional_bom_items:
|
||||
- # define an additional item to add to the bill of materials
|
||||
description: Label, pinout information
|
||||
qty: 2
|
||||
designators:
|
||||
- X2
|
||||
- X3
|
||||
manufacturer: generic company
|
||||
mpn: Label1
|
||||
pn: Label-ID-1
|
||||
href: "https://www.bradyid.com/wire-cable-labels/bmp71-bmp61-m611-tls-2200-nylon-cloth-wire-general-id-labels-cps-2958789"
|
||||
|
||||
@ -73,6 +73,7 @@ class AdditionalComponent:
|
||||
manufacturer: Optional[MultilineHypertext] = None
|
||||
mpn: Optional[MultilineHypertext] = None
|
||||
pn: Optional[Hypertext] = None
|
||||
href: Optional[PlainText] = None
|
||||
qty: float = 1
|
||||
unit: Optional[str] = None
|
||||
qty_multiplier: Union[ConnectorMultiplier, CableMultiplier, None] = None
|
||||
@ -88,6 +89,7 @@ class Connector:
|
||||
manufacturer: Optional[MultilineHypertext] = None
|
||||
mpn: Optional[MultilineHypertext] = None
|
||||
pn: Optional[Hypertext] = None
|
||||
href: Optional[PlainText] = None
|
||||
style: Optional[str] = None
|
||||
category: Optional[str] = None
|
||||
type: Optional[MultilineHypertext] = None
|
||||
@ -170,6 +172,7 @@ class Cable:
|
||||
manufacturer: Union[MultilineHypertext, List[MultilineHypertext], None] = None
|
||||
mpn: Union[MultilineHypertext, List[MultilineHypertext], None] = None
|
||||
pn: Union[Hypertext, List[Hypertext], None] = None
|
||||
href: Optional[PlainText] = None
|
||||
category: Optional[str] = None
|
||||
type: Optional[MultilineHypertext] = None
|
||||
gauge: Optional[float] = None
|
||||
|
||||
@ -14,7 +14,7 @@ from wireviz.wv_colors import get_color_hex
|
||||
from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \
|
||||
html_caption, remove_links, html_line_breaks
|
||||
from wireviz.wv_bom import manufacturer_info_field, component_table_entry, \
|
||||
get_additional_component_table, bom_list, generate_bom
|
||||
get_additional_component_table, bom_list, generate_bom, index_if_list
|
||||
from wireviz.wv_html import generate_html_output
|
||||
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, flatten2d, \
|
||||
open_file_read, open_file_write
|
||||
@ -159,7 +159,8 @@ class Harness:
|
||||
html = [row.replace('<!-- connector table -->', '\n'.join(pinhtml)) for row in html]
|
||||
|
||||
html = '\n'.join(html)
|
||||
dot.node(connector.name, label=f'<\n{html}\n>', shape='none', margin='0', style='filled', fillcolor='white')
|
||||
dot.node(connector.name, label=f'<\n{html}\n>', shape='none', href=connector.href,
|
||||
margin='0', style='filled', fillcolor='white')
|
||||
|
||||
if len(connector.loops) > 0:
|
||||
dot.attr('edge', color='#000000:#ffffff:#000000')
|
||||
@ -288,10 +289,12 @@ class Harness:
|
||||
# connections
|
||||
for connection in cable.connections:
|
||||
if isinstance(connection.via_port, int): # check if it's an actual wire and not a shield
|
||||
dot.attr('edge', color=':'.join(['#000000'] + wv_colors.get_color_hex(cable.colors[connection.via_port - 1], pad=pad) + ['#000000']))
|
||||
dot.attr('edge', color=':'.join(['#000000'] + wv_colors.get_color_hex(cable.colors[connection.via_port - 1], pad=pad) + ['#000000']),
|
||||
href=index_if_list(cable.href, connection.via_port - 1))
|
||||
else: # it's a shield connection
|
||||
# shield is shown with specified color and black borders, or as a thin black wire otherwise
|
||||
dot.attr('edge', color=':'.join(['#000000', shield_color_hex, '#000000']) if isinstance(cable.shield, str) else '#000000')
|
||||
dot.attr('edge', color=':'.join(['#000000', shield_color_hex, '#000000']) if isinstance(cable.shield, str) else '#000000',
|
||||
href=cable.href if isinstance(cable.href, str) else None)
|
||||
if connection.from_port is not None: # connect to left
|
||||
from_connector = self.connectors[connection.from_name]
|
||||
from_port = f':p{connection.from_port}r' if from_connector.style != 'simple' else ''
|
||||
@ -327,6 +330,7 @@ class Harness:
|
||||
|
||||
html = '\n'.join(html)
|
||||
dot.node(cable.name, label=f'<\n{html}\n>', shape='box',
|
||||
href=cable.href if isinstance(cable.href, str) else None,
|
||||
style='filled,dashed' if cable.category == 'bundle' else '', margin='0', fillcolor='white')
|
||||
|
||||
return dot
|
||||
|
||||
@ -15,7 +15,7 @@ def get_additional_component_table(harness, component: Union[Connector, Cable])
|
||||
for extra in component.additional_components:
|
||||
qty = extra.qty * component.get_qty_multiplier(extra.qty_multiplier)
|
||||
if harness.mini_bom_mode:
|
||||
id = get_bom_index(harness, extra.description, extra.unit, extra.manufacturer, extra.mpn, extra.pn)
|
||||
id = get_bom_index(harness, extra.description, extra.unit, extra.manufacturer, extra.mpn, extra.pn, extra.href)
|
||||
rows.append(component_table_entry(f'#{id} ({extra.type.rstrip()})', qty, extra.unit))
|
||||
else:
|
||||
rows.append(component_table_entry(extra.description, qty, extra.unit, extra.pn, extra.manufacturer, extra.mpn))
|
||||
@ -32,7 +32,8 @@ def get_additional_component_bom(component: Union[Connector, Cable]) -> List[dic
|
||||
'manufacturer': part.manufacturer,
|
||||
'mpn': part.mpn,
|
||||
'pn': part.pn,
|
||||
'designators': component.name if component.show_name else None
|
||||
'designators': component.name if component.show_name else None,
|
||||
'href': part.href,
|
||||
})
|
||||
return(bom_entries)
|
||||
|
||||
@ -49,7 +50,7 @@ def generate_bom(harness):
|
||||
+ (f', {connector.color}' if connector.color else ''))
|
||||
bom_entries.append({
|
||||
'item': description, 'qty': 1, 'unit': None, 'designators': connector.name if connector.show_name else None,
|
||||
'manufacturer': connector.manufacturer, 'mpn': connector.mpn, 'pn': connector.pn
|
||||
'manufacturer': connector.manufacturer, 'mpn': connector.mpn, 'pn': connector.pn, 'href': connector.href,
|
||||
})
|
||||
|
||||
# add connectors aditional components to bom
|
||||
@ -68,7 +69,8 @@ def generate_bom(harness):
|
||||
+ (' shielded' if cable.shield else ''))
|
||||
bom_entries.append({
|
||||
'item': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
||||
'manufacturer': cable.manufacturer, 'mpn': cable.mpn, 'pn': cable.pn
|
||||
'manufacturer': cable.manufacturer, 'mpn': cable.mpn, 'pn': cable.pn,
|
||||
'href': cable.href if isinstance(cable.href, str) else None,
|
||||
})
|
||||
else:
|
||||
# add each wire from the bundle to the bom
|
||||
@ -80,7 +82,8 @@ def generate_bom(harness):
|
||||
bom_entries.append({
|
||||
'item': description, 'qty': cable.length, 'unit': cable.length_unit, 'designators': cable.name if cable.show_name else None,
|
||||
'manufacturer': index_if_list(cable.manufacturer, index),
|
||||
'mpn': index_if_list(cable.mpn, index), 'pn': index_if_list(cable.pn, index)
|
||||
'mpn': index_if_list(cable.mpn, index), 'pn': index_if_list(cable.pn, index),
|
||||
'href': index_if_list(cable.href, index),
|
||||
})
|
||||
|
||||
# add cable/bundles aditional components to bom
|
||||
@ -89,7 +92,7 @@ def generate_bom(harness):
|
||||
for item in harness.additional_bom_items:
|
||||
bom_entries.append({
|
||||
'item': item.get('description', ''), 'qty': item.get('qty', 1), 'unit': item.get('unit'), 'designators': item.get('designators'),
|
||||
'manufacturer': item.get('manufacturer'), 'mpn': item.get('mpn'), 'pn': item.get('pn')
|
||||
'manufacturer': item.get('manufacturer'), 'mpn': item.get('mpn'), 'pn': item.get('pn'), 'href': item.get('href'),
|
||||
})
|
||||
|
||||
# remove line breaks if present and cleanup any resulting whitespace issues
|
||||
@ -97,7 +100,7 @@ def generate_bom(harness):
|
||||
|
||||
# deduplicate bom
|
||||
bom = []
|
||||
bom_types_group = lambda bt: (bt['item'], bt['unit'], bt['manufacturer'], bt['mpn'], bt['pn'])
|
||||
bom_types_group = lambda bt: (bt['item'], bt['unit'], bt['manufacturer'], bt['mpn'], bt['pn'], bt['href'])
|
||||
for group in Counter([bom_types_group(v) for v in bom_entries]):
|
||||
group_entries = [v for v in bom_entries if bom_types_group(v) == group]
|
||||
designators = []
|
||||
@ -118,24 +121,25 @@ def generate_bom(harness):
|
||||
bom = [{**entry, 'id': index} for index, entry in enumerate(bom, 1)]
|
||||
return bom
|
||||
|
||||
def get_bom_index(harness, item, unit, manufacturer, mpn, pn):
|
||||
def get_bom_index(harness, item, unit, manufacturer, mpn, pn, href):
|
||||
# Remove linebreaks and clean whitespace of values in search
|
||||
target = tuple(clean_whitespace(v) for v in (item, unit, manufacturer, mpn, pn))
|
||||
target = tuple(clean_whitespace(v) for v in (item, unit, manufacturer, mpn, pn, href))
|
||||
for entry in harness.bom():
|
||||
if (entry['item'], entry['unit'], entry['manufacturer'], entry['mpn'], entry['pn']) == target:
|
||||
if (entry['item'], entry['unit'], entry['manufacturer'], entry['mpn'], entry['pn'], entry['href']) == target:
|
||||
return entry['id']
|
||||
return None
|
||||
|
||||
def bom_list(bom):
|
||||
keys = ['id', 'item', 'qty', 'unit', 'designators'] # these BOM columns will always be included
|
||||
for fieldname in ['pn', 'manufacturer', 'mpn']: # these optional BOM columns will only be included if at least one BOM item actually uses them
|
||||
for fieldname in ['pn', 'manufacturer', 'mpn', 'href']: # these optional BOM columns will only be included if at least one BOM item actually uses them
|
||||
if any(entry.get(fieldname) for entry in bom):
|
||||
keys.append(fieldname)
|
||||
bom_list = []
|
||||
# list of staic bom header names, headers not specified here are generated by capitilising the internal name
|
||||
bom_headings = {
|
||||
"pn": "P/N",
|
||||
"mpn": "MPN"
|
||||
"mpn": "MPN",
|
||||
"href": "URL",
|
||||
}
|
||||
bom_list.append([(bom_headings[k] if k in bom_headings else k.capitalize()) for k in keys]) # create header row with keys
|
||||
for item in bom:
|
||||
|
||||
@ -36,6 +36,8 @@ def generate_html_output(filename: (str, Path), bom_list):
|
||||
file.write('<tr>')
|
||||
for i, item in enumerate(row):
|
||||
item_str = item.replace('\u00b2', '²')
|
||||
if listy[0][i] == 'URL':
|
||||
item_str = f'<a href="{item}">{item_str}</a>'
|
||||
align = 'text-align:right; ' if listy[0][i] == 'Qty' else ''
|
||||
file.write(f'<td style="{align}border:1px solid #000000; padding: 4px">{item_str}</td>')
|
||||
file.write('</tr>')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user