can

package module
v0.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2024 License: MIT Imports: 6 Imported by: 34

README

🔌 go.einride.tech/can

PkgGoDev GoReportCard Codecov

CAN toolkit for Go programmers.

can-go makes use of the Linux SocketCAN abstraction for CAN communication. (See the SocketCAN documentation for more details).

Installation

go get -u go.einride.tech/can

Examples

Setting up a CAN interface

import "go.einride.tech/can/pkg/candevice"

func main() {
	// Error handling omitted to keep example simple
	d, _ := candevice.New("can0")
	_ := d.SetBitrate(250000)
	_ := d.SetUp()
	defer d.SetDown()
}
Receiving CAN frames

Receiving CAN frames from a socketcan interface.

import "go.einride.tech/can/pkg/socketcan"

func main() {
	// Error handling omitted to keep example simple
	conn, _ := socketcan.DialContext(context.Background(), "can", "can0")

	recv := socketcan.NewReceiver(conn)
	for recv.Receive() {
		frame := recv.Frame()
		fmt.Println(frame.String())
	}
}
Sending CAN frames/messages

Sending CAN frames to a socketcan interface.

import "go.einride.tech/can/pkg/socketcan"

func main() {
	// Error handling omitted to keep example simple

	conn, _ := socketcan.DialContext(context.Background(), "can", "can0")

	frame := can.Frame{}
	tx := socketcan.NewTransmitter(conn)
	_ = tx.TransmitFrame(context.Background(), frame)
}
Generating Go code from a DBC file

It is possible to generate Go code from a .dbc file.

$ go run go.einride.tech/can/cmd/cantool generate <dbc file root folder> <output folder>

In order to generate Go code that makes sense, we currently perform some validations when parsing the DBC file so there may need to be some changes on the DBC file to make it work

After generating Go code we can marshal a message to a frame:

// import etruckcan "github.com/myproject/myrepo/gen"

auxMsg := etruckcan.NewAuxiliary().SetHeadLights(etruckcan.Auxiliary_HeadLights_LowBeam)
frame := auxMsg.Frame()

Or unmarshal a frame to a message:

// import etruckcan "github.com/myproject/myrepo/gen"

// Error handling omitted for simplicity
_ := recv.Receive()
frame := recv.Frame()

var auxMsg *etruckcan.Auxiliary
_ = auxMsg.UnmarshalFrame(frame)

Running integration tests

Building the tests:

$ make build-integration-tests

Built tests are placed in build/tests.

The candevice test requires access to physical HW, so run it using sudo. Example:

$ sudo ./build/tests/candevice.test
> PASS

Documentation

Overview

Package can provides primitives for working with CAN.

See: https://en.wikipedia.org/wiki/CAN_bus

Index

Constants

View Source
const (
	MaxID         = 0x7ff
	MaxExtendedID = 0x1fffffff
)

CAN format constants.

View Source
const MaxDataLength = 8

Variables

This section is empty.

Functions

func CheckBitRangeBigEndian

func CheckBitRangeBigEndian(frameLength, rangeStart, rangeLength uint8) error

CheckBitRangeBigEndian checks that a big-endian bit range fits in the data.

func CheckBitRangeLittleEndian

func CheckBitRangeLittleEndian(frameLength, rangeStart, rangeLength uint8) error

CheckBitRangeLittleEndian checks that a little-endian bit range fits in the data.

func CheckValue

func CheckValue(value uint64, bits uint8) error

CheckValue checks that a value fits in a number of bits.

Types

type Data

type Data [MaxDataLength]byte

Data holds the data in a CAN frame.

Layout

Individual bits in the data are numbered according to the following scheme:

         BIT
         NUMBER
         +------+------+------+------+------+------+------+------+
         |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
