import os from common.basedir import BASEDIR def get_attr_from_cars(attr, result=dict, combine_brands=True): # read all the folders in selfdrive/car and return a dict where: # - keys are all the car models # - values are attr values from all car folders result = result() for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]: try: car_name = car_folder.split('/')[-1] values = __import__('selfdrive.car.%s.values' % car_name, fromlist=[attr]) if hasattr(values, attr): attr_values = getattr(values, attr) else: continue if isinstance(attr_values, dict): for f, v in attr_values.items(): if combine_brands: result[f] = v else: if car_name not in result: result[car_name] = {} result[car_name][f] = v elif isinstance(attr_values, list): result += attr_values except (ImportError, IOError): pass return result FW_VERSIONS = get_attr_from_cars('FW_VERSIONS') _FINGERPRINTS = get_attr_from_cars('FINGERPRINTS') IGNORED_FINGERPRINTS = get_attr_from_cars('IGNORED_FINGERPRINTS', list) _DEBUG_ADDRESS = {1880: 8} # reserved for debug purposes def is_valid_for_fingerprint(msg, car_fingerprint): adr = msg.address # ignore addresses that are more than 11 bits return (adr in car_fingerprint and car_fingerprint[adr] == len(msg.dat)) or adr >= 0x800 def eliminate_incompatible_cars(msg, candidate_cars): """Removes cars that could not have sent msg. Inputs: msg: A cereal/log CanData message from the car. candidate_cars: A list of cars to consider. Returns: A list containing the subset of candidate_cars that could have sent msg. """ compatible_cars = [] for car_name in candidate_cars: if car_name in IGNORED_FINGERPRINTS: continue car_fingerprints = _FINGERPRINTS[car_name] for fingerprint in car_fingerprints: fingerprint.update(_DEBUG_ADDRESS) # add alien debug address if is_valid_for_fingerprint(msg, fingerprint): compatible_cars.append(car_name) break return compatible_cars def all_known_cars(): """Returns a list of all known car strings.""" return list(_FINGERPRINTS.keys())