Here it is! My Python client for the Philips Hue system is done.
The Short:
It's available on Github.
Sample Usage:
from hue import Hue
h = Hue() # Initialize the class
h.station_ip = "192.168.1.222" # your base station IP
h.get_state() # Authenticate, bootstrap your lighting system
# The first time, you have a minute between calling get_state() and pushing
# the button on your base station to authenticate your machine. It should
# Log and tell you if that is going to happen or not.
l = h.lights.get('l3') # get bulb #3
l.bri(0) # Dimmest
l.bri(255) # Brightest
l.rgb(120, 120, 0) # [0-255 rgb values]
l.rgb("#9af703") # Hex string
l.on()
l.off()
l.toggle()
l.alert() # short alert
l.alert("lselect") # long alert
l.setState({"bri": 220, "alert": "select"}) # Complex send
Philips Hue is a red/green/blue LED bulb and base-station system. The light quality is nice but the bulbs are pricey ($60 per after the base station, which is 3 bulbs and base for $200). You can also only buy them from apple right now, which is totally crazy because they have an android app too. I assume this is just a temporary exclusivity deal and they'll have wider availability soon.
As soon as I got them I wanted to hack them, the base station is ethernet on one end (between apps, the philips website) and zigbee on the other (to talk to the lights)
The API to the base station is actually quite nice, very RESTful, and much easier than the Wemo API. Straight HTTP over port 80 between the apps and device, but disappointingly on one hand (security), nice on the other (reverse engineering) also HTTP over port 80 to phone-home to two different Philips sites.
A typical request to the Philips Hue base station API looks like this:
GET http://<base station ip>/api/<client id string>
This request returns the entire state of the system. Mine is
{
"config": {
"UTC": "2012-11-10T22:31:57",
"dhcp": true,
"gateway": "192.168.1.1",
"ipaddress": "192.168.1.130",
"linkbutton": false,
"mac": "<mac is here>",
"name": "Philips hue",
"netmask": "255.255.255.0",
"portalservices": true,
"proxyaddress": "",
"proxyport": 0,
"swupdate": {
"notify": false,
"text": "",
"updatestate": 0,
"url": ""
},
"swversion": "01003542",
"whitelist": {
"22a828f1898a4257c3f181e75324f557": {
"create date": "2012-11-10T19:23:15",
"last use date": "2012-11-10T22:31:57",
"name": "python-hue"
},
... # more client info
}
},
"groups": {},
"lights": {
"1": {
"modelid": "LCT001",
"name": "Hue Lamp 1",
"pointsymbol": {
"1": "none",
"2": "none",
"3": "none",
"4": "none",
"5": "none",
"6": "none",
"7": "none",
"8": "none"
},
"state": {
"alert": "none",
"bri": 20,
"colormode": "ct",
"ct": 369,
"effect": "none",
"hue": 14922,
"on": true,
"reachable": true,
"sat": 144,
"xy": [
0.4595,
0.4105
]
},
"swversion": "65003148",
"type": "Extended color light"
},
"2": {
"modelid": "LCT001",
"name": "Hue Lamp 2",
"pointsymbol": {
"1": "none",
"2": "none",
"3": "none",
"4": "none",
"5": "none",
"6": "none",
"7": "none",
"8": "none"
},
"state": {
"alert": "none",
"bri": 20,
"colormode": "ct",
"ct": 369,
"effect": "none",
"hue": 14922,
"on": true,
"reachable": true,
"sat": 144,
"xy": [
0.4595,
0.4105
]
},
"swversion": "65003148",
"type": "Extended color light"
},
"3": {
"modelid": "LCT001",
"name": "Hue Lamp 3",
"pointsymbol": {
"1": "none",
"2": "none",
"3": "none",
"4": "none",
"5": "none",
"6": "none",
"7": "none",
"8": "none"
},
"state": {
"alert": "none",
"bri": 254,
"colormode": "xy",
"ct": 153,
"effect": "none",
"hue": 34073,
"on": true,
"reachable": true,
"sat": 254,
"xy": [
0.3136,
0.3297
]
},
"swversion": "65003148",
"type": "Extended color light"
}
},
"schedules": {}
}
There are some interesting things in there, not the least of which being that it has a "schedules" and "alert" function which is not available to the app.
You won't get this request the first time just by shooting a request to your base with cURL, you first have to authenticate.
The process looks like this:
Example:
curl -XPOST http://192.168.1.130/api/ -d '{"devicetype": "1337 client", "username": "22a828f1898a4257c3f181e753241337" }'
[{"error":{"type":101,"address":"/","description":"link button not pressed"}}]
# Go press the button!
curl -XPOST http://192.168.1.130/api/ -d '{"devicetype": "1337 client", "username": "22a828f1898a4257c3f181e753241337" }'
[{"success":{"username":"22a828f1898a4257c3f181e753241337"}}]
Once you've authenticated, your device ID is in the URI of every request. It's an interesting decision on the part of their API designers, but it works just fine once you realize that's what's going on.
Examples:
curl http://192.168.1.130/api/22a828f1898a4257c3f181e753241337/lights/3
{
"modelid": "LCT001",
"name": "Hue Lamp 3",
"pointsymbol": {
"1": "none",
"2": "none",
"3": "none",
"4": "none",
"5": "none",
"6": "none",
"7": "none",
"8": "none"
},
"state": {
"alert": "none",
"bri": 254,
"colormode": "xy",
"ct": 153,
"effect": "none",
"hue": 34073,
"on": true,
"reachable": true,
"sat": 254,
"xy": [
0.3136,
0.3297
]
},
"swversion": "65003148",
"type": "Extended color light"
}
curl -XPUT http://192.168.1.130/api/22a828f1898a4257c3f181e753241337/lights/3/state -d '{"bri": 0}'
[{"success":{"/lights/3/state/bri":0}}]
curl -XPUT http://192.168.1.130/api/22a828f1898a4257c3f181e753241337/lights/3/state -d '{"alert":"select"}'
[{"success":{"/lights/3/state/alert":"select"}}]
That's it!
Let me know if you're using it, or if you'd like to see more functionality out of the client, File issues on Github, or let me know what else you'd like to see me write about.
10th November 2012
I won't ever give out your email address. I don't publish comments but if you'd like to write to me then you could use this form.
I'm Issac. I live in Oakland. I make things for fun and money. I use electronics and computers and software. I manage teams and projects top to bottom. I've worked as a consultant, software engineer, hardware designer, artist, technology director and team lead. I do occasional fabrication in wood and plastic and metal. I run a boutique interactive agency with my brother Kasey and a roving cast of experts at Kelly Creative Tech. I was the Director of Technology for Nonchalance during the The Latitude Society project. I was the Lead Web Developer and then Technical Marketing Engineer at Nebula, which made an OpenStack Appliance. I've been building things on the web and in person since leaving Ohio State University's Electrical and Computer engineering program in 2007. Lots of other really dorky things happened to me before that, like dropping out of high school to go to university, getting an Eagle Scout award, and getting 6th in a state-wide algebra competition. I have an affinity for hopscotch.