pyBus

Python

I wrote a serial interface for the proprietary BMW KBus. It decodes incoming frames and handles write timing. Along with a full REST API, it's an all-in-one solution to hacking the KBus.

I overhauled the development of a KBus frame interpreter.

The Challenge

BMW’s KBus is the lesser known proprietary cousin to an automotive standard CAN, as both dynamically handle communication between a vehicle’s modules. The KBus is used primarily between non-regulated, “non-essential” modules like A/C, seat controls, or radio. Here’s a great writeup.

Quite simply, I wanted this to be a basic interface between a host machine and the car’s bus. Each model of car is slightly different, I needed to reverse engineer the addresses and data specific to the ones on my particular SKU.

Reverse Engineering

Many packets were already published online, but for those that I found didn’t work or weren’t listed, I had to find on my own. Pressing a button in the car would trigger a packet to be sent on the bus, which this program has been picking up.

Knowing what should be happening for each button, I could add to the map of src:dest:data to directive functions. Here is a snippet of that mapping:

	'00' : {
		'BF' : {
			'0200B9' : 'd_carUnlocked', # Unlocked via key
			'1100' 	 : 'd_ignitionOff', # Engine off
			'7202'	 : None, # Key, no button pressed (released)
			'7212'   : 'd_carLocked', # Locked via key
			'7222'	 : 'd_carUnlocked', # Unlocked via key
			'7A'	 : 'd_windowDoorMessage', # Response to window / door status request
			'7D0000' : 'd_topClosed', # Technically 'sunroof locked', but responds when top closed
			'7D00'	 : 'd_topOpen' # Last packet is the state / progress of open
		}
	},

The ‘00’ global address sends to the ‘BF’ global broadcast address a small packet of data, which corresponds to that functionality we can now detect. More importantly, once we know what packets correspond to what functions, we can write to the bus to replicate these actions without a button press.

Writing

80 [src = IKE Instrument Control Electronics]
BF [dest = RAD Radio]
31000007 [data]

with a checksum to the kbus will result in the radio skipping to the next song. This is equivalent to the Seek > being pressed!

Feature Breakdown

After testing for functionality in my car, I created a two list of functions called Directives and Utilities. Directive functions are reactive, defining what happens when the interface reads specific activity. Utility functions meanwhile are active, and are designed to emulate specific actions in the car.

For example: when running this hypothetical directive (which calls a utility), we’d run in an endless loop:

# openTrunk would emulate the car, and the interface would subsequently read d_trunkOpen
d_trunkOpen(packet): # read trunkOpen from the bus
	openTrunk() # write openTrunk to the bus

Utilities can be used for doing things in addition to the car’s normal function. Mind you, we can never completely remap.

# Will skip media backwards AND put the convertible top down
d_steeringPrev(packet): # read prevButton on steering wheel pressed
	convertibleTopDown() # put down convertible top

With Utilities and Directives we have a competent system for both logging and executing the car’s various functions. With a REST API to open POSTs for remote control, pyBus can interact with other, more global systems running in the car.

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

Projects

Selected Works

MDroid

Golang, React Native

MDroid provides an extensible base for low power, always-on LTE control of non-critical systems. I started this project to bring my car's tech up to the current decade.

Read Me

pyBus

Python

I wrote a serial interface for the proprietary BMW KBus. It decodes incoming frames and handles write timing. Along with a full REST API, it's an all-in-one solution to hacking the KBus.

Read Me

AirPhoto

Golang, React Native

AirPhoto is an Android app and Golang server for shared iCloud streams. It parses Apple's binary plist data, then organizes the Albums, Photos, and Comments into queryable chunks.

Read Me

Fish Monitor

PHP, C++

An ESP-32 programmed to dynamically fetch, cache and distribute a fish tank's temperature and lighting status. A PHP webpage provides control and alerts me on Slack if the temperature becomes unsafe.

Read Me

AeroGarden App

React Native, Typescript

A guerilla redesign of AeroGarden's WiFi app, written in React Native for simple portability to both Android and iOS. I built it with a clean but functional aesthetic that strongly represents the premium brand.

Read Me

DROK PSU Module

Golang

A relatively simple Go Module for interfacing with Drok branded PSUs over UART. Abstracts reading and writing voltages, currents, and states. It utilizes a fully featured serial IO writer found in many similar Go projects.

Read Me