- Notifications
You must be signed in to change notification settings - Fork 663
Add auto-modifying cyclic tasks#703
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
codecovbot commented Sep 28, 2019 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Codecov Report
Additional details and impacted files@@ Coverage Diff @@## develop #703 +/- ## =========================================== + Coverage 65.16% 68.34% +3.18% =========================================== Files 81 69 -12 Lines 8853 6211 -2642 =========================================== - Hits 5769 4245 -1524 + Misses 3084 1966 -1118 |
Added modifier_callback arguments where necessary, and changed MRO of sockercan's CyclicSendTask to match that of the fallback.
This makes several changes to socketcan in previous commits unnecessary. These changes are also removed.
christiansandberg commented Oct 3, 2019
I think this is something that is much needed. Things like checksums and alive counters are getting more common as safety is becoming a major driving force. Unfortunately it's only going to work with the thread based software method. Passing the task entirely to the kernel or hardware also means you can't do any processing in user space. Should we provide an interface to allow the user to choose the thread based transmission at the expense of poor timing? |
bessman commented Oct 4, 2019 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I've thought about this some more, and I'm no longer sure a callback is the way to go. At least for the issue of counters and checksums, a better solution is to pre-calculate all CRCs and send them using CyclicSendTask's already existing ability to send a sequence of messages, e.g.: This has the added benefit that the user does not have to keep track of the counter when the message data changes. With the callback method, the counter will reset when the data changes unless the user manually checks the counter of the most recently sent message and adds it to the message. The callback is more flexible, and there could be applications where pre-calculating all messages is not possible (though I can't think of any at the moment). But if that flexibility comes at the cost of performance, perhaps it isn't worth it. |
zariiii9003 commented Oct 12, 2019
Maybe we could implement this in the |
bessman commented Nov 21, 2019
How would this work, exactly? If data is a generator, wouldn't we need to call next(data) all over the place? That seems like a big change. |
hardbyte commented Jul 24, 2020
This is a good proposal, and a clean default implementation. I also don't see how a callback would interact nicely with the backends that already offload periodic messages (without falling back to the threading approach), which isn't a great user experience. However if this is useful for a few people (e.g. #809) and we can implement it in a way that doesn't harm the performance when not being used then I'd be happy to merge it in. I'm thinking that in the socketcan case we make it very clear in the docs that giving a callback will mean looser timing of messages being sent based on Python threads rather than the kernel. |
zorce commented Mar 22, 2021
Would love to see something like this, but if possible a kernel implementation to handle similar issues. |
hartkopp commented Mar 22, 2021
The CAN_BCM (in-kernel Broadcast Manager) can send a sequence of up to 256 CAN(FD) frames, e.g. every 100ms the next frame in the row is transmitted. The nframes element in the bcm_msg_head is usually 1 but can be extended to 2 .. 256 to send a sequence. Same on the receiving side: When you want to filter on data changes on a specific MUX ID you define the mux mask (to define where the MUX ID sits in the CAN frame data) and put the MUX ID in that place in the RX_SETUP filter. |
zorce commented Mar 23, 2021
Didn't know that, thanks for the information. Is this also exposed with other backends, noticed there is a cyclic_multiple example added 2 years ago. but I was running on version 3.3.4. will try to update and try it out. |
hartkopp commented Mar 23, 2021
I've just programmed the CAN_BCM module and started to look into the API that python-can provides. Unfortunately I'm not that good in Python to get behind the current API concept for handling (and on-the-fly updating) a sequence of cyclic messages ;-) |
leu1dy commented Nov 30, 2021 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I am also interested in about this feature. AliveCounter & Checksums are part of the daily work in automotive domain. Any chance to see this feature at a release state ? Thank you |
djnnvx commented Jun 29, 2022
Hello, I too am interested in this feature. Is there anything to correct for a merge, besides fixing the merge conflicts ? I would love to see it merged (or even help with the work left for a merge), as I am currently building a tool that requires such a need kind regards |
djnnvx commented Jul 20, 2022 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
For those of you looking to have a callback like I had, I found a way to do it. Here's how: importasyncioimportcan# Initiate listenerslogger=can.Logger('example.asc') async_reader=can.AsyncBufferedReader() listeners: List[can.notifier.MessageRecipient] = [ async_reader, logger, print_msg, # print callback function ] withcan.ThreadSafeBus( # fetching from configname=some_name, bustype=some_bustype, channel=some_channel, # Maybe it can work without this, actually. Have not tested yetreceive_own_messages=True, ) asbus: # Create Notifier with an explicit loop to use for scheduling of callbacksnotifier=can.Notifier(bus, listeners, loop=asyncio.get_running_loop()) # send message periodicallytask=bus.send_periodic(some_message, 0.2) whileTrue: # read all messages asynchronouslyasyncformsginasync_reader: msg.data=crc_function_or_whatever(msg) task.modify_data(msg)Since we read messages asynchronously, we can modify the tasks when we receive a new version of the message. This should then be sent on the bus to other ECUs. To ensure that we refresh the message periodically, we require the bus to receive our own message, which should trigger the callback. have not run extensive tests yet so there may be better way/things to fix, but it seems to work. Hope this helps :)~ |
# Conflicts: # can/broadcastmanager.py # can/bus.py # can/interfaces/socketcan/socketcan.py
zariiii9003 commented Jan 8, 2023
I resolved the merge conflicts. There are still a few problems though:
Personally i would prefer a mutating callback with no return value though ( |
# Conflicts: # can/bus.py # can/interfaces/socketcan/socketcan.py
zariiii9003 commented Apr 7, 2023
I think this can be merged if everyone agrees with the changes. |
# Conflicts: # can/interfaces/ixxat/canlib_vcinpl.py
This is a proposal to add an optional callback function to ModifiableCyclicTaskABC which manipulates each message automatically before sending it. This feature can be used to, for example, increment a counter or compute a checksum, as shown in examples/cyclic_checksum.py.
If you think this functionality is appropriate for merging, I will of course add it to all interfaces which override the fallback ThreadBasedCyclicSendTask.