Lately, I find myself giving lots of talks about The Physical Web and Web Bluetooth. To help demonstrate some of the capabilities of these technologies, I wanted to find an affordable device for my demos — preferably under $10 — so my audience can easily get the demo equipment and try it themselves.
Searching the Internet led me to a few consumer “smart bulbs” from China for under $10, so I ordered two kinds to play with. The smart bulbs include an RGB LED, so they can change colors, and they are, of course, controlled by Bluetooth! As you can expect from this kind of product, there wasn’t any documentation — just link to download Android app. Since I wanted to show how I control them through Web Bluetooth, I decided to try and reverse engineer the protocol.
Why take the time to reverse engineer the protocol?
First of all, this way is a lot more fun. It also gives you the ability to integrate it with anything, such as a weather service (bulb changes color according to weather), your startup’s automated build (bulb is red when the code is broken), or flashing random colors rapidly just for the sake of it (my audiences really seem to enjoy this last use for it).
Once you have control over the bulbs, the possibilities are limited only by your imagination: you could control it with your voice (using voice recognition), control it with the accelerometer of your phone, flash the bulb whenever you get a phone call, or even use it to regulate your sleep cycle by changing its color temperature throughout the day to get an effect that resembles sunrise/sunset light to help regulate body melatonin levels throughout the day. And those are only the ideas that would fit on the back of my napkin!
To complete this project, you don’t need to know everything there is about Bluetooth, but some basic concepts are needed to make it go.
If you want more information about Bluetooth Low Energy (a.k.a BLE), I’d be happy to point you in the right direction or write a post explaining the more technical aspects of BLE — hit me up in the comments!
Bluetooth Low Energy 101 (or maybe 100)
In Bluetooth Low Energy, devices can perform one of two roles. A device can be either a “Central” (in this example, your phone) or a “Peripheral” (and respectively, the bulb).
Bluetooth devices have services that correspond to one function of the device. For example, your smart watch might expose a service to report the battery level of the device, and then another for measuring your heart rate. Each service exposes variables/properties called characteristics. The characteristics represent one parameter of the service, which can be read, written or both.
For example, in the Battery service above, it will have a Battery Level Characteristic, a read-only value containing 1-byte value between 0 and 100, reporting percentage of battery remaining in the device.
A temperature service can have one characteristic for the temperature, and another one for the humidity, both are read-only. A smart bulb service can have one characteristic for the on/off switch (writing 0 turns it off, 1 on), and another characteristic for the brightness (0 to 100 or so), which can be either write-only or read+write.
Peripherals periodically advertise which services they have (usually once per second or so). Centrals (such as your phone) see those advertisements, and can initiate a connection with any peripheral around them, and start reading/writing from the characteristics exposed by its services.
Each service and characteristic is identified by a unique 16-bit or 128-bit number, such as
ff05 (16bit) or
00000000–0000–1000–8000–00805F9B34FB (128bit). 16bits are reserved for standard services and characteristics, such as the Battery Level service mentioned before, and are defined by the Bluetooth SIG Group. Nevertheless, many consumer devices like to use them for their own purposes.
Reverse Engineering the Bulbs: Bulb 1
After connecting to the bulb, I wrote random values to the different characteristics exposed by the device, and eventually it changed the color. After some trial and error, I figured out that the protocol was very simple. All you need to do is write 4 bytes to Service
ffb0 / Characteristic
ffb2, with the following format:
BB GG RR WW (blue, green, red and white levels), corresponding the internal LEDs of the bulb.
I didn’t even have to get the app for this bulb, and never did — I just controlled it directly via nRF Connect and later wrote a small Node.js app to control it using noble.
Reverse Engineering the Bulbs: Bulb 2
The second bulb, a Magic Blue UU E27 Bulb, was much more interesting. Using the same technique with nRF Connect, I immediately spotted the only writable Characteristic (Characteristic number
ffe9 in Service
ffe5), but sending values to it didn’t have any effect. I decided to try another approach — using the official Android app that comes with bulb, then recording all the communication, figuring out the commands, and then send them to the bulb myself to control it.
To start, I installed the official app for this bulb, made sure Bluetooth was enabled, and opened the app to make sure I could pair with the bulb and control it through the app.
Android 4.4 (and newer) has an option to record all Bluetooth packets going in/out of the device. I used this feature to record the messages between the app and the bulb. If you want to try it yourself, it’s really easy to enable:
- First, you need to enable Developer Mode in Android if you haven’t done so already.
- Next, go to Settings, then open “Developer Options” and turn on the “Enable Bluetooth HCI snoop log.” This will start recording all the Bluetooth traffic that goes through your device.
Once I had my recording mechanism all set up, I opened the “Magic Blue” app and sent some commands to the light bulb to change its color several times). To finish up the first part of the process, I copied the Bluetooth communication log from my Android device to my PC.
You can find the recording file in
/sdcard/btsnoop_hci.log. You can use the “File Manager” app to locate this file and share it via Google Drive or Email, or you can connect the Android device to your PC as using a USB cable, and locate the
btsnoop_hci.log file inside the root folder.
If you have the Android SDK on your computer, you can also connect it using a USB cable and use the following command to copy the log:
adb pull /sdcard/btsnoop_hci.log
Note: in some devices,
btsnoop_hci.log is created in a different path, such as
I used Wireshark to open the Bluetooth log. Wireshark is a free tool that lets you analyze network traffic. If you’re trying to reverse engineering the bulb yourself, note that you may need to rename the file to
btsnoop_hci.pcap for Wireshark to recognize it.
Initially, there were a ton of packets, some of them likely unrelated Bluetooth traffic. I used the “Filter” option (see photo above) to select just the “Write Characteristic Value” commands. I used this filter:
(Alternatively, you could also filter by the device address to see all the communication with a specific device. Here is an example for filter with my MagicBlue bulb address:
Sometimes it’s easier to find what you’re looking for this way.)
Looking into one of the Write commands, I found this payload:
The payload was
56 ff 08 5a 00 f0 aa.
I used the nRF Connect app mentioned above to send this value to characteristic
ffe9 of service
ffe5 (if you’ll remember, this was the only writable one), and voila — the led changed to color pinkish-purple.
By experimenting with a few other combinations, I figured out the format of the protocol. I discovered that there are actually two formats, one for controlling the RGB LED and another for controlling the warm white LED (seems like they can’t be both on at the same time):
56 RR GG BB 00 f0 aa
The first byte is always
56, then three bytes for the red, green and blue values, and then another three bytes with values
00 f0 aa.
For the white LED the format is:
56 00 00 00 WW 0f aa
The first byte is still
56, then next three bytes are
00 (or whatever you want, really, as the device will pay them no attention), then a value that specifies the intensity of the white LED, and two other bytes with the values 0f
Finally, the bulb also includes some fancy modes, such as fading between two colors. These are activated by a different command:
bb II SS 44
II is the index of the lighting mode (values between
38 have effect), and
SS is the speed (lower values mean faster change of colors), each unit is about 200 ms (so value of 5 will trigger a change every second).
For example, mode number 25 changes fades between all the rainbow colors and white. To activate it with about 1 second delay between every two colors, send the following command:
bb 25 05 44
A Word About Security
As you have seen above, both smart bulbs contain no security mechanism. This means that everyone within range can connect to them and control them. While the second bulb at least required some effort to reverse engineer the protocol, the first one didn’t even require a lot of effort. I hope that some of the higher-end smart bulbs are designed with security in mind, though from a quick Google for “Bluetooth smart bulb security,” it seems like nobody really addresses these concerns at the moment (for example, I could only find one reference to a security review of a smart bulb).
So just know that though these bulbs are nice as a decoration, a toy or part of an art project, you might have to tolerate your neighbor suddenly changing the lights of your bulbs at home after reading this post…
Moral of the story: I wouldn’t use them for anything critical.
Conclusions: we’ve hacked the bulbs… now for (more) fun!
So now we’ve hacked the bulbs by reverse engineering the protocols and we can confidently change the colors of our neighbors’ smart bulbs (I’m kidding: I don’t condone or recommend this at all… I’m just saying we could).
If you’re interested in playing with the smart bulbs I used, you can get them here (first) and here (second). I invite you to experiment with the bulbs yourself and see what neat things you can do with them (and feel free to let me know in the comments if you run into any trouble or discover anything extra cool!).
In my next post, I’ll talk about Web Bluetooth and demonstrate how you can control the bulbs from a web page. So if you get yourself a bulb, you’ll be ready to follow along :)
Update (Feb 2017)
I took apart the bulb and reverse engineered its firmware:
Interested in learning how the internals of the bulb work? Check out the follow-up post where I extract the firmware from the bulb and reverse engineer it, or read how I made the bulb run without mains power.