canbus

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2023 License: BSD-3-Clause Imports: 8 Imported by: 0

README

canbus

GitHub release CI codecov GoDoc License

canbus provides high-level facilities to interact with CAN sockets.

can-dump

can-dump prints data flowing on CAN bus.

Usage of can-dump:

sh> can-dump [options] <CAN interface>
   (use CTRL-C to terminate can-dump)

Examples:

 can-dump vcan0
$> can-dump vcan0
  vcan0  080 00000000  00 DE AD BE EF            |.....|
  vcan0  080 00000000  01 DE AD BE EF            |.....|
  vcan0  080 00000000  02 DE AD BE EF            |.....|
  vcan0  080 00000000  03 DE AD BE EF            |.....|
  vcan0  080 00000000  04 DE AD BE EF            |.....|
  vcan0  080 00000000  05 DE AD BE EF            |.....|
  vcan0  080 00000000  06 DE AD BE EF            |.....|
  vcan0  080 00000000  07 DE AD BE EF            |.....|
  vcan0  080 00000000  08 DE AD BE EF            |.....|
  vcan0  080 00000000  09 DE AD BE EF            |.....|
  vcan0  712 00000000  11 22 33 44 55 66 77 88   |."3DUFW.|
  vcan0  7fa 00000000  DE AD BE EF               |....|
[...]

can-send

can-send sends data on the CAN bus.

Usage of can-send:

sh> can-send [options] <CAN interface> <CAN frame>

where <CAN frame> is of the form: <ID-hex>#<frame data-hex>.

Examples:

 can-send vcan0 f12#1122334455667788
 can-send vcan0 ffa#deadbeef
$> can-dump vcan0 &
$> can-send vcan0 f12#1122334455667788
  vcan0  712 00000000  11 22 33 44 55 66 77 88   |."3DUFW.|
$> can-send vcan0 ffa#deadbeef
  vcan0  7fa 00000000  DE AD BE EF               |....|

References

$> modprobe can
$> modprobe can_raw
$> modprobe vcan

## setup vcan network devices
$> ip link add type vcan
$> ip link add dev vcan0 type vcan
$> ip link set vcan0 up

Documentation

Overview

Package canbus provides high-level access to CAN bus sockets.

A typical usage might look like:

sck, err := canbus.New()
err = sck.Bind("vcan0")
for {
    msg, err := sck.Recv()
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Frame

type Frame struct {
	ID   uint32
	Data []byte
	Kind Kind
}

Frame is exchanged over a CAN bus.

type Kind

type Kind uint8
const (
	SFF Kind = iota // Standard frame format
	EFF             // Extended frame format
	RTR             // Remote transmission request
	ERR             // Error message frame
)

func (Kind) String

func (i Kind) String() string

type Socket

type Socket struct {
	// contains filtered or unexported fields
}

Socket is a high-level representation of a CANBus socket.

Example
package main

import (
	"fmt"
	"log"

	"github.com/go-daq/canbus"
)

func main() {
	recv, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer recv.Close()

	send, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer send.Close()

	err = recv.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind recv socket: %+v", err)
	}

	err = send.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind send socket: %+v", err)
	}

	for i := 0; i < 5; i++ {
		_, err := send.Send(canbus.Frame{
			ID:   0x123,
			Data: []byte(fmt.Sprintf("data-%02d", i)),
			Kind: canbus.SFF,
		})
		if err != nil {
			log.Fatalf("could not send frame %d: %+v", i, err)
		}
	}

	for i := 0; i < 5; i++ {
		frame, err := recv.Recv()
		if err != nil {
			log.Fatalf("could not recv frame %d: %+v", i, err)
		}
		fmt.Printf("frame-%02d: %q (id=0x%x)\n", i, frame.Data, frame.ID)
	}

}
Output:

frame-00: "data-00" (id=0x123)
frame-01: "data-01" (id=0x123)
frame-02: "data-02" (id=0x123)
frame-03: "data-03" (id=0x123)
frame-04: "data-04" (id=0x123)
Example (EFF)
package main

import (
	"fmt"
	"log"

	"github.com/go-daq/canbus"
)

