02Portfolio
WireAmbi — car ambient lighting from the phone and Android Auto
An Android app for cheap ELK-BLEDOM and MELK LED strips that runs on the phone and on the Android Auto screen. The light pulses to music, and voice commands work offline. With the led-auto gateway it also shows the state of the doors and locks.
- 01/07
- 02/07
- 03/07
- 04/07
By the numbers
- Automated tests
- 359
- From beat to colour sent
- 6 ms
- Music reaction styles
- 9
Problem
Cheap ELK-BLEDOM-family LED controllers come with no documentation, and the vendor app does not run on the car screen. Different models understand the same commands differently: the controller in the car ignored them, even though the phone reported every send as successful. The controller does not report its state, accepts only one connection at a time and has no encryption. In Android Auto the sound never leaves the phone speaker, so music mode cannot pick it up through the microphone.
Approach
I took the controller commands from the public model list in the elkbledom integration for Home Assistant and checked them on hardware. The app recognises the model by name and picks one of three command variants, and it computes effects that different models interpret differently itself. Every command waits for confirmation and is resent if refused, and during rapid colour changes the strip always gets the latest one, so the light never lags behind. In music mode the app listens to what the phone is playing, detects the beats and tempo of the track and predicts the next beat. The logic is kept apart from Android and Bluetooth, so tests check exactly the bytes that would reach the controller. The Android Auto screens stay within the system’s limits, which I read from the library’s own code. The app connects to the led-auto gateway over the encrypted WireLink channel.
Outcome
The app runs with a real controller (MELK-OC21) on Android 15. I tested the car screens in the Android Auto emulator, and in the car the app works with the led-auto gateway and the Android Auto panel. It is covered by 359 automated tests, and the release build compiles without warnings. From a detected beat to the colour being sent takes 6 ms on average. On a 123 BPM track the typical gap between flashes was 487 ms, against the 488 ms the tempo implies. The interface is in Polish and English.
How it works
The key features, in short clips.
01
Pairing without guesswork
A wizard walks through permissions and the Bluetooth search and lists controllers from the strongest signal down. The chosen controller is remembered, so in the car WireAmbi reconnects on its own, including inside Android Auto.
02
Colours, scenes and a colour wheel
Eight preset colours, a colour wheel covering the full range and scenes that save colour, brightness, mode and speed under a name. The slider sends only the value where the finger stopped, and every command waits for confirmation, so none is silently lost.
03
Light that follows the music
The app listens to what the phone is playing rather than the microphone, so music mode also works with Android Auto. It detects the beats and tempo of the track itself and predicts the next beat ahead of time. There are nine reaction styles to choose from, from pulse to rainbow and sparks.
04
Calibration for any controller
Cheap controllers understand commands in three different ways, and the app picks the right one by device name. When a strip is wired differently and the colours get mixed up, the colour test shows it at once, and a single tap sets the right order.
05
Car panel with the led-auto gateway
The phone connects to the led-auto gateway over the encrypted WireLink channel and shows the state of the locks and doors live on a 3D model of the car. Opening a door turns on the entry light. The app protects unlocking and the windows with the owner’s biometrics or PIN, but these functions are not wired up in the car yet.
06
Android Auto and offline voice
The car screen has a colour grid, scenes and shortcut tiles that you arrange on the phone. Voice commands are recognised by Vosk without an internet connection. The app only knows its own list of commands and acts on one only when it has recognised every word with confidence.