Example #1
0
def fingerprint(logcan, sendcan, has_relay):
    if has_relay:
        # Vin query only reliably works thorugh OBDII
        bus = 1
        addr, vin = get_vin(logcan, sendcan, bus)
        _, car_fw = get_fw_versions(logcan, sendcan, bus)
    else:
        vin = VIN_UNKNOWN
        _, car_fw = set(), []

    cloudlog.warning("VIN %s", vin)
    Params().put("CarVin", vin)

    finger = gen_empty_fingerprint()
    candidate_cars = {i: all_known_cars()
                      for i in [0, 1]
                      }  # attempt fingerprint on both bus 0 and 1
    frame = 0
    frame_fingerprint = 10  # 0.1s
    car_fingerprint = None
    done = False

    while not done:
        a = messaging.get_one_can(logcan)

        for can in a.can:
            # need to independently try to fingerprint both bus 0 and 1 to work
            # for the combo black_panda and honda_bosch. Ignore extended messages
            # and VIN query response.
            # Include bus 2 for toyotas to disambiguate cars using camera messages
            # (ideally should be done for all cars but we can't for Honda Bosch)
            if can.src in range(0, 4):
                finger[can.src][can.address] = len(can.dat)
            for b in candidate_cars:
                if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \
                   can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]:
                    candidate_cars[b] = eliminate_incompatible_cars(
                        can, candidate_cars[b])

        # if we only have one car choice and the time since we got our first
        # message has elapsed, exit
        for b in candidate_cars:
            # Toyota needs higher time to fingerprint, since DSU does not broadcast immediately
            if only_toyota_left(candidate_cars[b]):
                frame_fingerprint = 100  # 1s
            if len(candidate_cars[b]) == 1:
                if frame > frame_fingerprint:
                    # fingerprint done
                    car_fingerprint = candidate_cars[b][0]

        # bail if no cars left or we've been waiting for more than 2s
        failed = all(len(cc) == 0
                     for cc in candidate_cars.values()) or frame > 200
        succeeded = car_fingerprint is not None
        done = failed or succeeded

        frame += 1

    cloudlog.warning("fingerprinted %s", car_fingerprint)
    return car_fingerprint, finger, vin, car_fw
Example #2
0
  extra: Any = None
  if args.scan:
    extra = {}
    # Honda
    for i in range(256):
      extra[(Ecu.unknown, 0x18da00f1 + (i << 8), None)] = []
      extra[(Ecu.unknown, 0x700 + i, None)] = []
      extra[(Ecu.unknown, 0x750, i)] = []
    extra = {"any": {"debug": extra}}

  time.sleep(1.)

  t = time.time()
  print("Getting vin...")
  addr, vin = get_vin(logcan, sendcan, 1, retry=10, debug=args.debug)
  print(f"VIN: {vin}")
  print("Getting VIN took %.3f s" % (time.time() - t))
  print()

  t = time.time()
  fw_vers = get_fw_versions(logcan, sendcan, 1, extra=extra, debug=args.debug, progress=True)
  _, candidates = match_fw_to_car(fw_vers)

  print()
  print("Found FW versions")
  print("{")
  for version in fw_vers:
    subaddr = None if version.subAddress == 0 else hex(version.subAddress)
    print(f"  (Ecu.{version.ecu}, {hex(version.address)}, {subaddr}): [{version.fwVersion}]")
  print("}")