func main() {
	recv, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer recv.Close()

	send, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer send.Close()

	err = recv.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind recv socket: %+v", err)
	}

	err = send.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind send socket: %+v", err)
	}

	for i := 0; i < 5; i++ {
		_, err := send.Send(canbus.Frame{
			ID:   0x1234567,
			Data: []byte(fmt.Sprintf("data-%02d", i)),
			Kind: canbus.EFF,
		})
		if err != nil {
			log.Fatalf("could not send frame %d: %+v", i, err)
		}
	}

	for i := 0; i < 5; i++ {
		frame, err := recv.Recv()
		if err != nil {
			log.Fatalf("could not recv frame %d: %+v", i, err)
		}
		fmt.Printf("frame-%02d: %q (id=0x%x)\n", i, frame.Data, frame.ID)
	}

}
Output:

frame-00: "data-00" (id=0x1234567)
frame-01: "data-01" (id=0x1234567)
frame-02: "data-02" (id=0x1234567)
frame-03: "data-03" (id=0x1234567)
frame-04: "data-04" (id=0x1234567)
Example (SetFilters)
package main

import (
	"fmt"
	"log"

	"github.com/go-daq/canbus"
	"golang.org/x/sys/unix"
)

func main() {
	recv1, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer recv1.Close()

	err = recv1.SetFilters([]unix.CanFilter{
		{Id: 0x123, Mask: unix.CAN_SFF_MASK},
	})
	if err != nil {
		log.Fatalf("could not set CAN filters: %+v", err)
	}

	recv2, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer recv2.Close()

	err = recv2.SetFilters([]unix.CanFilter{
		{Id: 0x123 | unix.CAN_INV_FILTER, Mask: unix.CAN_SFF_MASK},
	})
	if err != nil {
		log.Fatalf("could not set CAN filters: %+v", err)
	}

	send, err := canbus.New()
	if err != nil {
		log.Fatal(err)
	}
	defer send.Close()

	err = recv1.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind recv socket: %+v", err)
	}

	err = recv2.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind recv socket: %+v", err)
	}

	err = send.Bind("vcan0")
	if err != nil {
		log.Fatalf("could not bind send socket: %+v", err)
	}

	for i := 0; i < 6; i++ {
		var id uint32 = 0x123
		if i%2 == 0 {
			id = 0x321
		}
		_, err := send.Send(canbus.Frame{
			ID:   id,
			Data: []byte(fmt.Sprintf("data-%02d", i)),
			Kind: canbus.SFF,
		})
		if err != nil {
			log.Fatalf("could not send frame %d: %+v", i, err)
		}
	}

	fmt.Printf("recv1:\n")
	for i := 0; i < 3; i++ {
		frame, err := recv1.Recv()
		if err != nil {
			log.Fatalf("could not recv frame %d: %+v", i, err)
		}
		fmt.Printf("frame-%02d: %q (id=0x%x)\n", i, frame.Data, frame.ID)
	}

	fmt.Printf("\n")
	fmt.Printf("recv2:\n")
	for i := 0; i < 3; i++ {
		frame, err := recv2.Recv()
		if err != nil {
			log.Fatalf("could not recv frame %d: %+v", i, err)
		}
		fmt.Printf("frame-%02d: %q (id=0x%x)\n", i, frame.Data, frame.ID)
	}

}
Output:

recv1:
frame-00: "data-01" (id=0x123)
frame-01: "data-03" (id=0x123)
frame-02: "data-05" (id=0x123)

recv2:
frame-00: "data-00" (id=0x321)
frame-01: "data-02" (id=0x321)
frame-02: "data-04" (id=0x321)

func New

func New() (*Socket, error)

New returns a new CAN bus socket.

func (*Socket) Bind

func (sck *Socket) Bind(addr string) error

Bind binds the socket on the CAN bus with the given address.

Example:

err = sck.Bind("vcan0")

func (*Socket) Close

func (sck *Socket) Close() error

Close closes the CAN bus socket.

func (*Socket) Name

func (sck *Socket) Name() string

Name returns the device name the socket is bound to.

func (*Socket) Recv

func (sck *Socket) Recv() (msg Frame, err error)

Recv receives data from the CAN socket.

func (*Socket) Send

func (sck *Socket) Send(msg Frame) (int, error)

Send sends the provided frame on the CAN bus.

func (*Socket) SetFilters

func (sck *Socket) SetFilters(filters []unix.CanFilter) error

SetFilters sets the CAN_RAW_FILTER option and applies the provided filters to the underlying socket.

Directories

Path Synopsis
cmd
can-dump
can-dump prints data flowing on CAN bus.
can-dump prints data flowing on CAN bus.
can-send
can-send sends data on the CAN bus.
can-send sends data on the CAN bus.

Jump to

Keyboard shortcuts

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