diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py index eb85d936ba..e9f105d273 100644 --- a/selfdrive/car/docs_definitions.py +++ b/selfdrive/car/docs_definitions.py @@ -30,64 +30,72 @@ class Star(Enum): EMPTY = "empty" +class PartType(Enum): + harness_connector = "Harness Connector" + generic_part = "Generic Part" + + +Part = namedtuple("Part", ["value","type"], defaults=("",PartType.generic_part)) + + class CarPart(Enum): #harness connectors - nidec_connector = "Honda Nidec connector" - bosch_a_connector = "Honda Bosch A connector" - bosch_b_connector = "Honda Bosch B connector" - toyota_connector = "Toyota connector" - subaru_a_connector = "Subaru A connector" - subaru_b_connector = "Subaru B connector" - fca_connector = "FCA connector" - ram_connector = "Ram connector" - vw_connector = "VW connector" - j533_connector = "J533 connector" - hyundai_a_connector = "Hyundai A connector" - hyundai_b_connector = "Hyundai B connector" - hyundai_c_connector = "Hyundai C connector" - hyundai_d_connector = "Hyundai D connector" - hyundai_e_connector = "Hyundai E connector" - hyundai_f_connector = "Hyundai F connector" - hyundai_g_connector = "Hyundai G connector" - hyundai_h_connector = "Hyundai H connector" - hyundai_i_connector = "Hyundai I connector" - hyundai_j_connector = "Hyundai J connector" - hyundai_k_connector = "Hyundai K connector" - hyundai_l_connector = "Hyundai L connector" - hyundai_m_connector = "Hyundai M connector" - hyundai_n_connector = "Hyundai N connector" - hyundai_o_connector = "Hyundai O connector" - hyundai_p_connector = "Hyundai P connector" - hyundai_q_connector = "Hyundai Q connector" - custom_connector = "Developer connector" - obd_ii_connector = "OBD-II connector" - gm_connector = "GM connector" - nissan_a_connector = "Nissan A connector" - nissan_b_connector = "Nissan B connector" - mazda_connector = "Mazda connector" - ford_q3_connector = "Ford Q3 connector" - ford_q4_connector = "Ford Q4 connector" - none_connector = "None connector" + nidec_connector = Part("Honda Nidec connector", type=PartType.harness_connector) + bosch_a_connector = Part("Honda Bosch A connector", type=PartType.harness_connector) + bosch_b_connector = Part("Honda Bosch B connector", type=PartType.harness_connector) + toyota_connector = Part("Toyota connector", type=PartType.harness_connector) + subaru_a_connector = Part("Subaru A connector", type=PartType.harness_connector) + subaru_b_connector = Part("Subaru B connector", type=PartType.harness_connector) + fca_connector = Part("FCA connector", type=PartType.harness_connector) + ram_connector = Part("Ram connector", type=PartType.harness_connector) + vw_connector = Part("VW connector", type=PartType.harness_connector) + j533_connector = Part("J533 connector", type=PartType.harness_connector) + hyundai_a_connector = Part("Hyundai A connector", type=PartType.harness_connector) + hyundai_b_connector = Part("Hyundai B connector", type=PartType.harness_connector) + hyundai_c_connector = Part("Hyundai C connector", type=PartType.harness_connector) + hyundai_d_connector = Part("Hyundai D connector", type=PartType.harness_connector) + hyundai_e_connector = Part("Hyundai E connector", type=PartType.harness_connector) + hyundai_f_connector = Part("Hyundai F connector", type=PartType.harness_connector) + hyundai_g_connector = Part("Hyundai G connector", type=PartType.harness_connector) + hyundai_h_connector = Part("Hyundai H connector", type=PartType.harness_connector) + hyundai_i_connector = Part("Hyundai I connector", type=PartType.harness_connector) + hyundai_j_connector = Part("Hyundai J connector", type=PartType.harness_connector) + hyundai_k_connector = Part("Hyundai K connector", type=PartType.harness_connector) + hyundai_l_connector = Part("Hyundai L connector", type=PartType.harness_connector) + hyundai_m_connector = Part("Hyundai M connector", type=PartType.harness_connector) + hyundai_n_connector = Part("Hyundai N connector", type=PartType.harness_connector) + hyundai_o_connector = Part("Hyundai O connector", type=PartType.harness_connector) + hyundai_p_connector = Part("Hyundai P connector", type=PartType.harness_connector) + hyundai_q_connector = Part("Hyundai Q connector", type=PartType.harness_connector) + custom_connector = Part("Developer connector", type=PartType.harness_connector) + obd_ii_connector = Part("OBD-II connector", type=PartType.harness_connector) + gm_connector = Part("GM connector", type=PartType.harness_connector) + nissan_a_connector = Part("Nissan A connector", type=PartType.harness_connector) + nissan_b_connector = Part("Nissan B connector", type=PartType.harness_connector) + mazda_connector = Part("Mazda connector", type=PartType.harness_connector) + ford_q3_connector = Part("Ford Q3 connector", type=PartType.harness_connector) + ford_q4_connector = Part("Ford Q4 connector", type=PartType.harness_connector) + none_connector = Part("None connector", type=PartType.harness_connector) #harness accessories - harness_box = "harness box" - comma_power_v2 = "comma power v2" + harness_box = Part("harness box") + comma_power_v2 = Part("comma power v2") #mounts - mount = "mount" - angled_mount = "angled mount" + mount = Part("mount") + angled_mount = Part("angled mount") #cables - rj45_cable_7ft = "RJ45 cable (7 ft)" - long_obdc_cable = "long OBD-C cable" - usb_a_2_a_cable = "USB A-A cable" - usbc_otg_cable = "USB C OTG cable" - usbc_coupler = "USB-C coupler" - obd_c_cable_1point5ft = "OBD-C cable (1.5 ft)" + rj45_cable_7ft = Part("RJ45 cable (7 ft)") + long_obdc_cable = Part("long OBD-C cable") + usb_a_2_a_cable = Part("USB A-A cable") + usbc_otg_cable = Part("USB C OTG cable") + usbc_coupler = Part("USB-C coupler") + obd_c_cable_1point5ft = Part("OBD-C cable (1.5 ft)") #devices - comma_3 = "comma 3" - red_panda = "red panda" + comma_3 = Part("comma 3") + red_panda = Part("red panda") DEFAULT_CAR_PARTS: List[CarPart] = [CarPart.harness_box, CarPart.comma_power_v2, CarPart.rj45_cable_7ft, CarPart.mount] @@ -98,16 +106,9 @@ class CarParts: parts: List[CarPart] = field(default_factory=list) @classmethod - def default(cls, parts: List[CarPart], default: List[CarPart] = None, remove: List[CarPart] = None): - p = CarParts() - p.parts = [part for part in parts + (default or DEFAULT_CAR_PARTS) if part not in (remove or [])] - return p - - @classmethod - def custom(cls, parts: List[CarPart]): - p = CarParts() - p.parts = parts.copy() - return p + def default(cls, add: List[CarPart] = None, default: List[CarPart] = None, remove: List[CarPart] = None): + p = [part for part in (add or []) + (default or DEFAULT_CAR_PARTS) if part not in (remove or [])] + return cls(p) CarFootnote = namedtuple("CarFootnote", ["text", "column", "docs_only", "shop_footnote"], defaults=(False, False)) @@ -212,7 +213,7 @@ class CarInfo: if self.car_parts.parts: model_years = self.model + (' ' + self.years if self.years else '') buy_link = f'Buy Here' - parts = '
'.join([f"- {self.car_parts.parts.count(part)} {part.value}" for part in sorted(set(self.car_parts.parts), key=lambda part: part.value)]) + parts = '
'.join([f"- {self.car_parts.parts.count(part)} {part.value.value}" for part in sorted(set(self.car_parts.parts), key=lambda part: part.value)]) hardware_col = f'
View{parts}
{buy_link}
' self.row: Dict[Enum, Union[str, Star]] = { diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index c6e2512aef..62ef53169d 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -91,7 +91,7 @@ class GMCarInfo(CarInfo): if CP.networkLocation == car.CarParams.NetworkLocation.fwdCamera: self.car_parts = CarParts.default([CarPart.gm_connector]) else: - self.car_parts = CarParts.custom([CarPart.obd_ii_connector, CarPart.long_obdc_cable, CarPart.usbc_coupler, CarPart.mount]) + self.car_parts = CarParts([CarPart.obd_ii_connector, CarPart.long_obdc_cable, CarPart.usbc_coupler, CarPart.mount]) self.footnotes.append(Footnote.OBD_II) diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py index a7931389ca..9bc8028e54 100644 --- a/selfdrive/car/nissan/values.py +++ b/selfdrive/car/nissan/values.py @@ -36,7 +36,7 @@ NISSAN_PARTS = [CarPart.harness_box, CarPart.rj45_cable_7ft, CarPart.long_obdc_c @dataclass class NissanCarInfo(CarInfo): package: str = "ProPILOT Assist" - car_parts: CarParts = CarParts.default([CarPart.nissan_a_connector], NISSAN_PARTS) + car_parts: CarParts = CarParts.default([CarPart.nissan_a_connector], default=NISSAN_PARTS) CAR_INFO: Dict[str, Optional[Union[NissanCarInfo, List[NissanCarInfo]]]] = { @@ -44,7 +44,7 @@ CAR_INFO: Dict[str, Optional[Union[NissanCarInfo, List[NissanCarInfo]]]] = { CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), CAR.LEAF_IC: None, # same platforms CAR.ROGUE: NissanCarInfo("Nissan Rogue 2018-20"), - CAR.ALTIMA: NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.default([CarPart.nissan_b_connector], NISSAN_PARTS)), + CAR.ALTIMA: NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.default([CarPart.nissan_b_connector], default=NISSAN_PARTS)), } FINGERPRINTS = { diff --git a/selfdrive/car/tests/test_docs.py b/selfdrive/car/tests/test_docs.py index 2e0e0d18e0..3a688b6b8f 100755 --- a/selfdrive/car/tests/test_docs.py +++ b/selfdrive/car/tests/test_docs.py @@ -5,7 +5,7 @@ import unittest from selfdrive.car.car_helpers import interfaces, get_interface_attr from selfdrive.car.docs import CARS_MD_OUT, CARS_MD_TEMPLATE, generate_cars_md, get_all_car_info -from selfdrive.car.docs_definitions import Column, Star +from selfdrive.car.docs_definitions import CarPart, Column, PartType, Star from selfdrive.car.honda.values import CAR as HONDA @@ -74,8 +74,8 @@ class TestCarDocs(unittest.TestCase): if car.name == "comma body": raise unittest.SkipTest - self.assertTrue(car.car_parts.parts, f"Need to specify car parts: {car.name}") - self.assertTrue(any(" connector" in p for p in car.car_parts.parts), f"Need to specify an harness connector: {car.name}") + self.assertTrue(len(car.car_parts.parts) > 0, f"Need to specify car parts: {car.name}") + self.assertTrue(any(p.value.type is PartType.harness_connector and p.value is not CarPart.none_connector for p in car.car_parts.parts), f"Need to specify an harness connector: {car.name}") if __name__ == "__main__": diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 2cca261ffd..f94b44950e 100755 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -166,7 +166,7 @@ class Footnote(Enum): @dataclass class VWCarInfo(CarInfo): package: str = "Adaptive Cruise Control (ACC) & Lane Assist" - car_parts: CarParts = CarParts.custom([CarPart.j533_connector, CarPart.harness_box, CarPart.long_obdc_cable, CarPart.usbc_coupler, CarPart.mount]) + car_parts: CarParts = CarParts([CarPart.j533_connector, CarPart.harness_box, CarPart.long_obdc_cable, CarPart.usbc_coupler, CarPart.mount]) def init_make(self, CP: car.CarParams): self.footnotes.insert(0, Footnote.VW_EXP_LONG)