BYTE     +------+------+------+------+------+------+------+------+
NUMBER
+-----+  +------+------+------+------+------+------+------+------+
|  0  |  |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
+-----+  +------+------+------+------+------+------+------+------+
|  1  |  |  15  |  14  |  13  |  12  |  11  |  10  |   9  |   8  |
+-----+  +------+------+------+------+------+------+------+------+
|  2  |  |  23  |  22  |  21  |  20  |  19  |  18  |  17  |  16  |
+-----+  +------+------+------+------+------+------+------+------+
|  3  |  |  31  |  30  |  29  |  28  |  27  |  26  |  25  |  24  |
+-----+  +------+------+------+------+------+------+------+------+
|  4  |  |  39  |  38  |  37  |  36  |  35  |  34  |  33  |  32  |
+-----+  +------+------+------+------+------+------+------+------+
|  5  |  |  47  |  46  |  45  |  44  |  43  |  42  |  41  |  40  |
+-----+  +------+------+------+------+------+------+------+------+
|  6  |  |  55  |  54  |  53  |  52  |  51  |  50  |  49  |  48  |
+-----+  +------+------+------+------+------+------+------+------+
|  7  |  |  63  |  62  |  61  |  60  |  59  |  58  |  57  |  56  |
+-----+  +------+------+------+------+------+------+------+------+

Bit ranges can be manipulated using little-endian and big-endian bit ordering.

Little-endian bit ranges

Example range of length 32 starting at bit 29:

         BIT
         NUMBER
         +------+------+------+------+------+------+------+------+
         |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
BYTE     +------+------+------+------+------+------+------+------+
NUMBER
+-----+  +------+------+------+------+------+------+------+------+
|  0  |  |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
+-----+  +------+------+------+------+------+------+------+------+
|  1  |  |  15  |  14  |  13  |  12  |  11  |  10  |   9  |   8  |
+-----+  +------+------+------+------+------+------+------+------+
|  2  |  |  23  |  22  |  21  |  20  |  19  |  18  |  17  |  16  |
+-----+  +------+------+------+------+------+------+------+------+
|  3  |  |  <-------------LSb |  28  |  27  |  26  |  25  |  24  |
+-----+  +------+------+------+------+------+------+------+------+
|  4  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  5  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  6  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  7  |  |  63  |  62  |  61  | <-MSb--------------------------- |
+-----+  +------+------+------+------+------+------+------+------+

Big-endian bit ranges

Example range of length 32 starting at bit 29:

         BIT
         NUMBER
         +------+------+------+------+------+------+------+------+
         |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
BYTE     +------+------+------+------+------+------+------+------+
NUMBER
+-----+  +------+------+------+------+------+------+------+------+
|  0  |  |   7  |   6  |   5  |   4  |   3  |   2  |   1  |   0  |
+-----+  +------+------+------+------+------+------+------+------+
|  1  |  |  15  |  14  |  13  |  12  |  11  |  10  |   9  |   8  |
+-----+  +------+------+------+------+------+------+------+------+
|  2  |  |  23  |  22  |  21  |  20  |  19  |  18  |  17  |  16  |
+-----+  +------+------+------+------+------+------+------+------+
|  3  |  |  31  |  30  | <-MSb---------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  4  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  5  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  6  |  |  <--------------------------------------------------  |
+-----+  +------+------+------+------+------+------+------+------+
|  7  |  |  <------LSb |  61  |  60  |  59  |  58  |  57  |  56  |
+-----+  +------+------+------+------+------+------+------+------+

func (*Data) Bit

func (d *Data) Bit(i uint8) bool

Bit returns the value of the i:th bit in the data as a bool.

func (*Data) PackBigEndian

func (d *Data) PackBigEndian() uint64

PackBigEndian packs the data into a contiguous uint64 value for big-endian signals.

func (*Data) PackLittleEndian

func (d *Data) PackLittleEndian() uint64

PackLittleEndian packs the data into a contiguous uint64 value for little-endian signals.

func (*Data) SetBit

func (d *Data) SetBit(i uint8, value bool)

SetBit sets the value of the i:th bit in the data.

func (*Data) SetSignedBitsBigEndian

func (d *Data) SetSignedBitsBigEndian(start, length uint8, value int64)

SetSignedBitsBigEndian sets the big-endian bit range [start, start+length) to the provided signed value.

func (*Data) SetSignedBitsLittleEndian

func (d *Data) SetSignedBitsLittleEndian(start, length uint8, value int64)

SetSignedBitsLittleEndian sets the little-endian bit range [start, start+length) to the provided signed value.

func (*Data) SetUnsignedBitsBigEndian

func (d *Data) SetUnsignedBitsBigEndian(start, length uint8, value uint64)

SetUnsignedBitsBigEndian sets the big-endian bit range [start, start+length) to the provided unsigned value.

func (*Data) SetUnsignedBitsLittleEndian

func (d *Data) SetUnsignedBitsLittleEndian(start, length uint8, value uint64)

