Skip to content

Commit 79d6970

Browse files
committed
Merge the CAN viewer terminal application into python-can
See: hardbyte#370 and Lauszus/python_can_viewer#2
1 parent 090f380 commit 79d6970

9 files changed

Lines changed: 1227 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ __pycache__/
1515
# Distribution / packaging
1616
.Python
1717
env/
18+
venv/
1819
build/
1920
develop-eggs/
2021
dist/

CONTRIBUTORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ Eduard Bröcker <eduard@gmx.de>
2121
Boris Wenzlaff
2222
Pierre-Luc Tessier Gagné
2323
Felix Divo <felix.divo@gmail.com>
24+
Kristian Sloth Lauszus <lauszus@gmail.com>

can/scripts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# coding: utf-8
33

44
"""
5-
This module contains various scripts, like a logfile writer and a logfile player.
5+
This module contains various scripts, like a logfile writer, a logfile player and a terminal viewer application.
66
77
.. note::
88
The scripts reside in here so they can be launched as modules. That makes them

can/scripts/viewer.py

Lines changed: 602 additions & 0 deletions
Large diffs are not rendered by default.

doc/images/viewer.png

508 KB
Loading

doc/scripts.rst

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ They can either be called by for example ``python -m can.logger`` or ``can_logge
77
The scripts are internally placed in the module ``can.scripts.*``,
88
so they could also be launched by ``python -m can.scripts.logger``.
99

10-
1110
can.logger
1211
----------
1312

@@ -86,3 +85,102 @@ Command line help, called with ``--help``::
8685
minimum gap between frames)
8786
-g GAP, --gap GAP <s> minimum time between replayed frames
8887
-s SKIP, --skip SKIP <s> skip gaps greater than 's' seconds
88+
89+
can.viewer
90+
----------
91+
92+
A screenshot of the application can be seen below:
93+
94+
.. image:: ../images/viewer.png
95+
:width: 100%
96+
97+
The first column is the number of times a frame with the particular ID has been received, next is the timestamp of the frame relative to the first received message. The third column is the time between the current frame relative to the previous one. Next is the length of the frame and then the data.
98+
99+
The last two columns are the decoded CANopen function code and node ID. If CANopen is not used, then they can simply be ignored.
100+
101+
Command line arguments
102+
^^^^^^^^^^^^^^^^^^^^^^
103+
104+
By default it will be using the :doc:`/interfaces/socketcan` interface. All interfaces supported are supported and can be specified using the ``-i`` argument.
105+
106+
The full usage page can be seen below::
107+
108+
Usage: python -m can.viewer [-h] [--version] [-b BITRATE] [-c CHANNEL]
109+
[-d {<id>:<format>,<id>:<format>:<scaling1>:...:<scalingN>,file.txt}]
110+
[-f {<can_id>:<can_mask>,<can_id>~<can_mask>}]
111+
[-i {iscan,ixxat,kvaser,neovi,nican,pcan,serial,slcan,socketcan,socketcan_ctypes,socketcan_native,usb2can,vector,virtual}]
112+
[--ignore-canopen]
113+
114+
A simple CAN viewer terminal application written in Python
115+
116+
Optional arguments:
117+
-h, --help Show this help message and exit
118+
--version Show program's version number and exit
119+
-b, --bitrate BITRATE
120+
Bitrate to use for the given CAN interface
121+
-c, --channel CHANNEL
122+
Most backend interfaces require some sort of channel.
123+
for example with the serial interface the channel
124+
might be a rfcomm device: "/dev/rfcomm0" with the
125+
socketcan interfaces valid channel examples include:
126+
"can0", "vcan0". (default: use default for the
127+
specified interface)
128+
-d, --decode {<id>:<format>,<id>:<format>:<scaling1>:...:<scalingN>,file.txt}
129+
Specify how to convert the raw bytes into real values.
130+
The ID of the frame is given as the first argument and the format as the second.
131+
The Python struct package is used to unpack the received data
132+
where the format characters have the following meaning:
133+
< = little-endian, > = big-endian
134+
x = pad byte
135+
c = char
136+
? = bool
137+
b = int8_t, B = uint8_t
138+
h = int16, H = uint16
139+
l = int32_t, L = uint32_t
140+
q = int64_t, Q = uint64_t
141+
f = float (32-bits), d = double (64-bits)
142+
Fx to convert six bytes with ID 0x100 into uint8_t, uint16 and uint32_t:
143+
$ python -m can.viewer -d "100:<BHL"
144+
Note that the IDs are always interpreted as hex values.
145+
An optional conversion from integers to real units can be given
146+
as additional arguments. In order to convert from raw integer
147+
values the values are multiplied with the corresponding scaling value,
148+
similarly the values are divided by the scaling value in order
149+
to convert from real units to raw integer values.
150+
Fx lets say the uint8_t needs no conversion, but the uint16 and the uint32_t
151+
needs to be divided by 10 and 100 respectively:
152+
$ python -m can.viewer -d "101:<BHL:1:10.0:100.0"
153+
Be aware that integer division is performed if the scaling value is an integer.
154+
Multiple arguments are separated by spaces:
155+
$ python -m can.viewer -d "100:<BHL" "101:<BHL:1:10.0:100.0"
156+
Alternatively a file containing the conversion strings separated by new lines
157+
can be given as input:
158+
$ cat file.txt
159+
100:<BHL
160+
101:<BHL:1:10.0:100.0
161+
$ python -m can.viewer -d file.txt
162+
-f, --filter {<can_id>:<can_mask>,<can_id>~<can_mask>}
163+
Comma separated CAN filters for the given CAN interface:
164+
<can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)
165+
<can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)
166+
Fx to show only frames with ID 0x100 to 0x103:
167+
python -m can.viewer -f 100:7FC
168+
Note that the ID and mask are alway interpreted as hex values
169+
-i, --interface {iscan,ixxat,kvaser,neovi,nican,pcan,serial,slcan,socketcan,socketcan_ctypes,socketcan_native,usb2can,vector,virtual}
170+
Specify the backend CAN interface to use. (default: "socketcan")
171+
--ignore-canopen Do not print CANopen information
172+
173+
Shortcuts
174+
^^^^^^^^^
175+
176+
+------------+-------------------------+
177+
| Key | Description |
178+
+============+=========================+
179+
| ESC/q | Exit the viewer |
180+
+------------+-------------------------+
181+
| c | Clear the stored frames |
182+
+------------+-------------------------+
183+
| SPACE | Pause the viewer |
184+
+------------+-------------------------+
185+
| UP/DOWN | Scroll the viewer |
186+
+------------+-------------------------+

scripts/can_viewer.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
"""
5+
See :mod:`can.scripts.viewer`.
6+
"""
7+
8+
from __future__ import absolute_import
9+
10+
from can.scripts.viewer import main
11+
12+
13+
if __name__ == "__main__":
14+
main()

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
'pytest ~= 3.6',
3636
'pytest-timeout ~= 1.2',
3737
'pytest-cov ~= 2.5',
38-
'codecov ~= 2.0'
38+
'codecov ~= 2.0',
39+
'future'
3940
] + extras_require['serial']
4041

4142
extras_require['test'] = tests_require
@@ -98,7 +99,7 @@
9899
# see https://www.python.org/dev/peps/pep-0345/#version-specifiers
99100
python_requires=">=2.7,!=3.0,!=3.1,!=3.2,!=3.3",
100101
install_requires=[
101-
'wrapt ~= 1.10',
102+
'wrapt ~= 1.10', 'six', 'typing', 'windows-curses;platform_system=="Windows"',
102103
],
103104
extras_require=extras_require,
104105

0 commit comments

Comments
 (0)