question on DBC file parsing
samsamfire opened this issue · 2 comments
Hi,
I was looking for a go package that could parse DBC files and I stumbled upon this package.
In the docs I can see that it's possible to generate some go code from a DBC file, which sounds great but I am looking for a way for parsing some can data & converting it via a DBC to a human readable format.
The purpose of this would be to create a telegraf plugin to parse raw can data and converting it for visualizations & logging.
It seems that the parsed DBC data is inside a []Defs slice, ideally it would be great to have some sort of map for directly converting CAN IDs, I don't know if this is possible in this implementation ?
Thanks a lot !
Hi @samsamfire,
If I understand you correctly, you have binary CAN data which you want to convert to a human readable format using a DBC file. Using this library you do it in two steps:
- Parse your binary CAN data into
can.Frame
structs. - Use the generated go code from the DBC file to parse the
can.Frame
structs into DBC messages.
The generated go code that you get when using a DBC file contains functions for unmarshalling CAN frames to DBC messages. The prerequisite is that you have parsed your binary CAN frames into can.Frame
structs. If you can do that, then you can use the (md *MessageDescriptor) UnmarshalFrame(f can.Frame)
function generated from the DBC file to convert a CAN frame to a message in the DBC, which automatically converts to the correct type based on ID. Take a look inside the testdata
folder in this repo, where you can see an example DBC and its generated code. For reference, here's the can.Frame
struct and the UnmarshalFrame
that I'm talking about. I hope this helps 🙂
type Frame struct {
// ID is the CAN ID
ID uint32
// Length is the number of bytes of data in the frame.
Length uint8
// Data is the frame data.
Data Data
// IsRemote is true for remote frames.
IsRemote bool
// IsExtended is true for extended frames, i.e. frames with 29-bit IDs.
IsExtended bool
}
// UnmarshalFrame unmarshals the provided example CAN frame.
func (md *MessagesDescriptor) UnmarshalFrame(f can.Frame) (generated.Message, error) {
switch f.ID {
case md.EmptyMessage.ID:
var msg EmptyMessage
if err := msg.UnmarshalFrame(f); err != nil {
return nil, fmt.Errorf("unmarshal example frame: %w", err)
}
return &msg, nil
case md.DriverHeartbeat.ID:
var msg DriverHeartbeat
if err := msg.UnmarshalFrame(f); err != nil {
return nil, fmt.Errorf("unmarshal example frame: %w", err)
}
return &msg, nil
case md.MotorCommand.ID:
var msg MotorCommand
if err := msg.UnmarshalFrame(f); err != nil {
return nil, fmt.Errorf("unmarshal example frame: %w", err)
}
return &msg, nil
...
...
...
default:
return nil, fmt.Errorf("unmarshal example frame: ID not in database: %d", f.ID)
}
}
Thanks @hashemmm96 !