Skip to content

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

Merged
merged 16 commits into from
Sep 17, 2018

Conversation

Lauszus
Copy link
Collaborator

@Lauszus Lauszus commented Aug 11, 2018

@codecov
Copy link

codecov bot commented Aug 11, 2018

Codecov Report

Merging #390 into develop will increase coverage by 1.78%.
The diff coverage is 100%.

@@             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

@Lauszus Lauszus force-pushed the viewer branch 2 times, most recently from 2081d02 to 79d6970 Compare August 11, 2018 22:22
Copy link
Collaborator

@christiansandberg christiansandberg left a 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
Copy link
Collaborator

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.

self.y, self.x = self.stdscr.getmaxyx()

# Do not wait for key inputs and disable the cursor
self.stdscr.nodelay(True)
Copy link
Collaborator

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.

def main(): # pragma: no cover
parsed_args, can_filters, data_structs, ignore_canopen = parse_args(sys.argv[1:])

config = {}
Copy link
Collaborator

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.


class CanViewer:

def __init__(self, stdscr, bus, data_structs, ignore_canopen, testing=False):
Copy link
Collaborator

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.


from can import __version__

# CANopen function codes
Copy link
Collaborator

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.

Copy link
Owner

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
@Lauszus
Copy link
Collaborator Author

Lauszus commented Aug 12, 2018

@christiansandberg I believe 7a8ca77 should address all of your comments.

@Lauszus
Copy link
Collaborator Author

Lauszus commented Aug 12, 2018

Seems like Travis is having connection issues. Can someone with admin privileges please restart the Python 3.5 and pypy3.5 build?


# 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
Copy link
Collaborator

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?

Copy link
Collaborator Author

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.

# Increment frame counter
self.ids[key]['count'] += 1

# Sort frames based on the CAN-Bus ID if a new frame was added
Copy link
Collaborator

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

# Generate data string
data_string = ''
if msg.dlc > 0:
data_string = ' '.join('{:02X}'.format(x) for x in msg.data)
Copy link
Collaborator

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.

Copy link
Collaborator Author

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?


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')
Copy link
Collaborator

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.

self.redraw_screen()

# Sleep 0.1 ms, so the application does not use 100 % of the CPU resources
time.sleep(.1 / 1000.)
Copy link
Collaborator

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@felixdivo
Copy link
Collaborator

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
@Lauszus
Copy link
Collaborator Author

Lauszus commented Aug 17, 2018

@christiansandberg please see: 33ffd6c

@Lauszus
Copy link
Collaborator Author

Lauszus commented Aug 17, 2018

@felixdivo please see: 08249da

@felixdivo
Copy link
Collaborator

@Lauszus Your addition in the history section in 08249da looks good. 😃

@Lauszus
Copy link
Collaborator Author

Lauszus commented Aug 28, 2018

@christiansandberg anymore corrections?

@felixdivo
Copy link
Collaborator

felixdivo commented Sep 6, 2018

Please see #406. I fixed the bug with the scripts not being found. Because of this, I had to place the scripts in the python-can/can/ folder, and not inside the python-can/can/scripts/ folder.

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)

# [...]

Copy link
Owner

@hardbyte hardbyte left a 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!

@Lauszus
Copy link
Collaborator Author

Lauszus commented Sep 9, 2018

Just moved the script back into the CAN module. Will remove the CANopen code later tonight.

@Lauszus
Copy link
Collaborator Author

Lauszus commented Sep 9, 2018

The CANopen code is now removed and the documentation is updated :)

@Lauszus
Copy link
Collaborator Author

Lauszus commented Sep 9, 2018

Btw I have considered changing the syntax of the -d argument, so it is comma separated. Not sure if it's worth doing or I should just stick with colons?

@christiansandberg
Copy link
Collaborator

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.

@Lauszus
Copy link
Collaborator Author

Lauszus commented Sep 9, 2018

@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.

@Lauszus
Copy link
Collaborator Author

Lauszus commented Sep 12, 2018

@hardbyte anything holding this back?

Copy link
Owner

@hardbyte hardbyte left a 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. :shipit:

Thanks for taking on all the feedback.

@felixdivo felixdivo merged commit 5a9e6eb into hardbyte:develop Sep 17, 2018
Lauszus added a commit to Lauszus/python_can_viewer that referenced this pull request Sep 17, 2018
@Lauszus Lauszus deleted the viewer branch September 24, 2018 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants