Automating Philips Hue with complex rules on a Raspberry Pi

Gareth Cronin
5 min readJun 6, 2022

--

I’ve been using Philips Hue lights and accessories for a few years. The system operates from a Hue bridge — a network attached unit that uses the Zigbee wireless protocol to communicate with the Hue bulbs, switches, and plugs. It’s very reliable and the app that communicates with the system works pretty well.

We have our Hue set up with the Alexa integration so we can issue commands in the living room like “Alexa: movie time” or “Alexa: reading time” and the lights are set how we like them. At 9.30pm I have a routine set up in the Hue app to turn off all the lights.

I decided to add a night light to our living area and bought a cheap and cheerful LED strip from a local importer. The strip is perfect: it has a self-adhesive backing and and 5 metres of LEDs (and costs $6.50!). I attached it to the inside of a false rafter in our living area so it creates a diffuse glow.

The LED strip

I bought a Hue Smart Plug so I can remote control it from the Hue system. I added a routine to turn on the night light at 9.30pm. There’s a hitch though…

If we are up late watching a movie, the dimmed lamp in the corner (“movie time”) turns off and the night light comes on. That’s annoying. I’d like the Hue to know that if I haven’t turned off the lights yet, there’s no point in turning the night light on.

I could of course pull out my phone or talk to Alexa, but wouldn’t it be cool if I could set up more complex rules than the basic Hue app provides for?

The Hue bridge API

I needed to find a way that I can write a small application in my favourite stack (Node.js) to process complex rules and send instructions to the Hue bridge.

I was prepared for something complicated involving OAuth authentication with the Hue cloud service, so I was blown away when my first bit of Googling revealed that the Hue bridge runs a RESTful API locally! Not only does it expose an HTTP endpoint to the local network, it actually runs a small web server with a testing client! That meant all I needed to do was hook up a rules engine of some sort to an HTTP client library, and leave it running on the Raspberry Pi I keep in a drawer. It’s the same Pi I use for my two “SaaS Prepper” applications: the Flickr back-up and Evernote back-up.

This tutorial and this reference are great for getting started. I gave the Hue a few prods with Postman to make sure it all worked as advertised (it did). It’s oddly satisfying to watch your lights come on and off and change brightness based on Postman calls. The authentication is a little peculiar. It’s necessary to make a POST call to the /api endpoint with a body including a “devicetype” field. The value of the field can be anything. This first call returns an error because it’s now waiting for a press of the big button on top of the Hue bridge. You press the button, then repeat the call to the API and it returns a “username”. The username is a 40-character mess of alphanumeric characters, and its used as part of the URL in all subsequent calls.

Node.js and the Hue API

The Node community is huge, and there’s usually a decent client library for any established API. Having a nicely written and tested client sure beats messing around with Superagent calls. Huejay has been around three years and is very active. It has a nice tidy set of conventions, all the features and covered, and it worked really well for me. It’s already promisified, so async/await style calls are a breeze.

Rules, rules, rules

Now it was time to look at what the Node community has in terms of simple rules engines. I could go nuts and start building a domain-specific language, but that would mean a lot of time might go by before I had a working solution. I settled on JSON-rules-engine, it has plenty of stars on Github, and it keeps things very simple: when conditions regarding facts are met, an event is generated.

The engine is started with a set of facts, which are represented by a key-value map of arbitrary strings, numbers, booleans etc. I call the Hue API and copy the state (on/off, brightness, hue, colour temperature etc) for each light and group of lights into the facts, along with a bunch of human-readable fields from a Luxon time object (hour, minute, day, minute, second etc). That means I can write rules that reason on the state of the lights and the time of day, day of week, and so on. Here’s an excerpt from the facts at my house:

Facts

Next come the conditions, which are boolean rules expressing relationships with facts. This is what my nightlight “on” looks like:

Conditions

The final part of the engine is events. I defined two types of events: “on” and “off”. I included all the tweakable light parameters like “brightness” as parameters of the “on” event.

Event

Putting it all together

I wrapped all of this in a simple Node.js application that kicks of a timer loop and runs the engine every one minute from start of the next minute (to avoid weird variations in rule execution depending on which second of the minute you happen to start it).

The solution

The resulting code is in this repo.

Next steps

I’m going to keep expanding the facts available to the rules. Next off the block will be adding local sunrise and sunset times, and a weather API, so I can really go to town! Hue also has motion sensors available — that could make things really interesting.

--

--

Gareth Cronin
Gareth Cronin

Written by Gareth Cronin

Technology leader in Auckland, New Zealand: start-up founder, father of two, maker of t-shirts and small software products

No responses yet