Example #3
0
def fingerprint(logcan, sendcan):
    fixed_fingerprint = os.environ.get('FINGERPRINT', "")
    skip_fw_query = os.environ.get('SKIP_FW_QUERY', False)

    if not fixed_fingerprint and not skip_fw_query:
        # Vin query only reliably works thorugh OBDII
        bus = 1

        cached_params = Params().get("CarParamsCache")
        if cached_params is not None:
            cached_params = car.CarParams.from_bytes(cached_params)
            if cached_params.carName == "mock":
                cached_params = None

        if cached_params is not None and len(
                cached_params.carFw
        ) > 0 and cached_params.carVin is not VIN_UNKNOWN:
            cloudlog.warning("Using cached CarParams")
            vin = cached_params.carVin
            car_fw = list(cached_params.carFw)
        else:
            cloudlog.warning("Getting VIN & FW versions")
            _, vin = get_vin(logcan, sendcan, bus)
            car_fw = get_fw_versions(logcan, sendcan, bus)

        fw_candidates = match_fw_to_car(car_fw)
    else:
        vin = VIN_UNKNOWN
        fw_candidates, car_fw = set(), []

    cloudlog.warning("VIN %s", vin)
    Params().put("CarVin", vin)

    finger = gen_empty_fingerprint()
    candidate_cars = {i: all_known_cars()
                      for i in [0, 1]
                      }  # attempt fingerprint on both bus 0 and 1
    frame = 0
    frame_fingerprint = 10  # 0.1s
    car_fingerprint = None
    done = False

    while not done:
        a = get_one_can(logcan)

        for can in a.can:
            # need to independently try to fingerprint both bus 0 and 1 to work
            # for the combo black_panda and honda_bosch. Ignore extended messages
            # and VIN query response.
            # Include bus 2 for toyotas to disambiguate cars using camera messages
            # (ideally should be done for all cars but we can't for Honda Bosch)
            if can.src in range(0, 4):
                finger[can.src][can.address] = len(can.dat)
            for b in candidate_cars:
                if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \
                   can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]:
                    candidate_cars[b] = eliminate_incompatible_cars(
                        can, candidate_cars[b])

        # if we only have one car choice and the time since we got our first
        # message has elapsed, exit
        for b in candidate_cars:
            # Toyota needs higher time to fingerprint, since DSU does not broadcast immediately
            if only_toyota_left(candidate_cars[b]):
                frame_fingerprint = 100  # 1s
            if len(candidate_cars[b]) == 1 and frame > frame_fingerprint:
                # fingerprint done
                car_fingerprint = candidate_cars[b][0]

        # bail if no cars left or we've been waiting for more than 2s
        failed = all(len(cc) == 0
                     for cc in candidate_cars.values()) or frame > 200
        succeeded = car_fingerprint is not None
        done = failed or succeeded

        frame += 1

    source = car.CarParams.FingerprintSource.can

    # If FW query returns exactly 1 candidate, use it
    if len(fw_candidates) == 1:
        car_fingerprint = list(fw_candidates)[0]
        source = car.CarParams.FingerprintSource.fw

    if fixed_fingerprint:
        car_fingerprint = fixed_fingerprint
        source = car.CarParams.FingerprintSource.fixed

    cloudlog.warning("fingerprinted %s", car_fingerprint)
    return car_fingerprint, finger, vin, car_fw, source
Example #4
0
def fingerprint(logcan, sendcan):
  fixed_fingerprint = os.environ.get('FINGERPRINT', "")
  skip_fw_query = os.environ.get('SKIP_FW_QUERY', False)

  if not fixed_fingerprint and not skip_fw_query:
    # Vin query only reliably works thorugh OBDII
    bus = 1

    cached_params = Params().get("CarParamsCache")
    if cached_params is not None:
      cached_params = car.CarParams.from_bytes(cached_params)
      if cached_params.carName == "mock":
        cached_params = None

    if cached_params is not None and len(cached_params.carFw) > 0 and cached_params.carVin is not VIN_UNKNOWN:
      cloudlog.warning("Using cached CarParams")
      vin = cached_params.carVin
      car_fw = list(cached_params.carFw)
    else:
      cloudlog.warning("Getting VIN & FW versions")
      _, vin = get_vin(logcan, sendcan, bus)
      car_fw = get_fw_versions(logcan, sendcan)

    exact_fw_match, fw_candidates = match_fw_to_car(car_fw)
  else:
    vin = VIN_UNKNOWN
    exact_fw_match, fw_candidates, car_fw = True, set(), []

  cloudlog.warning("VIN %s", vin)
  Params().put("CarVin", vin)

  finger = gen_empty_fingerprint()
  candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]}  # attempt fingerprint on both bus 0 and 1
  frame = 0
  frame_fingerprint = 10  # 0.1s
  car_fingerprint = None
  done = False

  while not done:
    a = get_one_can(logcan)

    for can in a.can:
      # The fingerprint dict is generated for all buses, this way the car interface
      # can use it to detect a (valid) multipanda setup and initialize accordingly
      if can.src < 128:
        if can.src not in finger:
          finger[can.src] = {}
        finger[can.src][can.address] = len(can.dat)

      for b in candidate_cars:
        # Ignore extended messages and VIN query response.
        if can.src == b and can.address < 0x800 and can.address not in (0x7df, 0x7e0, 0x7e8):
          candidate_cars[b] = eliminate_incompatible_cars(can, candidate_cars[b])

    # if we only have one car choice and the time since we got our first
    # message has elapsed, exit
    for b in candidate_cars:
      if len(candidate_cars[b]) == 1 and frame > frame_fingerprint:
        # fingerprint done
        car_fingerprint = candidate_cars[b][0]

    # bail if no cars left or we've been waiting for more than 2s
    failed = (all(len(cc) == 0 for cc in candidate_cars.values()) and frame > frame_fingerprint) or frame > 200
    succeeded = car_fingerprint is not None
    done = failed or succeeded

    frame += 1

  exact_match = True
  source = car.CarParams.FingerprintSource.can

  # If FW query returns exactly 1 candidate, use it
  if len(fw_candidates) == 1:
    car_fingerprint = list(fw_candidates)[0]
    source = car.CarParams.FingerprintSource.fw
    exact_match = exact_fw_match

  if fixed_fingerprint:
    car_fingerprint = fixed_fingerprint
    source = car.CarParams.FingerprintSource.fixed

  cloudlog.event("fingerprinted", car_fingerprint=car_fingerprint,
                 source=source, fuzzy=not exact_match, fw_count=len(car_fw))
  return car_fingerprint, finger, vin, car_fw, source, exact_match
