From 2cef8acf681ceeba05028a6dfce32ebce7d3dc02 Mon Sep 17 00:00:00 2001 From: Laurier Loiselle Date: Fri, 20 Jan 2023 18:57:03 -0500 Subject: [PATCH] src: wireviz: suport belden wires mpn --- src/wireviz/wv_colors.py | 6 ++ src/wireviz/wv_dataclasses.py | 107 ++++++++++++++++++++++++++++++++-- 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/wireviz/wv_colors.py b/src/wireviz/wv_colors.py index a813339..be36ae2 100644 --- a/src/wireviz/wv_colors.py +++ b/src/wireviz/wv_colors.py @@ -164,6 +164,12 @@ class MultiColor: joiner = "???" return joiner.join([str(color) for color in self.colors]) + def __getitem__(self, idx): + if not self: + return None + else: + return self.colors[idx % len(self)] + @property def all_known(self): return all([color.known for color in self.colors]) diff --git a/src/wireviz/wv_dataclasses.py b/src/wireviz/wv_dataclasses.py index ef290ed..db3a43b 100644 --- a/src/wireviz/wv_dataclasses.py +++ b/src/wireviz/wv_dataclasses.py @@ -4,6 +4,7 @@ from collections import namedtuple from dataclasses import dataclass, field from enum import Enum from itertools import zip_longest +import logging from typing import Any, Dict, List, Optional, Tuple, Union from wireviz.wv_bom import ( @@ -575,7 +576,8 @@ class Cable(TopLevelGraphicalComponent): def gauge_str(self): if not self.gauge: return None - actual_gauge = f"{self.gauge.number} {self.gauge.unit}" + number = int(self.gauge.number) if self.gauge.unit == 'AWG' else self.gauge.number + actual_gauge = f"{number} {self.gauge.unit}" actual_gauge = actual_gauge.replace("mm2", "mm\u00B2") return actual_gauge @@ -628,16 +630,110 @@ class Cable(TopLevelGraphicalComponent): ) return desc - def _get_wire_partnumber(self, idx) -> PartNumberInfo: + belden_color = { + 'BN': '001', + 'RD': '002', + 'OG': '003', + 'YE': '004', + 'GN': '005', + 'TQ': '006', # (For Belden: light blue. For WireViz: turquoise) + 'VT': '007', + 'GY': '008', + 'WH': '009', + 'BK': '010', + 'BG': '011', + 'PK': '012', + 'BU': '013', + 'BKRD':'015', # (for Belden: white/red) + 'BKGN':'016', # (for Belden: white/green) + 'BKYE':'017', # (for Belden: white/yellow) + 'BKBU':'018', # (for Belden: white/blue) + 'BKBN':'019', # (for Belden: white/brown) + 'BKOG':'020', # (for Belden: white/orange) + 'BKGY':'021', # (for Belden: white/gray) + 'BKVT':'022', # (for Belden: white/purple) + # (1) Why use BKRD instead of WHRD, since Belden only sells white/red? + # - WHRD is impractical to use in Wireviz (white wire sides on white background does not help with identification) + # - BKRD is clearly distinguishable, and comes handy to use in Wireviz, as the representation of a GND rail associated (even twisted, if applicable) with a specific RD signal wire. + # (2) For all wire colors see: + # https://www.belden.com/dfsmedia/f1e38517e0cd4caa8b1acb6619890f5e/7806-source/options/view/cabling-solutions-for-industrial-applications-catalog-belden-09-2020#page=153 + + } + belden_tfe_base_mpn = { + # Leftmost in list is the prefered MPN + # NOTE (lal 2022-12-20): this prefered MPN is arbitrary ATM + '16 AWG': ['83030', '83010'], + '18 AWG': ['83029', '83009'], + '20 AWG': ['83028', '83027', '83007', '83008'], + '22 AWG': ['83025', '83026', '83005', '83006', '83049', '83050'], + '24 AWG': ['83023', '83003', '83004', '83047', '83048'], + '26 AWG': ['83002', '83046'], + '28 AWG': ['83001', '83045'], + '30 AWG': ['83000', '83043'], + '32 AWG': ['83041'], + # see: https://www.belden.com/dfsmedia/f1e38517e0cd4caa8b1acb6619890f5e/7806-source/options/view/cabling-solutions-for-industrial-applications-catalog-belden-09-2020#page=136 + } + + @property + def is_belden(self): + if 'belden' in self.manufacturer.lower(): + return True + return False + + def get_belden_color(self, color): + if color not in self.belden_color: + logging.warn(f'No color found in belden colors {list(self.belden_color.keys())} matching {self.color}, defaulting to BK') + return self.belden_color['BK'] + return self.belden_color[color] + + def gen_belden_cable_with_alternate(self, color): + # Gauge and mpn base + try: + parts = self.belden_tfe_base_mpn[self.gauge_str] + except KeyError: + raise ValueError(f'Couldn\'t find a belden TFE wire for wire of {self.gauge_str}') + + color = self.get_belden_color(color) + + if not color: + raise ValueError(f'Failed to find a color for property: {self.description}') + + # Create the list of mpn + roll_length = 100 + mpn_list = [f'{mpn} {color}{roll_length}' for mpn in parts] + + main_part = mpn_list[0] + alternates = mpn_list[1:] if len(mpn_list) > 1 else [] + return (main_part, alternates) + + def get_mpn_if_belden(self, manufacturer, mpn, color): + if self.manufacturer and not self.mpn: + if self.is_belden: + main_part, alternates = self.gen_belden_cable_with_alternate(color) + return main_part + if alternates: + logging.info(f'Alternate part{"s" if len(alternates) > 1 else ""} available for {self.gauge_str}, color {self.color}: {alternates}') + else: + logging.info(f'Not updating part for manufacturer {self.manufacturer}, only "belden" supported') + else: + logging.info(f'Not updating part, no manufacturer provided') + return mpn + + def _get_wire_partnumber(self, idx, color) -> PartNumberInfo: def _get_correct_element(inp, idx): return inp[idx] if isinstance(inp, List) else inp # TODO: possibly make more robust/elegant if self.category == "bundle": + manufacturer = _get_correct_element(self.partnumbers.manufacturer, idx), + mpn = _get_correct_element(self.partnumbers.mpn, idx), + if color is not None: + mpn = self.get_mpn_if_belden(manufacturer, mpn, color.code_en) + return PartNumberInfo( _get_correct_element(self.partnumbers.pn, idx), _get_correct_element(self.partnumbers.manufacturer, idx), - _get_correct_element(self.partnumbers.mpn, idx), + mpn, _get_correct_element(self.partnumbers.supplier, idx), _get_correct_element(self.partnumbers.spn, idx), ) @@ -712,13 +808,14 @@ class Cable(TopLevelGraphicalComponent): ) for wire_index, (wire_color, wire_label) in enumerate(wire_tuples): id = wire_index + 1 + color = MultiColor(wire_color) self.wire_objects[id] = WireClass( parent=self.designator, # wire-specific properties index=wire_index, # TODO: wire_id id=id, # TODO: wire_id label=wire_label, - color=MultiColor(wire_color), + color=color, # inheritable from parent cable type=self.type, subtype=self.subtype, @@ -726,7 +823,7 @@ class Cable(TopLevelGraphicalComponent): length=self.length, sum_amounts_in_bom=self.sum_amounts_in_bom, ignore_in_bom=self.ignore_in_bom, - partnumbers=self._get_wire_partnumber(wire_index), + partnumbers=self._get_wire_partnumber(wire_index, color[wire_index]), ) if self.shield: