Control With Bluez

Now for some real fun, I'll try to control the light bulb using a BLE adapter on a computer.  I'm going to use a Raspberry Pi, Bluetooth 4.0 USB adapter, and the bluez Bluetooth stack becuase it's easy to setup and use.  Unfortunately there is no cross-platform Bluetooth stack or API that works across Windows, Mac, Linux, etc. so if you want to use a different platform you'll need to look at that platform's Bluetooth Low Energy stack and API.

To setup the Bluetooth dongle and bluez I followed the steps in the setting up section of the Pi Beacon guide here.  A couple small changes I made were to download and build the latest version of bluez (5.28 as of the time of this writing) and to manually install bluez's GATT tool.  For some reason bluez does not install its GATT tool anymore as this bug notes, however an easy workaround is to manually install it by executing this command inside the bluez source directory after it has been compiled and installed:

sudo cp attrib/gatttool /usr/bin/

Confirm you can access gatttool by running 'gatttool --help' (without quotes) to see the usage information of the tool.  If you see an error that gatttool can't be found, double check it has been compiled by bluez and it's in to the /usr/bin/ directory.

Now I brought up the Bluetooth USB adapter on the Pi by running the command hciconfig to find the name of the adapter (it should be hci0 assuming it's the only Bluetooth adapter connected to the Pi).  Then running 'sudo hciconfig hci0 up' (without quotes) to turn on the adapter.  Finally running hciconfig again should show the adapter is in the UP RUNNING state as shown below:

Now that the adapter is up I can scan for BLE devices by running the command:

sudo hcitool lescan

Information about nearby BLE devices will be displayed.  Press Ctrl-C to stop the scanning process.  Notice from the picture below my light bulb address and name are visible during the scan:

If you don't see your light bulb in the scan then make sure it is turned on and that no devices are connected to the bulb.  Remember BLE only allows one device to be connected at a time so if you left the bulb's control application or a BLE GATT  app running then it might still be connected to the bulb and preventing you from finding the bulb.  Close out of all apps using the bulb and try running the scan again until you see the bulb being advertised.

Next I run the bluez GATT tool to interact with the bulb.   I ran this command to start GATT tool's command shell:

sudo gatttool -I

A command prompt is shown and I can type help and press enter to see a list of commands.

Now I connect to the bulb by issuing a connect command:

connect <bulb address>

Where is the address of the bulb that was found with the previous scan command.  In my case I ran 'connect 5C:31:3E:F2:16:13' (without quotes) to connect to my bulb.  After a moment a 'Connection successful' message should be displayed like below:

Once connected to the bulb some commands can be run to examine the bulb in more detail.  In particular the primary command will list services exposed by the bulb like below:

The output of the primary command is a raw list of the characteristic handles and service UUIDs implemented by the bulb.  This is the same information from earlier when exploring the GATT, but with a bit lower level of detail.

In particular I can see the characteristic handle 0x0028 falls within the range of the 0x1802 service UUID (for UUIDS that have the form 0000xxxx-0000-1000-8000-00805f9b34fb they are officially recognized UUIDs and are abbreviated with the shorter 16-bit UUID).  Looking at the Bluetooth services list the 0x1802 service is the Immediate Alert service, which is typically used for proximity sensors and similar devices.  Very odd that the light bulb appears to be using this service to control its color!

Another command that can be run is the char-desc command to get details on a particular characteristic.  I ran this command to query the 0x0028 characteristic:

char-desc 0x0028 0x0028

(both 0x0028 values are necessary as the command takes a range of beginning and ending handles)

I saw a response like the following which tells me what UUID represents this characteristic:

Going to the Bluetooth characteristic list I can see this characteristic is the alert level characteristic.  I can see from the characteristic definition that it is normally only takes one byte which is interpreted as a level of alert.  However from the protocol sniffing earlier it looks like the bulb has overloaded the alert level characteristic to take 9 bytes, including the 3 bytes of RGB color information--very strange, indeed!

Now for the moment of truth, can I change the color of the bulb by writing to this characteristic based on what was seen from sniffing the protocol?  I executed commands like these to write new values to the 0x0028 alert level characteristic:

char-write-cmd 0x0028 58010301ff00ff0000
char-write-cmd 0x0028 58010301ff0000ff00
char-write-cmd 0x0028 58010301ff000000ff
char-write-cmd 0x0028 58010301ff00000000
char-write-cmd 0x0028 58010301ff00ffffff

Woo hoo!  The light bulb changed its color after each command was run!  In particular, writing 58010301ff00ff0000 made the bulb turn red58010301ff0000ff00 turned the bulb green, and 58010301ff000000ff turned the bulb blue.  Sending RGB colors of 000000 and ffffff turned the bulb off and on at full bright white respectively too.  This confirms what I suspected from the protocol reverse engineering, the last 3 bytes of the message represent the red, green, and blue color of the bulb.

I could mix and match colors in between too, for example sending ffee00 for a yellow color.  An HTML color picker is helpful for finding color byte values quickly.

To really confirm my understanding of the bulb's protocol I duplicated this GATT tool control process with a second bulb.  I turned on a second bulb, scanned for BLE devices again to find the new bulb's address, and connected with GATT tool to change its color.  The same characteristic write commands above worked to control the second bulb's color!  It appears the 6 bytes at the start of the characteristic write are just a fixed value and luckily do not represent anything meaningful or necessary for changing the bulb's color.

Now that the protocol is understood I had some fun by controlling the light from code.  As a simple example I made a python script to use bluez's GATT tool and cycle through a rainbow of hues (note that if you are a more experienced bluez user you might realize that GATT tool can be controlled from the command line directly, however in my testing I couldn't get GATT tool to control the bulb outside of an interactive session, perhaps because of a bug inside the tool).  If you'd like to try yourself you can grab the script from this repository and install its dependencies by executing these commands on the Pi:

sudo apt-get update
sudo apt-get install git build-essential python-dev python-pip
sudo pip install pexpect
cd ~
git clone https://github.com/adafruit/BLE_Colorific.git
cd BLE_Colorific

Then run the script and provide it the address of the bulb to control as the first parameter.  Be sure to run the script as a root user with sudo too.  For example to control my bulb I ran:

sudo python colorific.py 5C:31:3E:F2:16:13

You should see the bulb cycle through all the hues of color.  If you'd like to adjust the speed, range of hues, etc. edit the colorific.py file and change some of the variables defined near the top (look at the comments to see what they mean).

Phew!  That was a decent amount of work but it's quite satisfying to have control over the bulb.  The sky is the limit as far as interesting things to do with a bulb that you can control yourself over Bluetooth Low Energy!  For example you could make the bulb change color if you get new emails or even based on the local weather forecast.  You can animate the bulb like the demo of cycling through hues or do something more interesting like flashing the bulb in time with music.  Be creative and turn the bulb into something fun and interesting!

This guide was first published on Mar 01, 2015. It was last updated on Sep 24, 2018. This page (Control With Bluez) was last updated on May 04, 2015.