Control Philips Hue Color (RGB) Lights With Python
Sun, Mar 20, 2022 in post General Tips and Tricks python philips hue colorspace api
I got tired of the fact, that Philips Hue application does not seem to have any easy way to set multiple lights to different colors (and possibly brightnesses) at once. Thankfully, there is a great "REST API" to query light and set status! Read on how to query your lights, set them, and do RBG to Philips Hue XY (or X, Y) colorspace conversion with Python!
Connecting and configuring your Philips Hue for API access
This is a prerequisite step. Find out your Hue Brige's IP and create a user (simple method of authentication). It's all covered in Get started.
Write down your IP and the username, and proceed to activate your user and test it according to instructions. Once you are done, you should be able to also open the lights list in your browser and see a lot of info:
https://
Listing Your Connected Philips Hue Lights with Python
Alright, with the prerequisites done, let's do a simple test with Python, and query that same address parse the returned JSON, and pretty print it. You'll need Python 3.10+ for this:
import urllib.request
import ssl, json, pprint
context = ssl._create_unverified_context()
def get_json(url):
"""Do a HTTP GET request and return response parsed as JSON."""
print(url)
req = urllib.request.Request(url=url, method='GET')
f = urllib.request.urlopen(req, context=context)
print(f.status, f.reason)
return json.loads(f.read())
# Replace these with your config
user = 'yourverylongusernamestring'
ip = '192.168.1.123'
data = get_json(f'https://{ip}/api/{user}/lights')
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(data)
for k in data: print(k, data[k]['name'])
Note the context = ...
line where we create an
unverified context — we've not that worried
about the security in this one.
Turning Philips Hue Light On And Off With Python
Turning a light on or off is simply a matter of
sending a PUT request to /api/{user}/lights/{id}
with JSON request of {"on":true}
for turning the
light on, and {"on":false}
for turning it off:
# Imports and user, ip set as in above example
def put(url, content):
"""Do a HTTP PUT request with given content as payload."""
print(url, content)
req = urllib.request.Request(url=url,
data=content.encode('UTF-8'), method='PUT')
f = urllib.request.urlopen(req, context=context)
print(f.status, f.reason)
# Turn ON light 7
light = 7
put(f'https://{ip}/api/{user}/lights/{light}/state', '{"on":true}')
Getting and Setting Philips Hue to Given X/Y and Brightness
If you have color capable Hue lights, you can get their current color in X/Y format (based on the CIY 1931 color space, I think), and set them in a similar fashion.
# Get light 4 x, y, and brightness values
light = 4
data = get_json(f'https://{ip}/api/{user}/lights/{light}')
state = data['state']
print(state['xy'][0], state['xy'][1], state['bri'])
# Set light 4 to a greenish hue with 50 % brightness
light, x, y, b = 4, 0.4, 0.6, 127
put(f'https://{ip}/api/{user}/lights/{light}/state',
'{"on":true,"xy":[%.4f,%.4f],"bri":%d}' % (x,y,b))
Note that the /api/{user}/lights/{light}
will give more info
than just the state, so we'll fetch the state
section and
then xy
items and bri
under that.
From Red, Green, Blue (RGB) Values to Philips Hue XY or "X, Y" format
This information took a bit googling, and was the reason I decided to write this article. The XY conversion is documented in Hue Developer pages (requires registration):
https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/
With Python, the formulas can be expressed in a pretty short form. Here's a function that takes RGB values and returns X and Y coordinates and brightness value:
def rgb2xyb(r,g,b):
r = ((r+0.055)/1.055)**2.4 if r > 0.04045 else r/12.92
g = ((g+0.055)/1.055)**2.4 if g > 0.04045 else g/12.92
b = ((b+0.055)/1.055)**2.4 if b > 0.04045 else b/12.92
X = r * 0.4124 + g * 0.3576 + b * 0.1805
Y = r * 0.2126 + g * 0.7152 + b * 0.0722
Z = r * 0.0193 + g * 0.1192 + b * 0.9505
return X / (X + Y + Z), Y / (X + Y + Z), int(Y*254)
Note: I have converted the brightness value to integer
in the range 0..254 as that is what the API expects the "bri"
value to be.
Using this is pretty easy, let's set the light 4 to light pink:
light = 4
x,y,b = rgb2xyb(1.0, 0.6, 0.8)
put(f'https://{ip}/api/{user}/lights/{light}/state',
'{"on":true,"xy":[%.4f,%.4f],"bri":%d}' % (x,y,b))
Wrapping it all together
I made a simple Python tool hue.py which includes all the above routines and some more. Here are a couple examples:
- List lights:
python3 hue.py list
- Turn light 7 on:
python3 hue.py on 7
- Turn lights 7 and 13 off:
python3 hue.py off 7 13
- Set light 4 to green:
python3 hue.py rgb 0 1 0 4
- Set light 4 to warm white:
python3 hue.py ctb 400 200 4
- Dump X/Y and brightness for lights 5-7 to
file.txt
with:python3 hue.py getxyb 5 6 7 > file.txt
- Set lights from
file.txt
usingpython3 hue.py setxyb file.txt
Enjoy! Now if someone has a nifty way of passing a keyword from Alexa to a web service, let me know. I'm all set to use that keyword to fetch a setting file and apply it!