Skip to content
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

question on DBC file parsing #126

Closed
samsamfire opened this issue Feb 15, 2023 · 2 comments
Closed

question on DBC file parsing #126

samsamfire opened this issue Feb 15, 2023 · 2 comments

Comments

@samsamfire
Copy link

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 !

@hashemmm96
Copy link

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:

  1. Parse your binary CAN data into can.Frame structs.
  2. 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)
	}
}

@samsamfire
Copy link
Author

Thanks @hashemmm96 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants