Exemple #1
0
def fingerprint(logcan, timeout):
    if os.getenv("SIMULATOR") is not None or logcan is None:
        return ("simulator", None)
    elif os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None)

    finger_st = sec_since_boot()

    cloudlog.warning("waiting for fingerprint...")
    candidate_cars = all_known_cars()
    finger = {}
    st = None
    while 1:
        for a in messaging.drain_sock(logcan, wait_for_one=True):
            if st is None:
                st = sec_since_boot()
            for can in a.can:
                if can.src == 0:
                    finger[can.address] = len(can.dat)
                candidate_cars = eliminate_incompatible_cars(
                    can, candidate_cars)

        ts = sec_since_boot()
        # if we only have one car choice and it's been 100ms since we got our first message, exit
        if len(candidate_cars) == 1 and st is not None and (ts - st) > 0.1:
            break
        # bail if no cars left or we've been waiting too long
        elif len(candidate_cars) == 0 or (timeout
                                          and ts - finger_st > timeout):
            return None, finger

    cloudlog.warning("fingerprinted %s", candidate_cars[0])
    return (candidate_cars[0], finger)
Exemple #2
0
def fingerprint(logcan, timeout):
  if os.getenv("SIMULATOR2") is not None:
    return ("simulator2", None)

  finger_st = sec_since_boot()

  cloudlog.warning("waiting for fingerprint...")
  candidate_cars = all_known_cars()
  finger = {}
  st = None
  while 1:
    for a in messaging.drain_sock(logcan, wait_for_one=True):
      if st is None:
        st = sec_since_boot()
      for can in a.can:
        if can.src == 0:
          finger[can.address] = len(can.dat)
        candidate_cars = eliminate_incompatible_cars(can, candidate_cars)

    ts = sec_since_boot()
    # if we only have one car choice and the time_fingerprint since we got our first
    # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not
    # broadcast immediately
    if len(candidate_cars) == 1 and st is not None:
      # TODO: better way to decide to wait more if Toyota
      time_fingerprint = 1.0 if ("TOYOTA" in candidate_cars[0] or "LEXUS" in candidate_cars[0]) else 0.1
      if (ts-st) > time_fingerprint:
        break

    # bail if no cars left or we've been waiting too long
    elif len(candidate_cars) == 0 or (timeout and ts-finger_st > timeout):
      return None, finger

  cloudlog.warning("fingerprinted %s", candidate_cars[0])
  return (candidate_cars[0], finger)
Exemple #3
0
def fingerprint(logcan, timeout):
    if os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None)
    elif os.getenv("SIMULATOR") is not None:
        return ("simulator", None)

    cloudlog.warning("waiting for fingerprint...")
    candidate_cars = all_known_cars()
    finger = {}
    st = None
    st_passive = sec_since_boot()  # only relevant when passive
    can_seen = False
    while 1:
        for a in messaging.drain_sock(logcan):
            for can in a.can:
                can_seen = True
                # ignore everything not on bus 0 and with more than 11 bits,
                # which are ussually sporadic and hard to include in fingerprints
                if can.src == 0 and can.address < 0x800:
                    finger[can.address] = len(can.dat)
                    candidate_cars = eliminate_incompatible_cars(
                        can, candidate_cars)

        if st is None and can_seen:
            st = sec_since_boot()  # start time
        ts = sec_since_boot()
        # if we only have one car choice and the time_fingerprint since we got our first
        # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not
        # broadcast immediately
        if len(candidate_cars) == 1 and st is not None:
            # TODO: better way to decide to wait more if Toyota
            time_fingerprint = 1.0 if ("TOYOTA" in candidate_cars[0] or "LEXUS"
                                       in candidate_cars[0]) else 0.1
            if (ts - st) > time_fingerprint:
                break

        # bail if no cars left or we've been waiting too long
        elif len(candidate_cars) == 0 or (timeout and
                                          (ts - st_passive) > timeout):
            #return None, finger
            print "Fingerprinting Failed: Returning Tesla (based on branch)"
            return "TESLA MODEL S", finger

        time.sleep(0.01)

    cloudlog.warning("fingerprinted %s", candidate_cars[0])
    return (candidate_cars[0], finger)