Example #5
0
def fingerprint(logcan, sendcan, has_relay):
  params = Params()
  car_params = params.get("CarParams")

  if not travis:
    cached_fingerprint = params.get('CachedFingerprint')
  else:
    cached_fingerprint = None

  if car_params is not None:
    car_params = car.CarParams.from_bytes(car_params)
  fixed_fingerprint = os.environ.get('FINGERPRINT', "")
  skip_fw_query = os.environ.get('SKIP_FW_QUERY', False)

  if has_relay and not fixed_fingerprint and not skip_fw_query:
    # Vin query only reliably works thorugh OBDII
    bus = 1

    cached_params = Params().get("CarParamsCache")
    if cached_params is not None:
      cached_params = car.CarParams.from_bytes(cached_params)
      if cached_params.carName == "mock":
        cached_params = None

    if cached_params is not None and len(cached_params.carFw) > 0 and cached_params.carVin is not VIN_UNKNOWN:
      cloudlog.warning("Using cached CarParams")
      vin = cached_params.carVin
      car_fw = list(cached_params.carFw)
    else:
      cloudlog.warning("Getting VIN & FW versions")
      _, vin = get_vin(logcan, sendcan, bus)
      car_fw = get_fw_versions(logcan, sendcan, bus)

    fw_candidates = match_fw_to_car(car_fw)
  else:
    vin = VIN_UNKNOWN
    fw_candidates, car_fw = set(), []

  cloudlog.warning("VIN %s", vin)
  Params().put("CarVin", vin)

  finger = gen_empty_fingerprint()
  candidate_cars = {i: all_known_cars() for i in [0, 1]}  # attempt fingerprint on both bus 0 and 1
  frame = 0
  frame_fingerprint = 10  # 0.1s
  car_fingerprint = None
  done = False


  if cached_fingerprint is not None and use_car_caching:  # if we previously identified a car and fingerprint and user hasn't disabled caching
    cached_fingerprint = json.loads(cached_fingerprint)
    if cached_fingerprint[0] is None or len(cached_fingerprint) < 3:
      params.delete('CachedFingerprint')
    else:
      finger[0] = {int(key): value for key, value in cached_fingerprint[2].items()}
      source = car.CarParams.FingerprintSource.can
      return (str(cached_fingerprint[0]), finger, vin, car_fw, cached_fingerprint[1])



  while not done:
    a = messaging.get_one_can(logcan)

    for can in a.can:
      # need to independently try to fingerprint both bus 0 and 1 to work
      # for the combo black_panda and honda_bosch. Ignore extended messages
      # and VIN query response.
      # Include bus 2 for toyotas to disambiguate cars using camera messages
      # (ideally should be done for all cars but we can't for Honda Bosch)
      if can.src in range(0, 4):
        finger[can.src][can.address] = len(can.dat)
      for b in candidate_cars:
        if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \
           can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]:
          candidate_cars[b] = eliminate_incompatible_cars(can, candidate_cars[b])

    # if we only have one car choice and the time since we got our first
    # message has elapsed, exit
    for b in candidate_cars:
      # Toyota needs higher time to fingerprint, since DSU does not broadcast immediately
      if only_toyota_left(candidate_cars[b]):
        frame_fingerprint = 100  # 1s
      if len(candidate_cars[b]) == 1:
        if frame > frame_fingerprint:
          # fingerprint done
          car_fingerprint = candidate_cars[b][0]
      elif len(candidate_cars[b]) < 4: # For the RAV4 2019 and Corolla 2020 LE Fingerprint problem
        if frame > 180:
          if any(("TOYOTA COROLLA TSS2 2019" in c) for c in candidate_cars[b]):
            car_fingerprint = "TOYOTA COROLLA TSS2 2019"
          if any(("TOYOTA COROLLA HYBRID TSS2 2019" in c) for c in candidate_cars[b]):
            car_fingerprint = "TOYOTA COROLLA HYBRID TSS2 2019"
          if any(("HYUNDAI IONIQ ELECTRIC LIMITED 2019" in c) for c in candidate_cars[b]):
            car_fingerprint = "HYUNDAI IONIQ ELECTRIC LIMITED 2019"

    # bail if no cars left or we've been waiting for more than 2s
    failed = all(len(cc) == 0 for cc in candidate_cars.values()) or frame > 200
    succeeded = car_fingerprint is not None
    done = failed or succeeded

    frame += 1

  source = car.CarParams.FingerprintSource.can

  # If FW query returns exactly 1 candidate, use it
  if len(fw_candidates) == 1:
    car_fingerprint = list(fw_candidates)[0]
    source = car.CarParams.FingerprintSource.fw

  if fixed_fingerprint:
    car_fingerprint = fixed_fingerprint
    source = car.CarParams.FingerprintSource.fixed

  cloudlog.warning("fingerprinted %s", car_fingerprint)
  params.put("CachedFingerprint", json.dumps([car_fingerprint, source, {int(key): value for key, value in finger[0].items()}]))
  return car_fingerprint, finger, vin, car_fw, source
