|
| 1 | +import os |
| 2 | +import time |
| 3 | +import random |
| 4 | +import _thread |
| 5 | +from collections import defaultdict |
| 6 | +from panda import Panda |
| 7 | +from panda_jungle import PandaJungle # pylint: disable=import-error |
| 8 | + |
| 9 | +H7_HW_TYPES = [Panda.HW_TYPE_RED_PANDA] |
| 10 | +JUNGLE_SERIAL = os.getenv("JUNGLE") |
| 11 | +H7_PANDAS_EXCLUDE = [] # type: ignore |
| 12 | +if os.getenv("H7_PANDAS_EXCLUDE"): |
| 13 | + H7_PANDAS_EXCLUDE = os.getenv("H7_PANDAS_EXCLUDE").strip().split(" ") # type: ignore |
| 14 | + |
| 15 | +#TODO: REMOVE, temporary list of CAN FD lengths, one in panda python lib MUST be used |
| 16 | +DLC_TO_LEN = [0,1,2,3,4,5,6,7,8, 12, 16, 20, 24, 32, 48] |
| 17 | + |
| 18 | +_panda_serials = [] |
| 19 | + |
| 20 | +def start_heartbeat_thread(p): |
| 21 | + def heartbeat_thread(p): |
| 22 | + while True: |
| 23 | + try: |
| 24 | + p.send_heartbeat() |
| 25 | + time.sleep(.5) |
| 26 | + except Exception: |
| 27 | + break |
| 28 | + _thread.start_new_thread(heartbeat_thread, (p,)) |
| 29 | + |
| 30 | +def panda_init(serial): |
| 31 | + p = Panda(serial=serial) |
| 32 | + assert p.recover(timeout=30) |
| 33 | + start_heartbeat_thread(p) |
| 34 | + for bus in range(3): |
| 35 | + p.set_can_speed_kbps(bus, 500) |
| 36 | + p.set_can_data_speed_kbps(bus, 2000) |
| 37 | + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) |
| 38 | + p.set_power_save(False) |
| 39 | + return p |
| 40 | + |
| 41 | +if JUNGLE_SERIAL: |
| 42 | + panda_jungle = PandaJungle(JUNGLE_SERIAL) |
| 43 | + panda_jungle.set_panda_power(False) |
| 44 | + time.sleep(2) |
| 45 | + panda_jungle.set_panda_power(True) |
| 46 | + time.sleep(4) |
| 47 | + #panda_jungle.set_can_enable(0, False) |
| 48 | + #panda_jungle.set_can_enable(1, False) |
| 49 | + #panda_jungle.set_can_enable(2, False) |
| 50 | + |
| 51 | +for serial in Panda.list(): |
| 52 | + if serial not in H7_PANDAS_EXCLUDE: |
| 53 | + p = Panda(serial=serial) |
| 54 | + if p.get_type() in H7_HW_TYPES: |
| 55 | + _panda_serials.append(serial) |
| 56 | + p.close() |
| 57 | + |
| 58 | +if len(_panda_serials) < 2: |
| 59 | + print("Minimum two H7 type pandas should be connected.") |
| 60 | + assert False |
| 61 | + |
| 62 | + |
| 63 | +def canfd_test(p_send, p_recv): |
| 64 | + for _ in range(500): |
| 65 | + sent_msgs = defaultdict(set) |
| 66 | + to_send = [] |
| 67 | + for _ in range(200): |
| 68 | + bus = random.randrange(3) |
| 69 | + for dlc in range(len(DLC_TO_LEN)): |
| 70 | + address = random.randrange(1, 1<<29) |
| 71 | + data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[dlc])]) |
| 72 | + to_send.append([address, 0, data, bus]) |
| 73 | + sent_msgs[bus].add((address, data)) |
| 74 | + |
| 75 | + p_send.can_send_many(to_send, timeout=0) |
| 76 | + |
| 77 | + while True: |
| 78 | + incoming = p_recv.can_recv() |
| 79 | + if not incoming: |
| 80 | + break |
| 81 | + for msg in incoming: |
| 82 | + address, _, data, bus = msg |
| 83 | + k = (address, bytes(data)) |
| 84 | + assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}" |
| 85 | + sent_msgs[bus].discard(k) |
| 86 | + |
| 87 | + for bus in range(3): |
| 88 | + assert not len(sent_msgs[bus]), f"loop : bus {bus} missing {len(sent_msgs[bus])} messages" |
| 89 | + |
| 90 | + # Set back to silent mode |
| 91 | + p_send.set_safety_mode(Panda.SAFETY_SILENT) |
| 92 | + p_recv.set_safety_mode(Panda.SAFETY_SILENT) |
| 93 | + p_send.set_power_save(True) |
| 94 | + p_recv.set_power_save(True) |
| 95 | + print("Got all messages intact") |
| 96 | + |
| 97 | + |
| 98 | +p_send = panda_init(_panda_serials[0]) |
| 99 | +p_recv = panda_init(_panda_serials[1]) |
| 100 | +canfd_test(p_send, p_recv) |
0 commit comments