Skip to content

Commit 89e925f

Browse files
authored
Feature canplayer (hardbyte#102)
Message playback support. Closes hardbyte#96 While capturing a db file is useful for offline analysis it can be very useful to "replay" a captured session. - Implementation currently only replays sqlite3 .db files - can_player.py has been added to the setup as a new script
1 parent 24f44d8 commit 89e925f

6 files changed

Lines changed: 530 additions & 321 deletions

File tree

bin/can_player.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python
2+
"""
3+
can_player.py replays CAN traffic saved with can_logger.py back
4+
to a CAN bus.
5+
6+
Similar to canplayer in the can-utils package.
7+
"""
8+
from __future__ import print_function
9+
import datetime
10+
import argparse
11+
12+
import can
13+
from can.util import MessageSync
14+
15+
if __name__ == "__main__":
16+
17+
parser = argparse.ArgumentParser(description="Replay CAN traffic")
18+
19+
parser.add_argument("-f", "--file_name", dest="log_file",
20+
help="""Path and base log filename, extension can be .txt, .asc, .csv, .db, .npz""",
21+
default=None)
22+
23+
parser.add_argument("-v", action="count", dest="verbosity",
24+
help='''Also print can frames to stdout.
25+
You can add several of these to enable debugging''', default=2)
26+
27+
parser.add_argument('-c', '--channel',
28+
help='''Most backend interfaces require some sort of channel.
29+
For example with the serial interface the channel might be a rfcomm device: "/dev/rfcomm0"
30+
With the socketcan interfaces valid channel examples include: "can0", "vcan0"''')
31+
32+
parser.add_argument('-i', '--interface', dest="interface",
33+
help='''Specify the backend CAN interface to use. If left blank,
34+
fall back to reading from configuration files.''',
35+
choices=can.interface.VALID_INTERFACES)
36+
37+
parser.add_argument('--ignore-timestamps', dest='timestamps',
38+
help='''Ignore timestamps (send all frames immediately with minimum gap between
39+
frames)''', action='store_false')
40+
41+
parser.add_argument('-g', '--gap', type=float, help='''<ms> minimum time between replayed frames''')
42+
parser.add_argument('-s', '--skip', type=float, default=60*60*24,
43+
help='''<s> skip gaps greater than 's' seconds''')
44+
45+
parser.add_argument('infile', metavar='input-file', type=str,
46+
help='The file to replay. Supported types: .db')
47+
48+
results = parser.parse_args()
49+
50+
verbosity = results.verbosity
51+
gap = 0.0001 if results.gap is None else results.gap
52+
53+
logging_level_name = ['critical', 'error', 'warning', 'info', 'debug', 'subdebug'][min(5, verbosity)]
54+
can.set_logging_level(logging_level_name)
55+
56+
bus = can.interface.Bus(results.channel, bustype=results.interface)
57+
58+
player = can.LogReader(results.infile)
59+
60+
in_sync = MessageSync(player, timestamps=True, skip=results.skip)
61+
62+
print('Can LogReader (Started on {})'.format(
63+
datetime.datetime.now()))
64+
65+
try:
66+
for m in in_sync:
67+
bus.send(m)
68+
except KeyboardInterrupt:
69+
pass
70+
finally:
71+
bus.shutdown()
72+

0 commit comments

Comments
 (0)