Exemple #4
0
def fingerprint(logcan, sendcan, is_panda_black):
    if os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None, "")
    elif os.getenv("SIMULATOR") is not None:
        return ("simulator", None, "")

    params = Params()
    car_params = params.get("CarParams")

    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 is_panda_black:
        # 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 = {i: {} for i in range(0, 4)}  # collect on all buses
    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.recv_one(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)
            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]:
                    finger[can.src][can.address] = len(can.dat)
                    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.itervalues()) 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
Exemple #5
0
def fingerprint(logcan, sendcan):
    if os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None, "")
    elif os.getenv("SIMULATOR") is not None:
        return ("simulator", None, "")

    finger = {}
    cloudlog.warning("waiting for fingerprint...")
    candidate_cars = all_known_cars()
    can_seen_ts = None
    can_seen = False

    # works on standard 11-bit addresses for diagnostic. Tested on Toyota and Subaru;
    # Honda uses the extended 29-bit addresses, and unfortunately only works from OBDII
    vin_query_msg = [[0x7df, 0, '\x02\x09\x02'.ljust(8, "\x00"), 0],
                     [0x7e0, 0, '\x30'.ljust(8, "\x00"), 0]]

    vin_cnts = [1, 2]  # number of messages to wait for at each iteration
    vin_step = 0
    vin_cnt = 0
    vin_responded = False
    vin_never_responded = True
    vin_dat = []
    vin = ""

    while 1:
        for a in messaging.drain_sock(logcan):
            for can in a.can:
                can_seen = True

                # have we got a VIN query response?
                if can.src == 0 and can.address == 0x7e8:
                    vin_never_responded = False
                    # basic sanity checks on ISO-TP response
                    if is_vin_response_valid(can.dat, vin_step, vin_cnt):
                        vin_dat += can.dat[2:] if vin_step == 0 else can.dat[1:]
                        vin_cnt += 1
                        if vin_cnt == vin_cnts[vin_step]:
                            vin_responded = True
                            vin_step += 1

                # ignore everything not on bus 0 and with more than 11 bits,
                # which are ussually sporadic and hard to include in fingerprints.
                # also exclude VIN query response on 0x7e8
                if can.src == 0 and can.address < 0x800 and can.address != 0x7e8:
                    finger[can.address] = len(can.dat)
                    candidate_cars = eliminate_incompatible_cars(
                        can, candidate_cars)

        if can_seen_ts is None and can_seen:
            can_seen_ts = sec_since_boot()  # start time
        ts = sec_since_boot()
        # if we only have one car choice and the time_fingerprint since we got our first
        # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not
        # broadcast immediately
        if len(candidate_cars) == 1 and can_seen_ts is not None:
            time_fingerprint = 1.0 if ("TOYOTA" in candidate_cars[0] or "LEXUS"
                                       in candidate_cars[0]) else 0.1
            if (ts - can_seen_ts) > time_fingerprint:
                break

        # bail if no cars left or we've been waiting for more than 2s since can_seen
        elif len(candidate_cars) == 0 or (can_seen_ts is not None and
                                          (ts - can_seen_ts) > 2.):
            return None, finger, ""

        # keep sending VIN qury if ECU isn't responsing.
        # sendcan is probably not ready due to the zmq slow joiner syndrome
        if can_seen and (vin_never_responded or
                         (vin_responded and vin_step < len(vin_cnts))):
            sendcan.send(
                can_list_to_can_capnp([vin_query_msg[vin_step]],
                                      msgtype='sendcan'))
            vin_responded = False
            vin_cnt = 0

        time.sleep(0.01)

    # only report vin if procedure is finished
    if vin_step == len(vin_cnts) and vin_cnt == vin_cnts[-1]:
        vin = "".join(vin_dat[3:])

    cloudlog.warning("fingerprinted %s", candidate_cars[0])
    cloudlog.warning("VIN %s", vin)
    return candidate_cars[0], finger, vin