def fingerprint(logcan, sendcan, has_relay):
    params = Params()
    car_params = params.get("CarParams")

    if not travis:
        cached_fingerprint = params.get('CachedFingerprint')
    else:
        cached_fingerprint = None

    if car_params is not None:
        # use already stored VIN: a new VIN query cannot be done, since panda isn't in ELM327 mode
        car_params = car.CarParams.from_bytes(car_params)
        vin = VIN_UNKNOWN if car_params.carVin == "" else car_params.carVin
    elif has_relay:
        # Vin query only reliably works thorugh OBDII
        vin = get_vin(logcan, sendcan, 1)
    else:
        vin = VIN_UNKNOWN

    cloudlog.warning("VIN %s", vin)
    Params().put("CarVin", vin)

    finger = gen_empty_fingerprint()
    candidate_cars = {i: all_known_cars()
                      for i in [0, 1]
                      }  # attempt fingerprint on both bus 0 and 1
    frame = 0
    frame_fingerprint = 10  # 0.1s
    car_fingerprint = None
    done = False

    if cached_fingerprint is not None and use_car_caching:  # if we previously identified a car and fingerprint and user hasn't disabled caching
        cached_fingerprint = json.loads(cached_fingerprint)
        finger[0] = {
            key: value
            for key, value in cached_fingerprint[1].items()
        }
        return (str(cached_fingerprint[0]), finger, vin)

    while not done:
        a = get_one_can(logcan)

        for can in a.can:
            # need to independently try to fingerprint both bus 0 and 1 to work
            # for the combo black_panda and honda_bosch. Ignore extended messages
            # and VIN query response.
            # Include bus 2 for toyotas to disambiguate cars using camera messages
            # (ideally should be done for all cars but we can't for Honda Bosch)
            if can.src in range(0, 4):
                finger[can.src][can.address] = len(can.dat)
            for b in candidate_cars:
                if (can.src == b or (only_toyota_left(candidate_cars[b]) and can.src == 2)) and \
                   can.address < 0x800 and can.address not in [0x7df, 0x7e0, 0x7e8]:
                    candidate_cars[b] = eliminate_incompatible_cars(
                        can, candidate_cars[b])

        # if we only have one car choice and the time since we got our first
        # message has elapsed, exit
        for b in candidate_cars:
            # Toyota needs higher time to fingerprint, since DSU does not broadcast immediately
            if only_toyota_left(candidate_cars[b]):
                frame_fingerprint = 100  # 1s
            if len(candidate_cars[b]) == 1:
                if frame > frame_fingerprint:
                    # fingerprint done
                    car_fingerprint = candidate_cars[b][0]

        # bail if no cars left or we've been waiting for more than 2s
        failed = all(len(cc) == 0
                     for cc in candidate_cars.values()) or frame > 200
        succeeded = car_fingerprint is not None
        done = failed or succeeded

        frame += 1

    cloudlog.warning("fingerprinted %s", car_fingerprint)
    params.put(
        "CachedFingerprint",
        json.dumps([
            car_fingerprint,
            {int(key): value
             for key, value in finger[0].items()}
        ]))
    return car_fingerprint, finger, vin