2021-06-16 21:46:34 +08:00
|
|
|
#!/usr/bin/env python3
|
2022-03-11 06:31:29 +08:00
|
|
|
import argparse
|
2021-06-16 21:46:34 +08:00
|
|
|
import binascii
|
2022-03-11 06:31:29 +08:00
|
|
|
import time
|
2021-06-16 21:46:34 +08:00
|
|
|
from collections import defaultdict
|
|
|
|
|
|
|
|
import cereal.messaging as messaging
|
2023-08-21 11:49:55 +08:00
|
|
|
from openpilot.selfdrive.debug.can_table import can_table
|
|
|
|
from openpilot.tools.lib.logreader import logreader_from_route_or_segment
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 09:06:13 +08:00
|
|
|
RED = '\033[91m'
|
|
|
|
CLEAR = '\033[0m'
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 09:06:13 +08:00
|
|
|
def update(msgs, bus, dat, low_to_high, high_to_low, quiet=False):
|
2022-03-11 06:31:29 +08:00
|
|
|
for x in msgs:
|
|
|
|
if x.which() != 'can':
|
|
|
|
continue
|
|
|
|
|
|
|
|
for y in x.can:
|
|
|
|
if y.src == bus:
|
2022-03-11 09:06:13 +08:00
|
|
|
dat[y.address] = y.dat
|
2022-03-11 06:31:29 +08:00
|
|
|
|
2022-03-11 09:06:13 +08:00
|
|
|
i = int.from_bytes(y.dat, byteorder='big')
|
2022-03-11 06:31:29 +08:00
|
|
|
l_h = low_to_high[y.address]
|
|
|
|
h_l = high_to_low[y.address]
|
|
|
|
|
|
|
|
change = None
|
|
|
|
if (i | l_h) != l_h:
|
|
|
|
low_to_high[y.address] = i | l_h
|
|
|
|
change = "+"
|
|
|
|
|
|
|
|
if (~i | h_l) != h_l:
|
|
|
|
high_to_low[y.address] = ~i | h_l
|
|
|
|
change = "-"
|
|
|
|
|
|
|
|
if change and not quiet:
|
|
|
|
print(f"{time.monotonic():.2f}\t{hex(y.address)} ({y.address})\t{change}{binascii.hexlify(y.dat)}")
|
|
|
|
|
|
|
|
|
2022-03-11 09:54:13 +08:00
|
|
|
def can_printer(bus=0, init_msgs=None, new_msgs=None, table=False):
|
2022-03-11 09:06:13 +08:00
|
|
|
logcan = messaging.sub_sock('can', timeout=10)
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 09:06:13 +08:00
|
|
|
dat = defaultdict(int)
|
2021-06-16 21:46:34 +08:00
|
|
|
low_to_high = defaultdict(int)
|
|
|
|
high_to_low = defaultdict(int)
|
|
|
|
|
2022-03-11 06:31:29 +08:00
|
|
|
if init_msgs is not None:
|
2022-03-11 09:06:13 +08:00
|
|
|
update(init_msgs, bus, dat, low_to_high, high_to_low, quiet=True)
|
|
|
|
|
|
|
|
low_to_high_init = low_to_high.copy()
|
|
|
|
high_to_low_init = high_to_low.copy()
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 06:31:29 +08:00
|
|
|
if new_msgs is not None:
|
2022-03-11 09:06:13 +08:00
|
|
|
update(new_msgs, bus, dat, low_to_high, high_to_low)
|
2022-03-11 06:31:29 +08:00
|
|
|
else:
|
|
|
|
# Live mode
|
2022-10-21 10:55:04 +08:00
|
|
|
print(f"Waiting for messages on bus {bus}")
|
2022-03-11 09:06:13 +08:00
|
|
|
try:
|
|
|
|
while 1:
|
|
|
|
can_recv = messaging.drain_sock(logcan)
|
|
|
|
update(can_recv, bus, dat, low_to_high, high_to_low)
|
|
|
|
time.sleep(0.02)
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
pass
|
|
|
|
|
|
|
|
print("\n\n")
|
2022-03-11 09:54:13 +08:00
|
|
|
tables = ""
|
2022-03-11 09:06:13 +08:00
|
|
|
for addr in sorted(dat.keys()):
|
|
|
|
init = low_to_high_init[addr] & high_to_low_init[addr]
|
|
|
|
now = low_to_high[addr] & high_to_low[addr]
|
|
|
|
d = now & ~init
|
|
|
|
if d == 0:
|
|
|
|
continue
|
|
|
|
b = d.to_bytes(len(dat[addr]), byteorder='big')
|
2022-03-11 09:54:13 +08:00
|
|
|
|
2022-03-11 09:06:13 +08:00
|
|
|
byts = ''.join([(c if c == '0' else f'{RED}{c}{CLEAR}') for c in str(binascii.hexlify(b))[2:-1]])
|
2022-03-11 09:54:13 +08:00
|
|
|
header = f"{hex(addr).ljust(6)}({str(addr).ljust(4)})"
|
|
|
|
print(header, byts)
|
|
|
|
tables += f"{header}\n"
|
|
|
|
tables += can_table(b) + "\n\n"
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 09:54:13 +08:00
|
|
|
if table:
|
|
|
|
print(tables)
|
2021-06-16 21:46:34 +08:00
|
|
|
|
2022-03-11 06:31:29 +08:00
|
|
|
if __name__ == "__main__":
|
|
|
|
desc = """Collects messages and prints when a new bit transition is observed.
|
|
|
|
This is very useful to find signals based on user triggered actions, such as blinkers and seatbelt.
|
|
|
|
Leave the script running until no new transitions are seen, then perform the action."""
|
|
|
|
parser = argparse.ArgumentParser(description=desc,
|
|
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
|
|
parser.add_argument("--bus", type=int, help="CAN bus to print out", default=0)
|
2022-03-11 09:54:13 +08:00
|
|
|
parser.add_argument("--table", action="store_true", help="Print a cabana-like table")
|
2022-10-21 10:55:04 +08:00
|
|
|
parser.add_argument("init", type=str, nargs='?', help="Route or segment to initialize with. Use empty quotes to compare against all zeros.")
|
2022-03-11 09:06:13 +08:00
|
|
|
parser.add_argument("comp", type=str, nargs='?', help="Route or segment to compare against init")
|
2022-03-11 06:31:29 +08:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
init_lr, new_lr = None, None
|
|
|
|
if args.init:
|
2022-10-21 10:55:04 +08:00
|
|
|
if args.init == '':
|
|
|
|
init_lr = []
|
|
|
|
else:
|
|
|
|
init_lr = logreader_from_route_or_segment(args.init)
|
2022-03-11 06:31:29 +08:00
|
|
|
if args.comp:
|
|
|
|
new_lr = logreader_from_route_or_segment(args.comp)
|
|
|
|
|
2022-03-11 09:54:13 +08:00
|
|
|
can_printer(args.bus, init_msgs=init_lr, new_msgs=new_lr, table=args.table)
|