Exemple #6
0
def fingerprint(logcan, sendcan):
    if os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None, "")
    elif os.getenv("SIMULATOR") is not None:
        return ("simulator", None, "")

    finger = {0: {}, 2: {}}  # collect on bus 0 or 2
    cloudlog.warning("waiting for fingerprint...")
    candidate_cars = all_known_cars()
    can_seen_frame = None
    can_seen = False

    # works on standard 11-bit addresses for diagnostic. Tested on Toyota and Subaru;
    # Honda uses the extended 29-bit addresses, and unfortunately only works from OBDII
    vin_query_msg = [[0x7df, 0, '\x02\x09\x02'.ljust(8, "\x00"), 0],
                     [0x7e0, 0, '\x30'.ljust(8, "\x00"), 0]]

    vin_cnts = [1, 2]  # number of messages to wait for at each iteration
    vin_step = 0
    vin_cnt = 0
    vin_responded = False
    vin_never_responded = True
    vin_dat = []
    vin = ""

    frame = 0

    while True:
        a = messaging.recv_one(logcan)

        for can in a.can:
            can_seen = True

            # have we got a VIN query response?
            if can.src == 0 and can.address == 0x7e8:
                vin_never_responded = False
                # basic sanity checks on ISO-TP response
                if is_vin_response_valid(can.dat, vin_step, vin_cnt):
                    vin_dat += can.dat[2:] if vin_step == 0 else can.dat[1:]
                    vin_cnt += 1
                    if vin_cnt == vin_cnts[vin_step]:
                        vin_responded = True
                        vin_step += 1

            # ignore everything not on bus 0 and with more than 11 bits,
            # which are ussually sporadic and hard to include in fingerprints.
            # also exclude VIN query response on 0x7e8.
            # 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 == 0 or (only_toyota_left(candidate_cars) and can.src == 2)) and \
               can.address < 0x800 and can.address != 0x7e8:
                finger[can.src][can.address] = len(can.dat)
                candidate_cars = eliminate_incompatible_cars(
                    can, candidate_cars)

        if can_seen_frame is None and can_seen:
            can_seen_frame = frame

        # if we only have one car choice and the time_fingerprint since we got our first
        # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not
        # broadcast immediately
        if len(candidate_cars) == 1 and can_seen_frame is not None:
            time_fingerprint = 1.0 if only_toyota_left(candidate_cars) else 0.1
            if (frame - can_seen_frame) > (time_fingerprint * 100):
                break

        # bail if no cars left or we've been waiting for more than 2s since can_seen
        elif len(candidate_cars) == 0 or (can_seen_frame is not None and
                                          (frame - can_seen_frame) > 200):
            return None, finger, ""

        # keep sending VIN qury if ECU isn't responsing.
        # sendcan is probably not ready due to the zmq slow joiner syndrome
        # TODO: VIN query temporarily disabled until we have the harness
        if False and can_seen and (vin_never_responded or
                                   (vin_responded
                                    and vin_step < len(vin_cnts))):
            sendcan.send(
                can_list_to_can_capnp([vin_query_msg[vin_step]],
                                      msgtype='sendcan'))
            vin_responded = False
            vin_cnt = 0

        frame += 1

    # only report vin if procedure is finished
    if vin_step == len(vin_cnts) and vin_cnt == vin_cnts[-1]:
        vin = "".join(vin_dat[3:])

    cloudlog.warning("fingerprinted %s", candidate_cars[0])
    cloudlog.warning("VIN %s", vin)
    return candidate_cars[0], finger, vin
