-
Notifications
You must be signed in to change notification settings - Fork 645
Merge the CAN viewer terminal application into python-can #390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #390 +/- ##
===========================================
+ Coverage 60.15% 61.94% +1.78%
===========================================
Files 54 55 +1
Lines 4337 4551 +214
===========================================
+ Hits 2609 2819 +210
- Misses 1728 1732 +4 |
2081d02
to
79d6970
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great addition! Unfortunately I developed an almost identical application, but yours is much better structured than mine so I might contribute with some of my features later.
doc/scripts.rst
Outdated
Specify the backend CAN interface to use. (default: "socketcan") | ||
--ignore-canopen Do not print CANopen information | ||
|
||
Shortcuts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be helpful to print these in the program too, maybe at the bottom.
can/scripts/viewer.py
Outdated
self.y, self.x = self.stdscr.getmaxyx() | ||
|
||
# Do not wait for key inputs and disable the cursor | ||
self.stdscr.nodelay(True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The program uses 100% CPU resources because there is no place for it to wait. Either put a small timeout on key input (like 10-100 ms or so) or a timeout on bus.recv()
(or both). Lowering the update rate of the window could also help reading values that change quickly, but might result in buffer overflow on some interfaces.
can/scripts/viewer.py
Outdated
def main(): # pragma: no cover | ||
parsed_args, can_filters, data_structs, ignore_canopen = parse_args(sys.argv[1:]) | ||
|
||
config = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put single_handle=True
here for Kvaser, otherwise we won't be able to see messages sent from the local machine.
can/scripts/viewer.py
Outdated
|
||
class CanViewer: | ||
|
||
def __init__(self, stdscr, bus, data_structs, ignore_canopen, testing=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also add curses.use_default_colors()
somewhere to allow the terminal window to choose a fitting background instead of always black.
can/scripts/viewer.py
Outdated
|
||
from can import __version__ | ||
|
||
# CANopen function codes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Python-can is meant to be protocol agnostic, so if we support CANopen then we will have to prepare to support many different protocols in the future as well. Perhaps it would be a good idea to make it possible to write plugins for decoding messages. There are a lot of proprietary CAN protocols out there and this would allow the most flexibility. We could also link to third party packages from here so it is easy to find them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the viewer should remain protocol agnostic. Can we aim to support multiple CAN protocols without the user having to change any python-can
code?
Your separate config file for --decode
looks close for a naive (no custom protocol code) version? Could add a display name per frame id.
… so the application does not use 100 % of the CPU resources, added "single_handle=True" so it is compatible with the Kvaser interface and let curses choose the background color automatically
…ment text, so there are no unwanted spaces after the text
@christiansandberg I believe 7a8ca77 should address all of your comments. |
Seems like Travis is having connection issues. Can someone with admin privileges please restart the Python 3.5 and pypy3.5 build? |
can/scripts/viewer.py
Outdated
|
||
# Convert it into raw integer values and then pack the data | ||
@staticmethod | ||
def pack_data(cmd, cmd_to_struct, *args): # type: (int, Dict, Union[*float, *int]) -> bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this used for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unpack_data
and pack_data
are coming from another project of mine. I use it for the test. I have moved into the test, as it is unused in the viewer.
can/scripts/viewer.py
Outdated
# Increment frame counter | ||
self.ids[key]['count'] += 1 | ||
|
||
# Sort frames based on the CAN-Bus ID if a new frame was added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other tools like CANalyzer tend to add new messages at the bottom as that does not disturb the user while reading the list. We could sort the list by pressing 's' for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
can/scripts/viewer.py
Outdated
# Generate data string | ||
data_string = '' | ||
if msg.dlc > 0: | ||
data_string = ' '.join('{:02X}'.format(x) for x in msg.data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might set data_string
to something like "Remote frame" if it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't see a clean way to implement this. Maybe use a different color?
can/scripts/viewer.py
Outdated
|
||
optional.add_argument('-i', '--interface', dest='interface', | ||
help='''R|Specify the backend CAN interface to use. (default: "socketcan")''', | ||
choices=sorted(can.VALID_INTERFACES), default='socketcan') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should default to use config files like the regular API.
can/scripts/viewer.py
Outdated
self.redraw_screen() | ||
|
||
# Sleep 0.1 ms, so the application does not use 100 % of the CPU resources | ||
time.sleep(.1 / 1000.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to put a longer timeout in the recv
method instead. By sleeping between each message you risk losing messages eventually. A timeout will only allow the program to rest when the receive queue has been cleared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I restarted the Travis CI builds and they now run flawlessly. You may also add a note on this merge in python-can/doc/history.rst. ;-) |
…er dropped, sort frame by pressing 's' instead of doing it automatically and moved "pack_data" into the test
@christiansandberg please see: 33ffd6c |
@felixdivo please see: 08249da |
@christiansandberg anymore corrections? |
Please see #406. I fixed the bug with the scripts not being found. Because of this, I had to place the scripts in the Also, this can be used to print the help section when no arguments were given: # [...]
import sys
# [...]
def main():
# [...]
# print help message when no arguments were given
if len(sys.argv) < 2:
parser.print_help(sys.stderr)
import errno
raise SystemExit(errno.EINVAL)
# [...] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @christiansandberg here that the viewer should remain protocol agnostic. I suggest removing the CANOPEN specific decoding information into a separate module.
Ideally can we aim to support multiple CAN protocols without the user having to change any python-can library code?
Your separate config file for --decode
looks close for a naive version? (no custom protocol code) Consider adding a display name per frame id.
edit Also this is a fantastic addition and I think it will make the library much more useful!
# Conflicts: # can/scripts/__init__.py
Just moved the script back into the CAN module. Will remove the CANopen code later tonight. |
…g how the decoding looks like
The CANopen code is now removed and the documentation is updated :) |
Btw I have considered changing the syntax of the |
The decoding part could also be moved to a plugin using a database instead of specifying everything on the command line. It could accomplished using canmatrix. |
@christiansandberg I already allow giving the decoding as a file, but you could add support for any kind of format in the future if you like. |
@hardbyte anything holding this back? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All good by me.
Thanks for taking on all the feedback.
See: #370 and Lauszus/python_can_viewer#2