GoKBus - BMW Serial Data in Go

Project Code 3

I designed a PCB for interfacing with my car. It has 5 relays that control custom add-ons like Angel Eye lights and a Raspberry Pi w/LTE connectivity, while communicating with BMW’s GPS and CAN modules. It’s is the hardware foundation for my BMW Control Center.

GoKBus is part of the monorepo for controlling the vehicle.

Go KBUS

Go KBus is a golang module designed to interface with the BMW I/K Bus. This protocol is similar to CAN, and controls the non-essential components in the car.

This module can be used to read, write, and interpret BMW serial commands. It’s loosely based on ezeakeal’s excellent pyBus (and my subsequent fork).

Overview

  • USB serial interface can be acquired from Reslers.de. Other USB interfaces should work just as well, although are untested.
  • Communicates on the I-BUS to send and receive diagnostics, running status, button presses, vehicle info, etc.

Install

go get github.com/qcasey/gokbus

Example module usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import (
	"log"

	"github.com/qcasey/gokbus"
)

func main() {
	kbus, err := gokbus.New("/dev/ttyUSB0", 9600)
	if err != nil {
		panic(err)
	}
	defer kbus.Port.Close()

	// Start the read and write channels
	// This isn't required - we can ReadPacket() / WritePacket() separately without channels,
	// but timing will be less precise and many packets will be dropped.
	go kbus.Start()

	// Read 5 packets
	for i := 0; i < 5; i++ {
		select {
		case newPacket := <-kbus.ReadChannel:
			log.Print(newPacket.Pretty())
		}
	}

	// Prepare a write packet, this one opens the trunk
	openTrunkPacket := gokbus.Packet{
		Source:      0x3F,
		Destination: 0x00,
		Data:        []byte{0x0C, 0x02, 0x01},
	}
	
	// alternatively, a list of known packets are provided in /pkg/prepackets
	// flashLowBeamsPacket := prepackets.FlashLowBeams

	// Block until packet is written to the bus
	kbus.WriteChannel <- openTrunkPacket

	// Read another 5 packets
	for i := 0; i < 5; i++ {
		select {
		case newPacket := <-kbus.ReadChannel:
			log.Print(newPacket.Pretty())
		}
	}

}

Missing write confirmation that pyBus offers

http://web.archive.org/web/20041204074622/www.openbmw.org/bus/
https://web.archive.org/web/20190210133920/http://web.comhem.se/bengt-olof.swing/ibusdevicesandoperations.htm
https://web.archive.org/web/20180511152050/http://www.online-rubin.de/BMW/I-Bus/I-BUS%20Codes%20e46.htm