Exemple #7
0
msgs = {}
"""""
while True:
  lc = messaging.recv_sock(logcan, True)
  for c in lc.can:
    # read also msgs sent by EON on CAN bus 0x80 and filter out the
    # addr with more than 11 bits
    if c.src%0x80 == 0 and c.address < 0x800:
      msgs[c.address] = len(c.dat)

  fingerprint = ', '.join("%d: %d" % v for v in sorted(msgs.items()))

  print "number of messages:", len(msgs)
  print "fingerprint", fingerprint
""" ""
candidate_cars = all_known_cars()
finger = {}
st = None
st_passive = sec_since_boot()  # only relevant when passive
can_seen = False
i = 100
while i:
    i = i - 1
    for a in messaging.drain_sock(logcan):
        for can in a.can:
            can_seen = True
            # ignore everything not on bus 0 and with more than 11 bits,
            # which are ussually sporadic and hard to include in fingerprints
            if can.src == 0 and can.address < 0x800:
                finger[can.address] = len(can.dat)
                candidate_cars = eliminate_incompatible_cars(
Exemple #8
0
def fingerprint(logcan, timeout):
    if os.getenv("SIMULATOR2") is not None:
        return ("simulator2", None)
    elif os.getenv("SIMULATOR") is not None:
        return ("simulator", None)

    params = Params()

    cached_fingerprint = params.get('CachedFingerprint')
    if cached_fingerprint is not None and kegman.get(
            "useCarCaching", True
    ):  # if we previously identified a car and fingerprint and user hasn't disabled caching
        cached_fingerprint = json.loads(cached_fingerprint)
        try:
            with open("/data/kegman.json", "r") as f:
                cloudlog.warning(str(f.read()))
        except:
            pass
        try:
            with open("/data/params/d/ControlsParams", "r") as f:
                cloudlog.warning(f.read())
        except:
            pass
        try:
            with open("/data/params/d/LiveParameters", "r") as f:
                cloudlog.warning(f.read())
        except:
            pass
        return (str(cached_fingerprint[0]), {
            long(key): value
            for key, value in cached_fingerprint[1].items()
        })  # not sure if dict of longs is required

    cloudlog.warning("waiting for fingerprint...")
    candidate_cars = all_known_cars()
    finger = {}
    st = None
    st_passive = sec_since_boot()  # only relevant when passive
    can_seen = False
    while 1:
        for a in messaging.drain_sock(logcan):
            for can in a.can:
                can_seen = True
                # ignore everything not on bus 0 and with more than 11 bits,
                # which are ussually sporadic and hard to include in fingerprints
                if can.src == 0 and can.address < 0x800:
                    finger[can.address] = len(can.dat)
                    candidate_cars = eliminate_incompatible_cars(
                        can, candidate_cars)

        if st is None and can_seen:
            st = sec_since_boot()  # start time
        ts = sec_since_boot()
        # if we only have one car choice and the time_fingerprint since we got our first
        # message has elapsed, exit. Toyota needs higher time_fingerprint, since DSU does not
        # broadcast immediately
        if len(candidate_cars) == 1 and st is not None:
            # TODO: better way to decide to wait more if Toyota
            time_fingerprint = 1.0 if ("TOYOTA" in candidate_cars[0] or "LEXUS"
                                       in candidate_cars[0]) else 0.1
            if (ts - st) > time_fingerprint:
                break

        # bail if no cars left or we've been waiting too long
        elif len(candidate_cars) == 0 or (timeout and
                                          (ts - st_passive) > timeout):
            return None, finger

        time.sleep(0.01)
    try:
        with open("/data/kegman.json", "r") as f:
            cloudlog.warning(str(f.read()))
    except:
        pass
    try:
        with open("/data/params/d/ControlsParams", "r") as f:
            cloudlog.warning(f.read())
    except:
        pass
    try:
        with open("/data/params/d/LiveParameters", "r") as f:
            cloudlog.warning(f.read())
    except:
        pass

    cloudlog.warning("fingerprinted %s", candidate_cars[0])

    params.put("CachedFingerprint",
               json.dumps([
                   candidate_cars[0],
                   {int(key): value
                    for key, value in finger.items()}
               ]))  # probably can remove long to int conversion
    return (candidate_cars[0], finger)
    "975b26878285314d|2018-12-25--14-42-13",  # CHRYSLER PACIFICA HYBRID 2018
    "8ae193ceb56a0efe|2018-06-18--20-07-32",  # TOYOTA RAV4 HYBRID 2017
    "a893a80e5c5f72c8|2019-01-14--20-02-59",  # HYUNDAI GENESIS 2018
    "49c73650e65ff465|2018-11-19--16-58-04",  # HOLDEN ASTRA RS-V BK 2017
    "d2d8152227f7cb82|2018-07-25--13-40-56",  # TOYOTA CAMRY 2018
    "07cb8a788c31f645|2018-06-17--18-50-29",  # mock
    "c9d60e5e02c04c5c|2018-01-08--16-01-49",  # HONDA CR-V 2016 TOURING
    "1632088eda5e6c4d|2018-06-07--08-03-18",  # HONDA CIVIC HATCHBACK 2017 SEDAN/COUPE 2019
    "fbd011384db5e669|2018-07-26--20-51-48",  # TOYOTA CAMRY HYBRID 2018
]

if __name__ == "__main__":

    # TODO: add routes for untested cars and fail test if we have an untested car
    tested_cars = [keys["carFingerprint"] for route, keys in routes.items()]
    for car_model in all_known_cars():
        if car_model not in tested_cars:
            print "***** WARNING: %s not tested *****" % car_model

    results = {}
    for route, checks in routes.items():
        if route not in non_public_routes:
            get_route_logs(route)
        elif "UNLOGGER_PATH" not in os.environ:
            continue

        for _ in range(3):
            shutil.rmtree('/data/params')
            manager.gctx = {}
            params = Params()
            params.manager_start()