old_contents: #!/usr/bin/env python3
  import os
  import usb1
  import time
  import struct
  import itertools
  import threading
  from typing import Any, List
  
  from panda import Panda
  
  JUNGLE = "JUNGLE" in os.environ
  if JUNGLE:
    from panda_jungle import PandaJungle # pylint: disable=import-error
  
  # Generate unique messages
  NUM_MESSAGES_PER_BUS = 2000
  messages = [bytes(struct.pack("Q", i)) for i in range(NUM_MESSAGES_PER_BUS)]
  tx_messages = list(itertools.chain.from_iterable(map(lambda msg: [[0xaa, None, msg, 0], [0xaa, None, msg, 1], [0xaa, None, msg, 2]], messages)))
  
  def flood_tx(panda):
    print('Sending!')
  
    BLOCK_SIZE = 50
    for i in range((len(tx_messages) + 1) // BLOCK_SIZE):
      while True:
        try:
          print(f"Sending block {BLOCK_SIZE * i}-{ BLOCK_SIZE * (i + 1)}: ", end="")
          panda.can_send_many(tx_messages[BLOCK_SIZE * i : BLOCK_SIZE * (i + 1)])
          print("OK")
          break
        except usb1.USBErrorTimeout:
          print("timeout")
  
    print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!")
  
  if __name__ == "__main__":
    serials = Panda.list()
    if JUNGLE:
      sender = Panda()
      receiver = PandaJungle()
    else:
      if len(serials) != 2:
        raise Exception("Connect two pandas to perform this test!")
      sender = Panda(serials[0])
      receiver = Panda(serials[1])
      receiver.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
  
    sender.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
    sender.set_heartbeat_disabled()
  
    # Start transmisson
    threading.Thread(target=flood_tx, args=(sender,)).start()
  
    # Receive as much as we can, and stop when there hasn't been anything for a second
    rx: List[Any] = []
    old_len = 0
    last_change = time.monotonic()
    while time.monotonic() - last_change < 1:
      if old_len < len(rx):
        last_change = time.monotonic()
      old_len = len(rx)
  
      rx.extend(receiver.can_recv())
    print(f"Received {len(rx)} messages")
  
    # Check if we received everything
    for bus in range(3):
      received_msgs = set(map(lambda m: bytes(m[2]), filter(lambda m, b=bus: m[3] == b, rx))) # type: ignore
      dropped_msgs = set(messages).difference(received_msgs)
      print(f"Bus {bus} dropped msgs: {len(list(dropped_msgs))} / {len(messages)}")
  
new_contents: #!/usr/bin/env python3
  import os
  import usb1
  import time
  import struct
  import itertools
  import threading
  from typing import Any, List
  
  from panda import Panda
  
  JUNGLE = "JUNGLE" in os.environ
  if JUNGLE:
    from panda_jungle import PandaJungle # pylint: disable=import-error
  
  # Generate unique messages
  NUM_MESSAGES_PER_BUS = 10000
  messages = [bytes(struct.pack("Q", i)) for i in range(NUM_MESSAGES_PER_BUS)]
  tx_messages = list(itertools.chain.from_iterable(map(lambda msg: [[0xaa, None, msg, 0], [0xaa, None, msg, 1], [0xaa, None, msg, 2]], messages)))
  
  def flood_tx(panda):
    print('Sending!')
    transferred = 0
    while True:
      try:
        print(f"Sending block {transferred}-{len(tx_messages)}: ", end="")
        panda.can_send_many(tx_messages[transferred:], timeout=10)
        print("OK")
        break
      except usb1.USBErrorTimeout as e:
        transferred += (e.transferred // 16)
        print("timeout, transferred: ", transferred)
  
    print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!")
  
  if __name__ == "__main__":
    serials = Panda.list()
    if JUNGLE:
      sender = Panda()
      receiver = PandaJungle()
    else:
      if len(serials) != 2:
        raise Exception("Connect two pandas to perform this test!")
      sender = Panda(serials[0])
      receiver = Panda(serials[1])
      receiver.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
  
    sender.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
    sender.set_heartbeat_disabled()
  
    # Start transmisson
    threading.Thread(target=flood_tx, args=(sender,)).start()
  
    # Receive as much as we can, and stop when there hasn't been anything for a second
    rx: List[Any] = []
    old_len = 0
    last_change = time.monotonic()
    while time.monotonic() - last_change < 1:
      if old_len < len(rx):
        last_change = time.monotonic()
      old_len = len(rx)
  
      rx.extend(receiver.can_recv())
    print(f"Received {len(rx)} messages")
  
    # Check if we received everything
    for bus in range(3):
      received_msgs = set(map(lambda m: bytes(m[2]), filter(lambda m, b=bus: m[3] == b, rx))) # type: ignore
      dropped_msgs = set(messages).difference(received_msgs)
      print(f"Bus {bus} dropped msgs: {len(list(dropped_msgs))} / {len(messages)}")
  
subject: send only what hasn't been sent yet