-
Notifications
You must be signed in to change notification settings - Fork 38
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
Adds flexible data rate CAN payload to account for 64 byte CANFD and > 64 byte ethernet payloads #21
base: master
Are you sure you want to change the base?
Conversation
* Updated Message.Length to uint16 to support message lengths up to 65,535 bytes * Updated Signal.Lenght and Signal.Size to uint16 for payloads larger than 8 bytes * Added payload.go and payload_tests.go * Updated Big and Little Endian encoding methods * Added benchmarks * Added methods and tests to decode signed/unsigned signals in big/little endian * Added benchmarks for UnsignedBitsLittleEndian * Added hex string methods for Payload * Added UnmarshalPhysicalPayload and updated bit-level methods for Payload struct * Added UnmarshalValueDescriptionPayload and associated methods for Payload data struct * Added decode_tests.go * Updated decode test * Added asserts to decode_test.go * Added comparitive unit tests for can.Data and benchmarks for decoding * Updated PackLittleEndian and PackBigEndian to return new big.Int and reference pointer to payload in decode methods * Fixed units in VDM_Disconnect test Co-authored-by: Jason Shiverick <[email protected]> Co-authored-by: Naveen Venkatesan <[email protected]> Co-authored-by: Naveen Venkatesan <[email protected]>
…ls (#2) Co-authored-by: Naveen Venkatesan <[email protected]>
….Data) (#3) Co-authored-by: Jason Shiverick <[email protected]>
Added Decode and DecodePayload signal methods for decoding without sh…
Added message.Decode method
…sage (#6) * Updated README with example of decoding and dbc file with >8 byte message * Fixed indenting in README * Fixed indenting in README part 2 * Updated filename to example_payload.dbc * Updated dbc messages and removed unnecessary code from payload.go Co-authored-by: Naveen Venkatesan <[email protected]>
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.
Hi @jshiv, @venkatesannaveen and team Rivian!
Huge thanks for using can-go and proposing this contribution on adding CAN FD support. 🙌
I don't think that we should make breaking changes to the existing API for CAN FD. Have you considered adding a separate package canfd
with separate Frame
and Conn
types?
We would love to work together on adding CAN FD support in a non-breaking way. We're just about leaving for Easter holiday now Swedish time - but let's look at how to go about this, and we look forward to working together to add support for this without breaking existing code.
It looks like you are focusing on the use case of decoding CAN payloads, but not necessarily reading/writing CAN FD frames via SocketCAN interactively, is that a correct assumption? |
I see now that the breaking changes are focused on the descriptors and not the actual runtime API, so it might be workable after all. Please give us some time to review further, and to assess the impact of the changes. 🔍 |
@odsod We will be happy to work with you to make this work! There is no time crunch for us, we mostly wanted to get a PR in to let you know where we are. |
Yes we have primarily been focused on decoding CAN payloads and have not used the SocketCAN functionality. This package has been great BTW! |
Loving the community contribution here. Let's make sure to work together to get this merged. Thank you so much guys |
Hi @odsod, Its been a while on this one, Just wanted to ping and see if there are has been any though on merging this? |
Removed copy from reverse function
Feature/add multiplex decoding
Hi @jshiv! I'm going to be maintaining this repo going forward and wanted to check with you what the status is of this PR. We really appreciate the effort you put into this so far! Perhaps we can start by rebasing on latest master and cleaning up the commits. Then I can review and we'll see how to merge this properly. |
Hi @hashemmm96! Thanks for looking at it! We will work on rebasing. |
Co-authored-by: Jason Shiverick <[email protected]>
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.
Nice work, and thanks for the contribution. Sorry for taking so long for reviewing.
A question regarding the payload.go
. Are you using it to decode arbitrary payloads, or only CAN/CAN FD? The reason I'm asking is due to the PR name mentioning ethernet.
See the comments I left on the uint8/uint16 topic. Changing to uint16 makes sense for the Signal
type, where we are counting bits, but not for the types where we're counting bytes.
Also note that the CI now formats code and checks that commits are following the "conventional commits" specification, so there's some cleaning up required there.
// ID is the CAN ID | ||
ID uint32 | ||
// Length is the number of bytes of data in the frame. | ||
Length uint8 | ||
Length uint16 | ||
// Data is the frame data. | ||
Data Data | ||
// IsRemote is true for remote frames. |
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.
In CAN FD the DLC field may be 16 bits but in our case we're only counting the number of bytes in a frame. The Frame
struct is supposed to parse candump
output, which shows the length of the frame in bytes (maximum of 64 bytes for CAN FD) and as such there is no need to modify the Length
field to uint16
.
Something that needs to be changed instead is the Data
type, defined in data.go
. There it is hard coded as a slice of length 8, but should be increased to 64 instead.
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.
We use an ethernet protocol that can actually send messages >255 bytes in length so the uint8
wasn't sufficient to hold the message length, which is why we changed this - open to suggestions on how you'd want to deal with this
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.
Your ethernet protocol must be some kind of higher-layer protocol which utilizes CAN in the link layer. In that case, I think the best option would be that you implement a new library for your higher-layer protocol which depends on our library. There, you can wrap the Frame
type in your own structs to fit your use case. As I see it this is a pure CAN library, thus we should limit the scope to the link-layer aspects and DBC file handling.
I assume you're using the descriptor library to parse signals within your protocol, meaning your signals can be more than 255 bits wide as well. This is something we can implement in this library, since signals don't really follow a standard size structure the same way the CAN and CAN FD protocols do. That will be a breaking change but would make sense to do if we're implementing CAN FD support.
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.
Correct, we actually may be able to extract the message length from the header in our ethernet protocol so we can potentially revert this back to a uint8
- the main issue with > 8 bytes (CAN-FD or arbitrary length) is that we're no longer able to use uint64
to pack the bits so we've resorted to using math.big
to handle this which by nature would allows lengths of any size. We can refactor some of our decoding code to deal with a 64 byte payload, it just seems like a more limiting constraint. We see value in keeping the current can.Data
struct and associated methods since it's very efficient for messages <= 8 bytes, and we currently use both.
Would your team be open to a meeting on Zoom, etc. to talk through some of our design choices? This may be much simpler than going back-and-forth on the comments here. @jshiv and I are both in PST which is 9 hours behind Sweden but we can work something out if that sounds good on your side.
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 that's a great idea to talk "face-to-face" 😄
I sent you a request on LinkedIn, let's exchange contact info there.
@@ -0,0 +1,415 @@ | |||
package decode_test |
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.
This test should probably be moved up a dir and renamed to message_test.go
// idAndFlags is the combined CAN ID and flags. | ||
idAndFlags uint32 | ||
// dataLengthCode is the frame payload length in bytes. | ||
dataLengthCode uint8 | ||
dataLengthCode uint16 | ||
// padding+reserved fields | ||
_ [3]byte | ||
// bytes contains the frame payload. |
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.
In the SocketCAN API, DLC is deprecated. Instead this field refers to the payload length in bytes, and is a uint8.
What actually needs to be changed is the data
field in the frame
struct. It has a fixed size of 8 bytes and should be increased to 64 to allow for CAN FD payloads. However, I think we should wait with adding CAN FD support to the socketcan package until we also have support for setting up/down CAN FD devices.
Our payload should support arbitrarily long messages so the CAN/CAN-FD is not relevant anymore so we can change the title of the PR to reflect that |
I'm also receiving payloads larger than 8 bytes (16 and 64). They are parsed by python cantools without any problem, maybe we can just check if each signal start/length is inside the payload size and not limit it to 8 bytes? |
Thanks for the great package! We have added some functionality for decoding >8 byte signals. The primary backwards incompatible change is
Message.Length
,Signal.Start
,Signal.Length
type changed from uint8 -> uint16.payload.go
with type PayloadSignal.UnmarshalPhysicalPayload
method distinct fromSignal.UnmarshalPhysical
Data
andPayload
becauseData
decoding is more performant thanPayload
Signal.Decode
andMessage.Decode
methods