Pinterest Stumbleupon Whatsapp
Ads by Google

The Philips Hue range of lights are certainly not cheap (there are some alternatives Philips Hue Alternatives That Are Actually Worth It Philips Hue Alternatives That Are Actually Worth It The Philips Hue system is leading the charge when it comes to smart lighting, but there are some worthy alternatives. We've picked three that all offer the same basic feature set and hackability. Read More ), but one thing that I really appreciate is the well documented API What Are APIs, And How Are Open APIs Changing The Internet What Are APIs, And How Are Open APIs Changing The Internet Have you ever wondered how programs on your computer and the websites you visit "talk" to each other? Read More  for making your own Hue apps. Today I’ll be showing you how to control your Hue lights from an Arduino – then adding a simple motion sensor.

Why are we doing this? Because home automation systems can be quite rigid and expensive. By learning how to control the Hue from Arduino, you open the doors to a variety of custom made home automation projects that simply can’t be beaten by off-the-shelf components. If hacking things together just isn’t your thing, try these 8 fabulous Hue apps 8 Fabulous Apps for Philips Hue Lights 8 Fabulous Apps for Philips Hue Lights The Philips Hue system has its own app, but why settle for the default when there's so many cooler options out there? These 8 apps give you fabulous options for some really cool effects. Read More instead.

The Hue System

Let’s get technical for a bit so you’ll know the underlying systems you’re working with. Hue lights create a mesh network Mesh Networks: The Future of Communication Mesh Networks: The Future of Communication Mesh networks are almost invulnerable. In a mesh network, there are no choke points through which all traffic passes. Instead, information is passed from one device to the next until it reaches its destination. Read More , using a short range wireless protocol called ZigBee – specifically, they are ZigBee Light Link certified, which means other ZLL products should also work alongside the Hue (in theory).

Although technically short range, the mesh networking feature of ZigBee means that each new bulb extends the network, relaying messages to other bulbs. This means that if you’re having trouble controlling a light on the other side of the house, try placing another light in between the two.

Zigbee is a great protocol, but it’s quite different to Wi-Fi or a wired computer network, so we need the Philips Hue Bridge to join the two together. The Hue bridge runs a modified open source linux firmware, which broadcasts a basic web server.

This is what you'll see if you just type in the IP address of your Hue bridge into your browser. You can't do much from here though.
This is what you’ll see if you just type in the IP address of your Hue bridge into your browser. You can’t do much from here though.

It’s by interacting with this local web server that you can find out the current status of the lights, and control them.

Ads by Google

It’s a beautifully simple system, and ripe for DIY projects. Kudos to Philips for making this thing so hackable.

Starting Out

Before you can access the API documentation, you’ll need to register as a developer. It’s free, but you need to accept the terms and conditions. Do this now.

Anyone familiar with standard web services or Javascript should be able to work with the Hue: all data is passed and received as JSON packets What Is JSON? A Layman's Overview What Is JSON? A Layman's Overview Whether you plan to be a web developer or not, it's a good idea to at least know what is JSON, why it's important, and why it's used all around the web. Read More .

To have a look at this in action, you’ll need to know the IP address of your Hue bridge. There are a few ways to do this:

network mapping to find bridge

When you’re done, go ahead and type it into your browser address bar with debug/clip.html appended to the URL. In my case, this was:

http://192.168.1.216/debug/clip.html

This is a debugging tool that let’s you send and receive the JSON packets through a simple web interface. The first step is to enable the developer profile on the Hue Bridge itself – which is disabled by default for security reasons. Paste the following into the BODY field, leave the URL as /api/, and send a POST request by clicking the post button:

{"devicetype":"test user","username":"newdeveloper"}

The first time you do this, you’ll see a “link button not pressed” somewhere in the response. This is a security feature that requires every new application you use to be physically authorized. Go and find your Bridge, press the button, and send the same request again within 30 seconds. This time you’ll get a different response, and the user will be authorized. If you’d like to use a different username, read the API docs about creating users. For now, this will suffice.

Once your user is setup, the base URL you should interact with becomes /api/newdeveloper/ . You can send a GET request to find out everything your Bridge currently knows about connnected lights, alarms, scenes, and a short log of apps that have been used. Here’s a sample of some of the status information contained for a single bulb.


"state": {
	"on": true,
	"bri": 254,
	"hue": 14910,
	"sat": 144,
	"effect": "none",
	"xy": [
		0.4596,
		0.4105
	],
	"ct": 369,
	"alert": "none",
	"colormode": "ct",
	"reachable": false
	},
"type": "Extended color light",
"name": "Bedroom 1",
"modelid": "LCT001",

Note that the “on”:true state doesn’t actually show you if the bulb is on or not; only that according to the Bridge settings, it should be on. “reachable”:false can indicate both a bulb that is too far away, or simply turned off at the power switch.

One last example before we integrate this into the Arduino: make sure one of your lights is visible and on, and that you know which number it is. Change the URL to /api/newdevelopers/lights/1/state (changing the number to your light), and send a PUT request with the following data:

{"hue": 50100,"sat":255,"bri":255}

You should see your light react like this:

hue demo

What you’ve done is to push a new state to the bulb. You can also add “transitiontime”, which is a primitive animation method indicating how many seconds you’d like the state change to take.

The color can be set in a number of different ways, but unfortunately there’s no simple way to send an RGB value. In the example above, we sent hue, saturation, and brightness. Try changing the hue value and sending the PUT request again.

Working From Arduino

There is an existing Hue / Arduino library called ArduinoHue which Philips themselves link to in the API documentation, but the problem with this library is that it communicates over the USB connection to your PC, which also needs to be running a Python application constantly. Eugh. You may as well let your computer run the entire thing at that point, and cut out the Arduino entirely.

Instead, I’ll show you how to control the Hue from the Arduino using an Ethernet shield. Your Arduino needn’t be connected to a computer, so it can operate independently anywhere you can put an Ethernet cable. In fact, it should also work with a Wi-Fi shield, but I don’t have one to play with.

ehternet-sheild-box

If you’d like to skip ahead, the full sample code is embedded below, or available here. I’ve adapted it from an example posted by Gilson Oguime. If you’ve never played with your Ethernet shield before, you might want to have a quick run through the web client tutorial – I’ll assume some level of familiarity with this, and won’t be covering the code used to establish a network IP etc. We’ve also shown you how to create a mini web-server with the Ethernet shield Give Your Arduino Project Its Own Mini-Webserver, With An Ethernet Shield Give Your Arduino Project Its Own Mini-Webserver, With An Ethernet Shield A while ago, I showed you how to setup an internet control system for your Arduino - but it had to stay connected to a computer through USB in order to maintain the internet connection.... Read More .

Creating State Changes

Creating a new state to push to the bulbs is a simple case of creating a new String variable, and escaping all the double quotes. I’ve added a random() function in there as well to create a somewhat dynamic animation. Try making the hue variable random too for different colors.

String command = "{\"on":true,\"hue\":50100,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}";

Sending the Command

To actually send the command, you have a helper function called setHue() which takes the light number and the command string as an argument, like so:

setHue(1,command);

All it does then is it connects to the bridge, spits out the command as a PUT request, along with all the other nonsense that creating an HTTP request involves.


client.print("PUT /api/");
client.print(hueUsername);
client.print("/lights/");
client.print(lightNum);
client.println("/state HTTP/1.1");
client.println("keep-alive");
client.print("Host: ");
client.println(hueHubIP);
client.print("Content-Length: ");
client.println(command.length());
client.println("Content-Type: text/plain;charset=UTF-8");
client.println(); // blank line before body
client.println(command); // Hue command

Adding a Motion Sensor

Finally, I wired a simple HC-SR501 motion sensor to digital I/O pin 2. When motion is detected, a series of states are pushed to the bridge for 2 bulbs to create a slow, dynamic animation. When the motion sensor deactivates, a single off command is sent to both. Ideally, they would be reverted to the state they were in before motion was detected, but the logic isn’t that smart – we’re just going to turn them on and off.

Limitations

Although admittedly unoptimized code, it takes almost a second for the network interface of the Arduino to send a single command request. I tested the same command from a Mac, using the same Ethernet connection, and it was capable of ten to twenty times that speed (here’s the AppleScript in case you’d like to test). Consequently, any kind of fast animation (I was attempting to create a flickering candle effect) just isn’t possible from an Arduino. This shouldn’t be a problem for most projects, just for high speed light animations, but it’s good to be aware of the limitation.

It’s also difficult to fully parse any JSON response you get back from the bridge; there just isn’t enough RAM on the Arduino to store all the raw data. For this reason, you might want to mostly limit yourself to sending.

Hack the Hue

Now that you’re armed with the knowledge of how to control Hue completely independently, it opens up a world of Hue home automation hacks. The real question is: what will you make?

  1. Seth
    May 3, 2016 at 5:22 am

    Hello, this was really helpful. FYI, in the getHue function where client.findUntil("\"hue\":", "\0"); and all the other property parsing happens, the \0 has to be in single quotes instead of double quotes since it's a character. We were getting bad data back until this was discovered. Thanks!

  2. Joren Broekema
    April 19, 2016 at 12:49 pm

    Me and a couple of others have tried to make something similar to this work but ran into the issue where Philips recently changed their Hue security protocol to https and the authorization is an issue for the limited capacity of Arduinos and other microcontrollers (raspberry might be able to handle it).

    To make sure it wasn't me, I adapted your tutorial fully and got the same issue.

    Maybe you should put this in the Limitation section ;)

    • Mitchell Lombard
      October 16, 2016 at 1:39 pm

      You only need to authorise once and this authorisation doesn't have to come from the Arduino. You can use any REST client to submit the authorisation request via HTTPS and the bridge will then accept requests to the authorised url via HTTP from the Arduino or any other device.

  3. John Canty
    November 22, 2015 at 7:16 pm

    Hello,

    I was working with your sketch and I thank you profoundly for coming up with this idea. I might not have thought of it unless I came across your article. This will make my home automation go significantly easier knowing what I have read in your article.

    That being said, I come from a networking background and noticed that this sketch will flood a network with constant communication to the Hue Bridge. I came up with the best way to mitigate that for anyone who is interested. In my example I am working with Hue LUX lights so the command is slightly different please excuse the changes.

    I modified the conditions upon which setHue are called. First before updating activated, a copy of activated is stored into a variable called previousState. Then the program updates activated. From there the program evaluates previousState and activated to verify something has changed. If that condition is true, it calls setHue and updates the two lamps.

    /*
    Talking to Hue from an Arduino
    By James Bruce (MakeUseOf.com)
    Adapted from code by Gilson Oguime. https://github.com/oguime/Hue_W5100_HT6P20B/blob/master/Hue_W5100_HT6P20B.ino
    */
    #include
    #include
    // Hue constants
    const char hueHubIP[] = "10.10.11.2"; // Hue hub IP
    const char hueUsername[] = "user"; // Hue username
    const int hueHubPort = 80;
    // PIR
    //I haven't pulled a pin to ground so for testing I need to force the issue with two jumper wires. This can be changed
    //back to the original one pin once I have a pin pulled to ground.
    int benchOn = 2;
    int benchOff = 1;
    //Create two states. The one we are changing and the one we once changed.
    boolean activated;
    boolean previousState = false;
    // Hue variables
    boolean hueOn; // on/off
    int hueBri; // brightness value
    long hueHue; // hue value
    String hueCmd; // Hue command
    unsigned long buffer=0; //buffer for received data storage
    unsigned long addr;
    // Ethernet
    byte mac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // W5100 MAC address
    IPAddress ip(10,10,11,3); // Arduino IP
    EthernetClient client;
    /*
    Setup
    */
    void setup()
    {
    Serial.begin(9600);
    Ethernet.begin(mac,ip);
    pinMode(benchOn,INPUT);
    pinMode(benchOff,INPUT);
    delay(2000);
    Serial.println("Ready.");
    }

    void loop()
    {
    if(digitalRead(benchOn) == 1){
    Serial.println("activated");
    // A series of four sample commands, which colour fades two lights between red and pink. Read up on the Hue API
    // documentation for more details on the exact commands to be used, but note that quote marks must be escaped.
    // String command = "{\"on\": true,\"hue\": 50100,\"sat\":255,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}";
    String command = "{\"on\": true,\"bri\":255,\"transitiontime\":"+String(random(15,25))+"}";
    previousState = activated; //save a copy of the old state before we udpate to the new one.
    activated = true;
    if(previousState != activated){ //verify that a change has occured otherwise no need to update the bridge
    setHue(4,command);
    setHue(5,command);
    }
    }
    if(digitalRead(benchOff) == 1 && activated == true){
    Serial.println("deactivated");
    //was activated, so send a single off command
    String command = "{\"on\": false}";
    previousState = activated; //save a copy of the old state before we udpate to the new one.
    activated = false;
    if(previousState != activated){ //verify that a change has occured otherwise no need to update the bridge
    setHue(4,command);
    setHue(5,command);
    }
    }
    }
    /* setHue() is our main command function, which needs to be passed a light number and a
    * properly formatted command string in JSON format (basically a Javascript style array of variables
    * and values. It then makes a simple HTTP PUT request to the Bridge at the IP specified at the start.
    */
    boolean setHue(int lightNum,String command)
    {
    if (client.connect(hueHubIP, hueHubPort))
    {
    while (client.connected())
    {
    client.print("PUT /api/");
    client.print(hueUsername);
    client.print("/lights/");
    client.print(lightNum); // hueLight zero based, add 1
    client.println("/state HTTP/1.1");
    client.println("keep-alive");
    client.print("Host: ");
    client.println(hueHubIP);
    client.print("Content-Length: ");
    client.println(command.length());
    client.println("Content-Type: text/plain;charset=UTF-8");
    client.println(); // blank line before body
    client.println(command); // Hue command
    }
    client.stop();
    return true; // command executed
    }
    else
    return false; // command failed
    }
    /* A helper function in case your logic depends on the current state of the light.
    * This sets a number of global variables which you can check to find out if a light is currently on or not
    * and the hue etc. Not needed just to send out commands
    */
    boolean getHue(int lightNum)
    {
    if (client.connect(hueHubIP, hueHubPort))
    {
    client.print("GET /api/");
    client.print(hueUsername);
    client.print("/lights/");
    client.print(lightNum);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(hueHubIP);
    client.println("Content-type: application/json");
    client.println("keep-alive");
    client.println();
    while (client.connected())
    {
    if (client.available())
    {
    client.findUntil("\"on\":", "");
    hueOn = (client.readStringUntil(',') == "true"); // if light is on, set variable to true
    client.findUntil("\"bri\":", "");
    hueBri = client.readStringUntil(',').toInt(); // set variable to brightness value
    client.findUntil("\"hue\":", "");
    hueHue = client.readStringUntil(',').toInt(); // set variable to hue value
    break; // not capturing other light attributes yet
    }
    }
    client.stop();
    return true; // captured on,bri,hue
    }
    else
    return false; // error reading on,bri,hue
    }

  4. Patrick
    November 17, 2015 at 11:52 pm

    I believe the PUT URL to change light color is incorrect, resulting in an "unauthorized user" error.

    INCORRECT: /api/newdevelopers/lights/1/state
    CORRECT: /api/newdeveloper/lights/1/state

  5. Yuval Levental
    May 31, 2015 at 11:33 am

    My name is Yuval, I go to school at ESIEE Paris, and I have adapted this tutorial for a Master's degree project where we create a smart home network. Thank you so much for providing this information, hope you see this comment!

    • James Bruce
      May 31, 2015 at 12:35 pm

      Glad it could be of use to you, Yuval!

    • Yuval Levental
      June 1, 2015 at 12:27 pm

      Thanks. I have a couple questions though: I would like to create a program where I can personally change the value of the brightness while the program is running. How do I do this? Do you know of any good GUI software for Arduino?

Leave a Reply

Your email address will not be published. Required fields are marked *