SetUnsignedBitsBigEndian sets the little-endian bit range [start, start+length) to the provided unsigned value.

func (*Data) SignedBitsBigEndian

func (d *Data) SignedBitsBigEndian(start, length uint8) int64

SignedBitsBigEndian returns little-endian bit range [start, start+length) as a signed value.

func (*Data) SignedBitsLittleEndian

func (d *Data) SignedBitsLittleEndian(start, length uint8) int64

SignedBitsLittleEndian returns little-endian bit range [start, start+length) as a signed value.

func (*Data) UnpackBigEndian

func (d *Data) UnpackBigEndian(packed uint64)

UnpackBigEndian sets the value of d.Bytes by unpacking the provided value as sequential big-endian bits.

func (*Data) UnpackLittleEndian

func (d *Data) UnpackLittleEndian(packed uint64)

UnpackLittleEndian sets the value of d.Bytes by unpacking the provided value as sequential little-endian bits.

func (*Data) UnsignedBitsBigEndian

func (d *Data) UnsignedBitsBigEndian(start, length uint8) uint64

UnsignedBitsBigEndian returns the big-endian bit range [start, start+length) as an unsigned value.

func (*Data) UnsignedBitsLittleEndian

func (d *Data) UnsignedBitsLittleEndian(start, length uint8) uint64

UnsignedBitsLittleEndian returns the little-endian bit range [start, start+length) as an unsigned value.

type Frame

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
}

Frame represents a CAN frame.

A Frame is intentionally designed to fit into 16 bytes on common architectures and is therefore amenable to pass-by-value and judicious copying.

func (Frame) JSON

func (f Frame) JSON() string

JSON returns the JSON-encoding of f, using hex-encoding for the data.

Examples:

{"id":32,"data":"0102030405060708"}
{"id":32,"extended":true,"remote":true,"length":4}

func (Frame) MarshalJSON

func (f Frame) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON-encoding of f, using hex-encoding for the data.

See JSON for an example of the JSON schema.

func (Frame) String

func (f Frame) String() string

String returns an ASCII representation the CAN frame.

Format:

([0-9A-F]{3}|[0-9A-F]{3})#(R[0-8]?|[0-9A-F]{0,16})

The format is compatible with the candump(1) log file format.

func (*Frame) UnmarshalJSON

func (f *Frame) UnmarshalJSON(jsonData []byte) error

UnmarshalJSON sets *f using the provided JSON-encoded values.

See MarshalJSON for an example of the expected JSON schema.

The result should be checked with Validate to guard against invalid JSON data.

func (*Frame) UnmarshalString

func (f *Frame) UnmarshalString(s string) error

UnmarshalString sets *f using the provided ASCII representation of a Frame.

func (*Frame) Validate

func (f *Frame) Validate() error

Validate returns an error if the Frame is not a valid CAN frame.

type FrameMarshaler

type FrameMarshaler interface {
	MarshalFrame() (Frame, error)
}

FrameMarshaler can marshal itself to a CAN frame.

type FrameUnmarshaler

type FrameUnmarshaler interface {
	UnmarshalFrame(Frame) error
}

FrameUnmarshaler can unmarshal itself from a CAN frame.

type Message

type Message interface {
	FrameMarshaler
	FrameUnmarshaler
}

Message is anything that can marshal and unmarshal itself to/from a CAN frame.

Directories

Path Synopsis
cmd
internal
clock
Package clock provides primitives for mocking time.
Package clock provides primitives for mocking time.
mocks/gen/mockcanrunner
Package mockcanrunner is a generated GoMock package.
Package mockcanrunner is a generated GoMock package.
mocks/gen/mockclock
Package mockclock is a generated GoMock package.
Package mockclock is a generated GoMock package.
mocks/gen/mocksocketcan
Package mocksocketcan is a generated GoMock package.
Package mocksocketcan is a generated GoMock package.
reinterpret
Package reinterpret provides primitives for reinterpreting arbitrary-length values as signed or unsigned.
Package reinterpret provides primitives for reinterpreting arbitrary-length values as signed or unsigned.
pkg
dbc
Package dbc provides primitives for parsing, formatting and linting DBC files.
Package dbc provides primitives for parsing, formatting and linting DBC files.
generated
Package generated provides primitives for working with code-generated CAN messages.
Package generated provides primitives for working with code-generated CAN messages.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL