def wrapper(*args, **kwargs): p = Panda() for i in [0, 1, 2, 0xFFFF]: p.can_clear(i) p.reset() p.close() f(*args, **kwargs)
def wrapper(): p = Panda() for i in [0, 1, 2, 0xFFFF]: p.can_clear(i) p.reset() p.close() fn()
def wrapper(panda_type=None, **kwargs): # Change panda_types to a list if panda_type is not None: if not isinstance(panda_type, list): panda_type = [panda_type] # If not done already, get panda serials and their type global _panda_serials if _panda_serials == None: _panda_serials = [] for serial in Panda.list(): p = Panda(serial=serial) _panda_serials.append((serial, p.get_type())) p.close() # Find a panda with the correct types and add the corresponding serial serials = [] for p_type in panda_type: found = False for serial, pt in _panda_serials: # Never take the same panda twice if (pt == p_type) and (serial not in serials): serials.append(serial) found = True break if not found: raise IOError( "No unused panda found for type: {}".format(p_type)) return fn(serials, **kwargs)
def wrapper(*args, **kwargs): for serial in Panda.list(): p = Panda(serial) for i in [0, 1, 2, 3, 0xFFFF]: p.can_clear(i) p.reset() p.close() f(*args, **kwargs)
def test_usb_fw(self): subprocess.check_output(f"cd {BASEDIR} && PEDAL=1 PEDAL_USB=1 scons", shell=True) self._flash_over_can(PEDAL_BUS, f"{BASEDIR}board/obj/pedal_usb.bin.signed") time.sleep(2) p = Panda(PEDAL_SERIAL) self.assertTrue(p.is_pedal()) p.close() self.assertTrue(self._listen_can_frames() > 40)
def init_panda_serials(): global panda_jungle, _panda_serials _panda_serials = [] panda_jungle.set_panda_power(True) time.sleep(5) for serial in Panda.list(): p = Panda(serial=serial) _panda_serials.append((serial, p.get_type())) p.close() print('Found', str(len(_panda_serials)), 'pandas')
def init_panda_serials(): global panda_jungle, _panda_serials _panda_serials = [] panda_jungle.set_panda_power(True) time.sleep(5) for serial in Panda.list(): if serial not in PANDAS_EXCLUDE: p = Panda(serial=serial) _panda_serials.append((serial, p.get_type())) p.close() print(f"Found {len(_panda_serials)} pandas")
def flash_release(path=None, st_serial=None): from panda import Panda, PandaDFU from zipfile import ZipFile def status(x): print("\033[1;32;40m" + x + "\033[00m") if st_serial is not None: # look for Panda panda_list = Panda.list() if len(panda_list) == 0: raise Exception( "panda not found, make sure it's connected and your user can access it" ) elif len(panda_list) > 1: raise Exception("Please only connect one panda") st_serial = panda_list[0] print("Using panda with serial %s" % st_serial) if path is None: print( "Fetching latest firmware from github.com/commaai/panda-artifacts") r = requests.get( "https://raw.githubusercontent.com/commaai/panda-artifacts/master/latest.json" ) url = json.loads(r.text)['url'] r = requests.get(url) print("Fetching firmware from %s" % url) path = io.BytesIO(r.content) zf = ZipFile(path) zf.printdir() version = zf.read("version").decode() status("0. Preparing to flash " + str(version)) code_bootstub = zf.read("bootstub.panda.bin") code_panda = zf.read("panda.bin") # enter DFU mode status("1. Entering DFU mode") panda = Panda(st_serial) panda.reset(enter_bootstub=True) panda.reset(enter_bootloader=True) time.sleep(1) # program bootstub status("2. Programming bootstub") dfu = PandaDFU(PandaDFU.st_serial_to_dfu_serial(st_serial)) dfu.program_bootstub(code_bootstub) time.sleep(1) # flash main code status("3. Flashing main code") panda = Panda(st_serial) panda.flash(code=code_panda) panda.close() # check for connection status("4. Verifying version") panda = Panda(st_serial) my_version = panda.get_version() print("dongle id: %s" % panda.get_serial()[0]) print(my_version, "should be", version) assert (str(version) == str(my_version)) # done! status("6. Success!")
class ELMCarSimulator(): def __init__(self, sn, silent=False, can_kbaud=500, can=True, can11b=True, can29b=True, lin=True): self.__p = Panda(sn if sn else Panda.list()[0]) self.__on = True self.__stop = False self.__silent = silent self.__lin_timer = None self.__lin_active = False self.__lin_enable = lin self.__lin_monitor_thread = threading.Thread(target=self.__lin_monitor) self.__can_multipart_data = None self.__can_kbaud = can_kbaud self.__can_extra_noise_msgs = deque() self.__can_enable = can self.__can11b = can11b self.__can29b = can29b self.__can_monitor_thread = threading.Thread(target=self.__can_monitor) @property def panda(self): return self.__p def stop(self): if self.__lin_timer: self.__lin_timer.cancel() self.__lin_timeout_handler() self.__stop = True def join(self): if self.__lin_monitor_thread.is_alive(): self.__lin_monitor_thread.join() if self.__can_monitor_thread.is_alive(): self.__can_monitor_thread.join() if self.__p: print("closing handle") self.__p.close() def set_enable(self, on): self.__on = on def start(self): self.panda.set_safety_mode(Panda.SAFETY_ALLOUTPUT) if self.__lin_enable: self.__lin_monitor_thread.start() if self.__can_enable: self.__can_monitor_thread.start() ######################### # LIN related functions # ######################### def __lin_monitor(self): print("STARTING LIN THREAD") self.panda.set_uart_baud(2, 10400) self.panda.kline_drain() # Toss whatever was already there lin_buff = bytearray() while not self.__stop: lin_msg = self.panda.serial_read(2) if not lin_msg: continue lin_buff += lin_msg #print(" ** Buff", lin_buff) if lin_buff.endswith( b'\x00\xc1\x33\xf1\x81\x66'): # Leading 0 is wakeup lin_buff = bytearray() self.__lin_active = True print("GOT LIN (KWP FAST) WAKEUP SIGNAL") self._lin_send(0x10, b'\xC1\x8F\xE9') self.__reset_lin_timeout() continue if self.__lin_active: msglen = lin_buff[0] & 0x7 if lin_buff[0] & 0xF8 not in (0x80, 0xC0): print("Invalid bytes at start of message") print(" BUFF", lin_buff) continue if len(lin_buff) < msglen + 4: continue if lin_checksum(lin_buff[:-1]) != lin_buff[-1]: continue self.__lin_process_msg( lin_buff[0] & 0xF8, # Priority lin_buff[1], lin_buff[2], lin_buff[3:-1]) lin_buff = bytearray() def _lin_send(self, to_addr, msg): if not self.__silent: print(" LIN Reply (%x)" % to_addr, binascii.hexlify(msg)) PHYS_ADDR = 0x80 #FUNC_ADDR = 0xC0 RECV = 0xF1 #SEND = 0x33 # Car OBD Functional Address headers = struct.pack("BBB", PHYS_ADDR | len(msg), RECV, to_addr) if not self.__silent: print(" Sending LIN", binascii.hexlify(headers + msg), hex(sum(bytearray(headers + msg)) % 0x100)) self.panda.kline_send(headers + msg) def __reset_lin_timeout(self): if self.__lin_timer: self.__lin_timer.cancel() self.__lin_timer = threading.Timer(5, self.__lin_timeout_handler) self.__lin_timer.start() def __lin_timeout_handler(self): print("LIN TIMEOUT") self.__lin_timer = None self.__lin_active = False @property def lin_active(self): return self.__lin_active def __lin_process_msg(self, priority, toaddr, fromaddr, data): self.__reset_lin_timeout() if not self.__silent and data != b'\x3E': print("LIN MSG", "Addr:", hex(toaddr), "obdLen:", len(data), binascii.hexlify(data)) outmsg = None #if data == b'\x3E': # print("KEEP ALIVE") #el if len(data) > 1: outmsg = self._process_obd(data[0], data[1]) if outmsg: obd_header = struct.pack("BB", 0x40 | data[0], data[1]) if len(outmsg) <= 5: self._lin_send(0x10, obd_header + outmsg) else: first_msg_len = min(4, len(outmsg) % 4) or 4 self._lin_send( 0x10, obd_header + b'\x01' + b'\x00' * (4 - first_msg_len) + outmsg[:first_msg_len]) for num, i in enumerate(range(first_msg_len, len(outmsg), 4)): self._lin_send( 0x10, obd_header + struct.pack('B', (num + 2) % 0x100) + outmsg[i:i + 4]) ######################### # CAN related functions # ######################### def __can_monitor(self): print("STARTING CAN THREAD") self.panda.set_can_speed_kbps(0, self.__can_kbaud) self.panda.can_recv() # Toss whatever was already there while not self.__stop: for address, ts, data, src in self.panda.can_recv(): if self.__on and src == 0 and len(data) == 8 and data[0] >= 2: if not self.__silent: print("Processing CAN message", src, hex(address), binascii.hexlify(data)) self.__can_process_msg(data[1], data[2], address, ts, data, src) elif not self.__silent: print("Rejecting CAN message", src, hex(address), binascii.hexlify(data)) def can_mode_11b(self): self.__can11b = True self.__can29b = False def can_mode_29b(self): self.__can11b = False self.__can29b = True def can_mode_11b_29b(self): self.__can11b = True self.__can29b = True def change_can_baud(self, kbaud): self.__can_kbaud = kbaud self.panda.set_can_speed_kbps(0, self.__can_kbaud) def can_add_extra_noise(self, noise_msg, addr=None): self.__can_extra_noise_msgs.append((addr, noise_msg)) def _can_send(self, addr, msg): if not self.__silent: print(" CAN Reply (%x)" % addr, binascii.hexlify(msg)) self.panda.can_send(addr, msg + b'\x00' * (8 - len(msg)), 0) if self.__can_extra_noise_msgs: noise = self.__can_extra_noise_msgs.popleft() self.panda.can_send(noise[0] if noise[0] is not None else addr, noise[1] + b'\x00' * (8 - len(noise[1])), 0) def _can_addr_matches(self, addr): if self.__can11b and (addr == 0x7DF or (addr & 0x7F8) == 0x7E0): return True if self.__can29b and (addr == 0x18db33f1 or (addr & 0x1FFF00FF) == 0x18da00f1): return True return False def __can_process_msg(self, mode, pid, address, ts, data, src): if not self.__silent: print("CAN MSG", binascii.hexlify(data[1:1 + data[0]]), "Addr:", hex(address), "Mode:", hex(mode)[2:].zfill(2), "PID:", hex(pid)[2:].zfill(2), "canLen:", len(data), binascii.hexlify(data)) if self._can_addr_matches(address) and len(data) == 8: outmsg = None if data[:3] == b'\x30\x00\x00' and len(self.__can_multipart_data): if not self.__silent: print("Request for more data") outaddr = 0x7E8 if address == 0x7DF or address == 0x7E0 else 0x18DAF110 msgnum = 1 while (self.__can_multipart_data): datalen = min(7, len(self.__can_multipart_data)) msgpiece = struct.pack( "B", 0x20 | msgnum) + self.__can_multipart_data[:datalen] self._can_send(outaddr, msgpiece) self.__can_multipart_data = self.__can_multipart_data[7:] msgnum = (msgnum + 1) % 0x10 time.sleep(0.01) else: outmsg = self._process_obd(mode, pid) if outmsg: outaddr = 0x7E8 if address == 0x7DF or address == 0x7E0 else 0x18DAF110 if len(outmsg) <= 5: self._can_send( outaddr, struct.pack("BBB", len(outmsg) + 2, 0x40 | data[1], pid) + outmsg) else: first_msg_len = min(3, len(outmsg) % 7) payload_len = len(outmsg) + 3 msgpiece = struct.pack("BBBBB", 0x10 | ((payload_len >> 8) & 0xF), payload_len & 0xFF, 0x40 | data[1], pid, 1) + outmsg[:first_msg_len] self._can_send(outaddr, msgpiece) self.__can_multipart_data = outmsg[first_msg_len:] ######################### # General OBD functions # ######################### def _process_obd(self, mode, pid): if mode == 0x01: # Mode: Show current data if pid == 0x00: # List supported things return b"\xff\xff\xff\xfe" # b"\xBE\x1F\xB8\x10" #Bitfield, random features elif pid == 0x01: # Monitor Status since DTC cleared return b"\x00\x00\x00\x00" # Bitfield, random features elif pid == 0x04: # Calculated engine load return b"\x2f" elif pid == 0x05: # Engine coolant temperature return b"\x3c" elif pid == 0x0B: # Intake manifold absolute pressure return b"\x90" elif pid == 0x0C: # Engine RPM return b"\x1A\xF8" elif pid == 0x0D: # Vehicle Speed return b"\x53" elif pid == 0x10: # MAF air flow rate return b"\x01\xA0" elif pid == 0x11: # Throttle Position return b"\x90" elif pid == 0x33: # Absolute Barometric Pressure return b"\x90" elif mode == 0x09: # Mode: Request vehicle information if pid == 0x02: # Show VIN return b"1D4GP00R55B123456" if pid == 0xFC: # test long multi message. Ligned up for LIN responses return b''.join((struct.pack(">BBH", 0xAA, 0xAA, num + 1) for num in range(80))) if pid == 0xFD: # test long multi message parts = (b'\xAA\xAA\xAA' + struct.pack(">I", num) for num in range(80)) return b'\xAA\xAA\xAA' + b''.join(parts) if pid == 0xFE: # test very long multi message parts = (b'\xAA\xAA\xAA' + struct.pack(">I", num) for num in range(584)) return b'\xAA\xAA\xAA' + b''.join(parts) + b'\xAA' if pid == 0xFF: return b'\xAA\x00\x00' + \ b"".join(((b'\xAA' * 5) + struct.pack(">H", num + 1) for num in range(584)))
# 'COMPUTER_BRAKE_REQUEST': 1, # 'COMPUTER_BRAKE_REQUEST_2': 1, # 'COUNTER': 0, # 'CRUISE_BOH2': 0, # 'CRUISE_BOH3': 0, # 'CRUISE_CANCEL_CMD': 1, # 'CRUISE_FAULT_CMD': 0, # 'CRUISE_OVERRIDE': 1, # 'CRUISE_STATES': 0, # 'FCW': 'no_fcw', # 'SET_ME_0X80': 128, # 'ZEROS_BOH': 0, # 'ZEROS_BOH4': 0, # 'ZEROS_BOH6': 0} print("Press Enter to send braking commands") idx_counter = 1 total_cmds_sent = 0 try: while raw_input() == '': for i in range(100): cmd = create_brake_command(True, True, True, 0, idx_counter) print("Sending: " + str(cmd) + " (#" + str(total_cmds_sent) + ")") panda.can_send(cmd[0], cmd[2], 0) idx_counter += 1 idx_counter %= 4 total_cmds_sent += 1 except KeyboardInterrupt: panda.close()
if JUNGLE_SERIAL: panda_jungle = PandaJungle(JUNGLE_SERIAL) panda_jungle.set_panda_power(False) time.sleep(2) panda_jungle.set_panda_power(True) time.sleep(4) #panda_jungle.set_can_enable(0, False) #panda_jungle.set_can_enable(1, False) #panda_jungle.set_can_enable(2, False) for serial in Panda.list(): if serial not in H7_PANDAS_EXCLUDE: p = Panda(serial=serial) if p.get_type() in H7_HW_TYPES: _panda_serials.append(serial) p.close() if len(_panda_serials) < 2: print("Minimum two H7 type pandas should be connected.") assert False def canfd_test(p_send, p_recv): for _ in range(500): sent_msgs = defaultdict(set) to_send = [] for _ in range(200): bus = random.randrange(3) for dlc in range(len(DLC_TO_LEN)): address = random.randrange(1, 1 << 29) data = bytes(
def flash_release(path=None, st_serial=None): from panda import Panda, PandaDFU, ESPROM, CesantaFlasher from zipfile import ZipFile def status(x): print("\033[1;32;40m" + x + "\033[00m") if st_serial == None: # look for Panda panda_list = Panda.list() if len(panda_list) == 0: raise Exception( "panda not found, make sure it's connected and your user can access it" ) elif len(panda_list) > 1: raise Exception("Please only connect one panda") st_serial = panda_list[0] print("Using panda with serial %s" % st_serial) if path == None: print( "Fetching latest firmware from github.com/commaai/panda-artifacts") r = requests.get( "https://raw.githubusercontent.com/commaai/panda-artifacts/master/latest.json" ) url = json.loads(r.text)['url'] r = requests.get(url) print("Fetching firmware from %s" % url) path = io.StringIO(r.content) zf = ZipFile(path) zf.printdir() version = zf.read("version") status("0. Preparing to flash " + version) code_bootstub = zf.read("bootstub.panda.bin") code_panda = zf.read("panda.bin") code_boot_15 = zf.read("boot_v1.5.bin") code_boot_15 = code_boot_15[0:2] + "\x00\x30" + code_boot_15[4:] code_user1 = zf.read("user1.bin") code_user2 = zf.read("user2.bin") # enter DFU mode status("1. Entering DFU mode") panda = Panda(st_serial) panda.enter_bootloader() time.sleep(1) # program bootstub status("2. Programming bootstub") dfu = PandaDFU(PandaDFU.st_serial_to_dfu_serial(st_serial)) dfu.program_bootstub(code_bootstub) time.sleep(1) # flash main code status("3. Flashing main code") panda = Panda(st_serial) panda.flash(code=code_panda) panda.close() # flashing ESP if panda.is_white(): status("4. Flashing ESP (slow!)") align = lambda x, sz=0x1000: x + "\xFF" * ((sz - len(x)) % sz) esp = ESPROM(st_serial) esp.connect() flasher = CesantaFlasher(esp, 230400) flasher.flash_write(0x0, align(code_boot_15), True) flasher.flash_write(0x1000, align(code_user1), True) flasher.flash_write(0x81000, align(code_user2), True) flasher.flash_write(0x3FE000, "\xFF" * 0x1000) flasher.boot_fw() del flasher del esp time.sleep(1) else: status("4. No ESP in non-white panda") # check for connection status("5. Verifying version") panda = Panda(st_serial) my_version = panda.get_version() print("dongle id: %s" % panda.get_serial()[0]) print(my_version, "should be", version) assert (str(version) == str(my_version)) # done! status("6. Success!")
class HondaCivicCan(object): def __init__(self): print("Loading CAN DBC file...") self.can_msg_parser = load_dbc_file( 'honda_civic_touring_2016_can_for_cantools.dbc') print("Connecting to Panda board...") self.panda = Panda() print("Ready.") # ROS subscribers to send the commands? def decode_msg(self, message): """Return a dictionary with the decoded message Looks like: {'STEER_ANGLE_OFFSET': -0.5, 'CHECKSUM': 4, 'COUNTER': 0, 'STEER_ANGLE_RATE': -338, 'STEER_WHEEL_ANGLE': 86.5, 'STEER_ANGLE': 89.4} """ # A message looks like: # (1024, 59709, bytearray(b'\x00\x00\x02\x00\x02'), 0) return self.can_msg_parser.decode_message(message[0], message[2]) def encode_msg(self, frame_id, message): """Return the message in a dictionary encoded. """ return self.can_msg_parser.encode_message(frame_id, message) def run(self): self.panda.set_safety_mode(self.panda.SAFETY_HONDA) try: while True: data = self.panda.can_recv() for msg in data: decoded_msg = None try: decoded_msg = self.decode_msg(msg) except KeyError: pass except ValueError: pass if decoded_msg: # print decoded_msg # continue for k in decoded_msg.keys(): if 'STEER_TORQUE' in k: print decoded_msg print msg print "---" steer_msg = create_steering_control(1000, 0)[0] print steer_msg print self.decode_msg(steer_msg) print self.panda.can_send(steer_msg[0], steer_msg[2], 0) # msg_to_send = self.encode_msg(891, {'CHECKSUM': 15, 'COUNTER': 1, 'WIPERS': 1}) # self.panda.can_send(msg[0], '\x00\x00\x01 \x00\x00\x00\x00', 0) # for pending_msg in self.pending_msg: # panda.can_send(0xXXXX, pending_msg, 0) except KeyboardInterrupt: self.panda.close()
def flash_release(path=None, st_serial=None): from panda import Panda, PandaDFU, ESPROM, CesantaFlasher from zipfile import ZipFile def status(x): print("\033[1;32;40m"+x+"\033[00m") if st_serial == None: # look for Panda panda_list = Panda.list() if len(panda_list) == 0: raise Exception("panda not found, make sure it's connected and your user can access it") elif len(panda_list) > 1: raise Exception("Please only connect one panda") st_serial = panda_list[0] print("Using panda with serial %s" % st_serial) if path == None: print("Fetching latest firmware from github.com/commaai/panda-artifacts") r = requests.get("https://raw.githubusercontent.com/commaai/panda-artifacts/master/latest.json") url = json.loads(r.text)['url'] r = requests.get(url) print("Fetching firmware from %s" % url) path = StringIO.StringIO(r.content) zf = ZipFile(path) zf.printdir() version = zf.read("version") status("0. Preparing to flash "+version) code_bootstub = zf.read("bootstub.panda.bin") code_panda = zf.read("panda.bin") code_boot_15 = zf.read("boot_v1.5.bin") code_boot_15 = code_boot_15[0:2] + "\x00\x30" + code_boot_15[4:] code_user1 = zf.read("user1.bin") code_user2 = zf.read("user2.bin") # enter DFU mode status("1. Entering DFU mode") panda = Panda(st_serial) panda.enter_bootloader() time.sleep(1) # program bootstub status("2. Programming bootstub") dfu = PandaDFU(PandaDFU.st_serial_to_dfu_serial(st_serial)) dfu.program_bootstub(code_bootstub) time.sleep(1) # flash main code status("3. Flashing main code") panda = Panda(st_serial) panda.flash(code=code_panda) panda.close() # flashing ESP status("4. Flashing ESP (slow!)") align = lambda x, sz=0x1000: x+"\xFF"*((sz-len(x)) % sz) esp = ESPROM(st_serial) esp.connect() flasher = CesantaFlasher(esp, 230400) flasher.flash_write(0x0, align(code_boot_15), True) flasher.flash_write(0x1000, align(code_user1), True) flasher.flash_write(0x81000, align(code_user2), True) flasher.flash_write(0x3FE000, "\xFF"*0x1000) flasher.boot_fw() del flasher del esp time.sleep(1) # check for connection status("5. Verifying version") panda = Panda(st_serial) my_version = panda.get_version() print("dongle id: %s" % panda.get_serial()[0]) print(my_version, "should be", version) assert(str(version) == str(my_version)) # done! status("6. Success!")