Control your classic BMW from your phone.
Ready-to-flash ESP32 firmware that puts the lights, windows, locks and trunk of your car on a web page β no app and no internet needed. A version for Arduino boards without Wi-Fi β Uno, Nano, Pro Mini, Mega β is included too. With transceiver schematics and wiring photos for the BMW E46.
Features Β· Quick Start Β· Web Interface Β· Hardware Β· Where to Connect Β· Messages Β· FAQ
Classic BMWs link their body electronics over a single wire, the K-Bus. A small microcontroller on that wire can tell the light module, the body module and the windows what to do.
This repository is the firmware side of that idea: complete sketches you upload, connect and use. The ESP32 version creates its own Wi-Fi network and lets you control the car from a web page on your phone.
| Firmware | Board | What it does |
|---|---|---|
E46_KBus_ESP32 |
ESP32 | Wi-Fi web interface to control the car from your phone. |
E46_KBus_Code |
Arduino Uno / Nano / Pro Mini / Mega | These boards have no Wi-Fi, so this version works from the remote key: welcome lights, goodbye lights and follow-me-home. |
Basic_Code |
Arduino Uno / Nano / Pro Mini / Mega | Bus reader that prints every message β useful to check your wiring. |
Important
These sketches need the BMW IBus KBus library. It handles the bus communication β receiving, checksums and collision-free transmitting β and has to be installed before the sketches compile.
flowchart LR
PHONE["Phone<br/>web interface"] <-->|"Wi-Fi"| MCU["ESP32"]
MCU <--> TRX["Bus transceiver<br/>TH3122.4 Β· ELMOS 10026B"]
TRX <--> CAR["BMW K-Bus<br/>12 V Β· single wire"]
| Function | How it works | |
|---|---|---|
| π± | Phone control | Lights, locks, trunk, windows, sunroof, interior light and wipers from any phone browser β no app, no internet. |
| ποΈ | Settings on the page | Change the sleep timers and switch functions on or off; everything is stored on the ESP32. |
| π | Bus monitor | See the latest bus messages live in the web interface. |
| π€ | Sleep mode | Powers down when the bus goes quiet and wakes up with the car, so it does not drain the battery. |
Arduino boards have no Wi-Fi, so their firmware is driven by the remote key instead:
| Function | How it works | |
|---|---|---|
| π‘ | Welcome lights | Press unlock β parking lights and turn signals come on. Press unlock again within about 15 seconds to add the fog lights. |
| π | Goodbye lights | Press lock β the lights come on for 2 seconds as you walk away. |
| π | Follow-me-home | With the car locked, press lock twice within 4 seconds to keep the headlights on. |
The ESP32 firmware includes these three as well; they can be switched off in the web interface.
1. Build the interface β the transceiver circuit connects the microcontroller to the 12 V bus.
2. Tap the bus β the CD-changer connector in the trunk gives you 12 V, ground and K-Bus in one plug.
3. Install the library β download the BMW IBus KBus library as a ZIP and add it in the Arduino IDE with Sketch β Include Library β Add .ZIP Libraryβ¦ It is also on its way into the Library Manager.
4. Get the firmware and open the sketch for your board in the Arduino IDE:
git clone https://github.com/muki01/BMW_IBus_KBus.git5. Upload.
- ESP32 β open
Codes/E46_KBus_ESP32, set your own Wi-Fi password inConfig.h, select ESP32 Dev Module and upload. Then connect your phone to theBMW-E46network and open http://192.168.4.1 - Arduino β open
Codes/E46_KBus_Code, select your board (Uno, Nano, Pro Mini or Mega 2560) and upload. Disconnect the transceiver from D0 / D1 while uploading; the bus shares the hardware UART with USB.
![]() |
![]() |
![]() |
| Control | Monitor | Settings |
The ESP32 creates its own Wi-Fi network and serves a single page that behaves like an app β it works without internet and without installing anything.
- Control β every button sends one message from
E46_Codes.h. Filter by category β lights, locks, windows, interior, wipers β and see at a glance how long the ESP32 stays awake. The buttons are defined inCommands.h; add, remove or reorder a line to change the page. - Monitor β the last 20 messages on the bus, newest first, with the sending and receiving module named.
- Settings β switch the key-fob light functions on or off, adjust both sleep timers and put the device to sleep. Settings are stored in flash.
The ESP32 does not use a sleep mode of its own. Exactly like the Arduino version, it is switched off completely by the bus transceiver and powered up again when the car wakes up.
| Situation | Behaviour |
|---|---|
| The bus is active | The ESP32 stays on. |
| The bus has been silent for 60 s | The ESP32 pulls the transceiver's EN pin low. The transceiver goes to sleep and switches the ESP32's power supply off. |
| You used the web interface | It stays on for another 300 s after your last action, even if the bus is silent. |
| Any message appears on the bus | The transceiver wakes up and switches the power supply back on; the ESP32 starts again β for example when you press the remote key. |
Both times can be changed on the Settings tab. The Control tab shows a countdown to the next sleep with a Stay awake button, and Sleep now is on the Settings tab.
Warning
Anyone who can join the Wi-Fi network can unlock the car. The firmware therefore has no default password and does not compile until you set your own in Config.h. Choose a strong one.
Note
The ESP32 firmware is experimental: it compiles on Arduino-ESP32 2.x and 3.x and the web interface has been tested in a browser, but it has not yet been verified in a vehicle.
The bus idles at battery voltage, so a microcontroller must never be wired to it directly. The firmware is designed around the TH3122.4 / ELMOS 10026B bus transceiver:
| Transceiver pin | Arduino | ESP32 | Purpose |
|---|---|---|---|
| TXD | D0 (RX) |
GPIO16 |
Bus β microcontroller |
| RXD | D1 (TX) |
GPIO17 |
Microcontroller β bus |
| SEN/STA | D3 |
GPIO4 |
Bus-idle detection before transmitting |
| EN | D4 |
GPIO5 |
Keeps the transceiver on; pulled low to switch everything off |
| β | D13 |
GPIO2 |
Bus activity LED |
| β | D7 / D8 |
USB | Debug output |
Arduino β powered from the transceiver's 5 V output. When the bus goes quiet the firmware pulls EN low, the transceiver switches its regulator off and the Arduino powers down with it. Bus activity wakes both again. The pins are the same on the Uno, Nano, Pro Mini and Mega 2560.
ESP32 β two things differ from the Arduino build:
- Power: the transceiver's regulator cannot supply an ESP32 with Wi-Fi, so the ESP32 gets its own 12 V buck converter with an enable pin. The transceiver's 5 V output β the pin that powers the Arduino β drives that enable pin instead. When the transceiver sleeps, the converter is off and the ESP32 draws nothing; when the bus wakes the transceiver, the converter starts and the ESP32 boots.
- Logic level: the transceiver uses 5 V logic and ESP32 pins are 3.3 V. Use a level shifter or voltage divider on the signals going into the ESP32 (TXD and SEN/STA).
The pins are set in Config.h.
Optocouplers (PC817) β built from common parts; well suited to reading the bus.
MCP2025 LIN transceiver β compact, with a built-in voltage regulator.
These circuits have no SEN/STA and EN pins, so the firmware's collision avoidance and sleep mode are not available with them.
The K-Bus is not available on the OBD-II port. These are the most practical places to reach it:
Pre-wired in the trunk on most cars, even when no CD changer is installed. One plug provides everything you need.
![]() |
![]() |
![]() |
| 1. Open the trunk β driver's side | 2. Remove the trim to reach the bracket | 3. The 3-pin connector X18180 |
| Wire colour | Signal |
|---|---|
| βͺπ΄π‘ White / red with yellow dots | K-Bus |
| π΄π’ Red / green | +12 V |
| π€ Brown | Ground |
The central splice point where every K-Bus branch of the car meets. Take the bus signal here and source 12 V and ground elsewhere.
![]() |
![]() |
| 1. Locate the connector block above the fuse box | 2. Unclip it and pull it out |
![]() |
![]() |
| 3. Find the K-Bus junction block | 4. All white / red / yellow wires are K-Bus |
The K-Bus wire (white / red / yellow) is also present in the radio harness behind the head unit.
E46_Codes.h contains more than 100 ready-to-send messages for the E46. A selection is shown here with its checksum. Behaviour varies between models and equipment levels, so verify each one on your own car.
Events the firmware can react to
| Message | Meaning |
|---|---|
00 04 BF 72 22 EB |
Key fob β unlock pressed |
00 04 BF 72 12 DB |
Key fob β lock pressed |
44 05 BF 74 04 00 8E |
Key inserted |
44 05 BF 74 00 FF 75 |
Key removed |
80 04 BF 11 00 2A |
Ignition off |
80 04 BF 11 01 2B |
Ignition position 1 |
80 04 BF 11 03 29 |
Ignition position 2 |
50 04 68 32 11 1F |
Steering wheel β volume up |
50 04 68 32 10 1E |
Steering wheel β volume down |
50 04 68 3B 02 05 |
Steering wheel β R/T button |
Lights
| Message | Action |
|---|---|
3F 0B BF 0C 00 00 00 00 7A 48 0A 06 B9 |
Parking lights + turn signals |
3F 0B BF 0C 00 00 00 00 7A 48 0B 06 B8 |
Parking lights + turn signals + fog lights |
3F 0B BF 0C 00 00 00 00 02 4E 0A 06 C7 |
Low beams |
3F 0B BF 0C 00 00 00 00 62 08 A0 06 4B |
Goodbye lights |
3F 0B BF 0C 00 00 80 00 00 00 00 06 01 |
Follow-me-home |
3F 0B BF 0C 00 00 00 00 00 00 01 06 80 |
Fog lights |
3F 0B BF 0C 20 00 00 00 00 00 00 06 A1 |
Hazard lights |
3F 05 00 0C 75 01 42 |
Hazard lights for 3 seconds |
3F 05 00 0C 01 01 36 |
Interior light on |
Windows, sunroof, locks and wipers
| Message | Action |
|---|---|
3F 05 00 0C 52 01 65 |
Driver window β open |
3F 05 00 0C 53 01 64 |
Driver window β close |
3F 05 00 0C 54 01 63 |
Front passenger window β open |
3F 05 00 0C 55 01 62 |
Front passenger window β close |
3F 05 00 0C 7E 01 49 |
Sunroof β open |
3F 05 00 0C 7F 01 48 |
Sunroof β close |
3F 05 00 0C 03 01 34 |
Central locking β toggle |
3F 05 00 0C 34 01 03 |
Lock doors |
3F 05 00 0C 02 01 35 |
Open trunk |
3F 05 00 0C 49 01 7E |
Front wipers |
3F 05 00 0C 62 01 55 |
Front washer |
3F 05 00 0C 4E 01 79 |
Alarm LED ("clown nose") for 3 seconds |
Want to write your own functions? The message format, the API and the module address list are documented in the library repository.
The firmware and message table were written for the BMW E46. The K-Bus itself is shared by many models, so the hardware and the library also work on the cars below β the messages may differ and need to be verified.
| Chassis | Series | Years | I-Bus | K-Bus |
|---|---|---|---|---|
| E46 | 3 Series | 1997β2006 | β | |
| E38 | 7 Series | 1994β2001 | β | β |
| E39 | 5 Series | 1995β2004 | β | β |
| E53 | X5 | 1999β2006 | β | β |
| E83 | X3 | 2003β2010 | β | |
| E85 | Z4 | 2002β2008 | β |
BMW_IBus_KBus/
βββ Codes/
β βββ E46_KBus_ESP32/ ESP32 firmware: web interface for your phone
β βββ E46_KBus_Code/ Arduino firmware: light functions from the remote key
β βββ Basic_Code/ Bus reader for checking the wiring
βββ Schematics/ Transceiver circuits
βββ images/ Wiring photos and screenshots
The bus communication code lives in its own repository: BMW_IBus_KBus_Library.
Can I connect to the OBD-II port instead?
No. The K-Bus is the car's internal body network and is not present on the OBD-II connector. The line on the OBD-II port is the diagnostic K-Line β for that, see OBD2 K-line Reader.
Will it drain my battery?
No. Both versions are switched off completely by the transceiver when the bus goes quiet, and powered up again when the car wakes up. While the car sleeps, only the transceiver's own sleep current remains.
Which Arduino boards work?
The Arduino sketches build for the Uno, Nano, Pro Mini and Mega 2560. Boards with native USB such as the Leonardo and Micro are not supported as they are, because their Serial port is the USB connection and not a UART.
Why is there no default Wi-Fi password on the ESP32?
Because the web interface can unlock the car. A password that is published in a repository would let anyone nearby open every car running this firmware, so you have to choose your own before the sketch compiles.
Does it work on other BMWs?
The hardware and the library work on any car with an I-Bus or K-Bus. The messages in this repository were collected on an E46 and should be checked on other chassis before you rely on them.
How do I add my own button to the web interface?
Add one line to Commands.h with the group, the button text and the name of a message from E46_Codes.h. The page is built from that list.
Contributions are welcome β especially:
- Test reports for the ESP32 firmware
- Verified messages for other chassis (E38, E39, E53, E83, E85)
- Wiring photos and connection points for other models
Please read the Contributing Guide and the Code of Conduct. Tested it on your car? Open a vehicle report with the model and year β real-world reports help everyone.
This firmware is part of a family of open-source automotive projects. They share the same hardware approach, so what you build for one carries over to the others.
| Firmware β flash it and use it | ||
|---|---|---|
| BMW I-Bus / K-Bus Firmware you are here |
Phone control and key-fob light functions for the BMW E46, on the ESP32 and Arduino. | |
| OBD2 K-Line Reader | Scan tool for K-Line cars (ISO 9141-2, KWP2000) with a web dashboard, for the ESP32, ESP8266 and Arduino. | |
| OBD2 CAN Bus Reader | Scan tool for CAN bus cars (ISO 15765-4) with the same web dashboard, for the ESP32. | |
| VAG KW1281 | KW1281 diagnostics for VW, Audi, Ε koda and SEAT: ECU information, measuring groups and fault codes. | |
| Libraries β build your own firmware | ||
| BMW IBus KBus Library | Receives, checks and sends BMW I-Bus and K-Bus messages; the library behind the BMW firmware. | |
| OBD2 K-Line Library | K-Line diagnostics behind one API: ISO 9141-2, KWP2000, KW1281, DS2 and KW82. | |
| OBD2 CAN Bus Library | OBD-II diagnostics over ISO 15765-4 with the ESP32's built-in CAN controller. | |
| Interface | ||
| OBD2 Diagnostic UI | The web dashboard used by the two OBD2 readers. | |
I design automotive diagnostic tools, firmware and hardware professionally. Whether you need a complete product or only the communication layer, I can help.
| Service | Details |
|---|---|
| Protocol implementation | BMW I/K-Bus, K-Line (ISO 9141-2 / KWP2000), CAN / UDS, VAG KW1281 and other manufacturer-specific protocols |
| ECU communication & reverse engineering | Bus sniffing, packet decoding, module control, undocumented ECUs and buses |
| ECU security access | Seed-key algorithms and unlock routines for KWP2000 / UDS |
| Embedded firmware | Arduino, ESP32, ESP8266, STM32, Raspberry Pi Pico |
| Custom hardware | Diagnostic dongles, shields and PCBs designed to your requirements |
| Companion apps | Android, iOS and web apps to visualise, log and control your device |
Have a project in mind? Reach out through the Contact section below.
For custom development, collaboration, sponsorship or ready-made devices:
| Channel | Address |
|---|---|
| π§ Email | muksin.muksin04@gmail.com |
| πΌ LinkedIn | linkedin.com/in/muksin-muksin |
| π GitHub | @muki01 |
If this project helped you, consider supporting its development:
Warning
This is a hobby and development project. Transmitting on a live vehicle bus can affect lighting, locking and other body functions. Test with the vehicle stationary, proceed at your own risk, and never operate the system in a way that distracts from driving. The author accepts no responsibility for damage or malfunction.
BMW is a registered trademark of BMW AG. This project is independent and is not affiliated with, endorsed by or sponsored by BMW AG.
Released under the GNU General Public License v3.0.
- You are free to use, study, modify and share this firmware.
- If you distribute it β on its own or as part of a product or firmware β you must make the complete source available under the same license.
Closed-source or commercial product? A separate commercial license is available. Get in touch through the Contact section.
Copyright Β© 2023β2026 Muksin Muksin.
Created by Muki Β· If this project helped you, please give it a β
BMW Β· I-Bus Β· K-Bus Β· IBus Β· KBus Β· E46 Β· ESP32 Β· Arduino Β· web interface Β· welcome lights Β· follow-me-home Β· car hacking Β· TH3122












