• Blog
  • Papers
  • Datasets
  • Running Philips Hue Lights Locally

    04 April, 2017 | Home Automation

    One of my biggest bug-bears about the so-called Internet of Things is the Internet bit. I love the idea of having heating and lights that are intelligent and act correctly based on my actions inside my own home, but just that - inside my own home. With most commercially successful IoT technologies, you are not controlling your home, a remote server owned by a company is controlling your home and you are politely asking it to do things. There are various drawbacks to this...

    • The company could turn evil - whatever your definition of 'evil' is.
    • The manufacturer could discontinue the IoT product and your house stops working - This has actually happened.
    • Your house could lose internet connection - I'm sure this has happened to you at some point

    Even from a data protection point of view, allowing a remote company access to your living habits when you really don't need to is probably a bad idea. A more sensible model for sustainability and security is a model whereby you talk directly to your house, rather than go through Philips, or Google, or even your gas company.

    I love the Philips Hue system. The bulbs themselves are expensive at around £15 for a plain white bulb, but the benefits are worth paying for. Firstly, you get a light that can be remote-controlled via the Zigbee wireless home automation protocol. Secondly, the bulbs are 9W super-bright LED bulbs, which are brighter and use less energy than normal energy-saving bulbs. Thirdly, you can query these bulbs and get their current status. Want to just check if you left the light in the hallway on without getting out of bed? Now you can.

    The standard app is pretty good from a technical point of view. If you're on the same local network as a Hue bridge (the transmitter that does all the talking to the lights) then it talks locally and doesn't go out onto the internet. But if it can't find a bridge on the network it's on - say you're on 3G or at someone else's house - then it contacts Philips. Your Hue bridge is periodically contacting Philips' mothership, updating it with your home IP address, so your app can look it up and connect to it. Philips basically acts as a sort of directory enquiries for Hue users. Thing is, if you have a static IP address like I do, you can't just tell the app what it is, it has to get your IP address from Philips, making them a single point of failure. Additionally, the Android version wants to know your location. The only real reason it would need this is to turn your lights on when you're near home, but surely a better way of doing this is to turn them on once you connect to your home wifi or something. GPS is a lousy way to do this, and I have an automatic distrust of any app that wants to access the GPS of my phone unless it's giving me directions to someplace.

    I have various uses for the Hue system. The light switch in my garage is at the front of the building, but I usually enter through the back door from the garden, meaning I have to fumble my way along the entire length of the garage to find the light switch. To fix this, I have a motion sensor on the ceiling which turns the light on when it detects movement in the garage, so it doesn't matter which door I come in through. The light in my hallway is set to come on at sundown. Ideal in the winter months, and has a lovely side-effect of never coming on right on the hour or at the same time every day, so anyone watching the house won't realise that it's on a timer. Finally, staying with security, I keep a log of every time the lights are turned on and off, and have written a script called 'replay' which repeats the light patterns of the previous week. This is great if I go away on holiday for a week, as the lights going on and off at sensible times makes it look as if someone is home. None of these three scenarios actually require the Hue system to have access to the internet (apart from once a day to download the sundown times, but that hardly warrants continual 'phoning home'.)

    So, as a good rule of thumb, if a system doesn't need internet access, don't give it internet access.

    My Hue bridge has a static IP address on the network. It's 192.168.0.70. This is assigned by the router via DHCP. I've also set up the router not to allow any outside access from this IP address. It's easy to see if a Hue bridge lacks internet access as one of its blue LEDs will be blinking. Once the Hue is set up and talking to the lights, it can be easily controlled through one of two methods.

    Python

    There is a lovely library for Python called phue. You can install it through pip or easy_install, and it does a great job of wrapping the Hue API into Python objects. The 'Hello World' program looks a bit like this...

    >>> from phue import Bridge
    >>> b = Bridge("192.168.0.70")
    >>> b.lights
    [<phue.Light object "Office ceiling light" at 0xb67a87b0L>,
    <phue.Light object "Spare coloured bulb 1" at 0xb67a8ef0L>,
    <phue.Light object "Bedroom light" at 0xb67a8830L>,
    <phue.Light object "Bedroom Corridor light" at 0xb67a8f30L>,
    <phue.Light object "Dining Room light" at 0xb67a8f10L>,
    <phue.Light object "Lounge light" at 0xb67a8f70L>,
    <phue.Light object "Garage light" at 0xb67a8f50L>,
    <phue.Light object "Garden light" at 0xb67a8fb0L>,
    <phue.Light object "Kitchen spotlight 1" at 0xb67a8f90L>,
    <phue.Light object "Kitchen spotlight 2" at 0xb6cc6570L>,
    <phue.Light object "Kitchen spotlight 3" at 0xb6cc6630L>,
    <phue.Light object "Kitchen spotlight 4" at 0xb67a8630L>,
    <phue.Light object "Landing light" at 0xb67a8730L>,
    <phue.Light object "Hallway light" at 0xb67a8770L>,
    <phue.Light object "Bathroom spotlight 1" at 0xb67a8790L>,
    <phue.Light object "Bathroom spotlight 2" at 0xb67a87d0L>,
    <phue.Light object "Spare coloured bulb 2" at 0xb67a8750L>]

    This simply connects to the bridge at the IP address given, and lists all the lights registered on your system.

    >>> b.lights[0]
    <phue.Light object "Office ceiling light" at 0xb67a87b0L>
    >>> b.lights[0].on
    True

    This, on my system, will check the status of the office light.

    >>> b.lights[0].on = False

    And this turns it off. This is all you need to be able to script turning lights on and off, and checking their status.

    The REST API

    The phue library basically just wraps the Hue's API, which is REST-based, and sends and receives data in JSON format. The bridge actually has a built-in debugger that you can use to test your REST calls, and this can be accessed at...

    http://192.168.0.70/debug/clip.html

    Obviously, you need to replace 192.168.0.70 with the local IP address of your bridge.

    Before you can do anything, you need an API key. This is simple to generate. Make up a user name, ie 'ash'. Then you need to MD5-encrypt it. If you have a Linux machine handy, you can simply type

    echo 'ash' | md5sum

    Which will get the result 2c7282bbca9abc9d446e02b8adee9563 (obviously this will be different if you put something other than 'ash'). Then, in the debug page, make sure the URL is set to just '/api/' (no quotes), and paste the following into the message body:

    {"username": "2c7282bbca9abc9d446e02b8adee9563", "devicetype": "Testing"}

    Again, replace the hash with the hash of your own user name, and the devicetype with the name of your 'app'. If you now click the POST button, the site will almost certainly reply that the button has not been pressed. This is a little bit of physical security on the Hue's part. Press the button on the top of the bridge and send the POST request again. You should be given a piece of JSON saying something like...

    {"success":{"username":"2c7282bbca9abc9d446e02b8adee9563"}}

    Remember this username hash, you'll need it in all future calls to the Hue system.

    Now let's try turning some lights on and off. Paste the following into the URL box:

    /api/2c7282bbca9abc9d446e02b8adee956/lights

    Don't forget to replace the hash with your own. You should get something like the following returned...

    {
    "1": {
    "state": {
    "on": true,
    "bri": 254,
    "hue": 58969,
    "sat": 0,
    "effect": "none",
    "xy": [
    0.3804,
    0.3768
    ],
    "ct": 248,
    "alert": "none",
    "colormode": "hs",
    "reachable": true
    },
    "type": "Extended color light",
    "name": "Office ceiling light",
    "modelid": "LCT001",
    "manufacturername": "Philips",
    "swversion": "66013187"
    },
    ...

    This is a JSON object featuring all the lights in your system, the keys are the light IDs. You can call them individually with /api/[hash]/lights/[light id], and you can control the state by putting /api/[hash]/lights/[id]/state in the URL box, and the following JSON in the message body:

    {"on": true}

    and then clicking the PUT button. You can control other attributes too. The JSON below will set the brightness of the bulb to half-way:

    {"bri": 127, "on": true}

    Setting the time

    The Hue bridge gets its time from a remote time server. If you block its internet connection it cannot do this. However, it is possible to set the time via the API. Try calling /api/[hash]/config and you should see something like the following:

    {
    "name": "Ash's Lights",
    "zigbeechannel": 20,
    "dhcp": true,
    "ipaddress": "192.168.0.70",
    "netmask": "255.255.255.0",
    "gateway": "192.168.0.1",
    "proxyaddress": "none",
    "proxyport": 0,
    "UTC": "2016-12-14T23:23:28",
    "localtime": "2016-12-14T23:23:28",
    "timezone": "Europe/London",
    "modelid": "BSB001",
    ...

    This is basically the entire Hue bridge configuration, which can be set using PUT. So, leaving /api/[hash]/config in the URL and pasting...

    {"UTC": "2016-12-14T16:00:00"} (NB replace with the actual date!)

    into the message body will set the Hue's internal clock.

    Adding new bulbs

    You can also add new Hue bulbs to your system, using only the REST API. If the bulb you want to add is brand new out of the box, in the debug page, paste the following into the URL:

    /api/[hash]/lights

    and, ensuring nothing is in Message Body, and the new bulb is plugged in and within wireless range of the bridge, click POST. This will take a while while it searches for your new light. You can GET /api/[hash]/lights/new to check progress, but the light will pulse when the system detects it.

    If this fails, or the bulb has previously been connected to a different Hue system, no problem, just add an extra piece of JSON in the Message Body before pressing POST...

    {"deviceid": "light_id"}

    ...where light_id is the serial number printed on the side of the Hue bulb.

    If you're a programmer, this should give you everything you need to make your Hue lights do whatever you want, based on scripts. I myself have a Raspberry Pi mini-computer sat on my desk controlling the lights. It's permanently turned on but Raspberry Pis use very little power.

    Adding new sensors

    Philips also make some nice little dimmer switches. All methods of sending input into the Hue system are called 'sensors' and these switches are no exception. The switches usually come in packs with a bulb, so you need to decouple the switch from the bulb by holding the 'off' button close to the bulb until it flashes. Once you've done this you can put the switch into 'pair' mode by using a paperclip to press and hold the setup button on the back until it starts blinking orange. Once it's in pair mode, do exactly as you did with a light, only with 'sensors' in the URL. Send a POST to...

    /api/[hash]/sensors

    ...and wait. The orange light will stop blinking once pairing is complete, but the bridge will continue searching for more for a while. Check the status by sending a GET request to

    /api/[hash]/sensors/new

    Adding rules

    If you want to make the switches actually do anything, you need to add rules. You can get a list of the Hue's rules by sending a GET to

    /api/[hash]/rules

    You can add a rule by POSTing to this address. Here's a sample data structure that tells light group 1 to turn on if sensor 2's 'on' button is pressed...

    {
    "name": "Dimmer 2.1 ",
    "conditions": [
    {
    "address": "/sensors/2/state/buttonevent",
    "operator": "eq",
    "value": "1000"
    },
    {
    "address": "/sensors/2/state/lastupdated",
    "operator": "dx"
    }
    ],
    "actions": [
    {
    "address": "/groups/1/action",
    "method": "PUT",
    "body": {
    "on": true
    }
    }
    ]
    }

    Replace the value 1000 with 4000 for the off switch, and true with false for light off. That's your basic functionality - on switch turns light on, off switch turns it off. There are more complex things you can do, with the dimmer buttons and with combinations of pressing, releasing and holding buttons.

    I really like the concept of computer-controllable home devices, but connecting everything to the internet is just asking for trouble. Thankfully the Hue system works just fine with no internet access, and now I have an army of Raspberry Pis inside my house doing all the house management instead of having to do it myself via a phone and an internet connection!