I made the decision that we would use consumer tech in our Smart Home (see this post) and the lighting system we settled on was Philips Hue. I will explain why we went for Philips Hue over other possibilities in another post at some point. However, when using a system like Philips Hue (or any of the others with their own controllers) there is a choice between performing the automation natively in the system controller, doing it within a central control system (like Home Assistant) or some form of hybrid.
In my experience, there is always a slight (but noticeable) delay if trying to perform all the automations within the central controller. I know that some of this comes from the particular platforms that are being integrated, e.g. the Philips Hue integration polls the Hue Bridge rather than accepting push notifications for motion sensors, etc. However, there is a second issue; namely, what happens if my central controller is offline for some reason? If my Home Assistant machine fails (more on my resilient setup in another post) then my lights won't work. So, we decided to keep as much of the lighting controlled by the Philips Hue Bridge as possible so most of our lighting control would work even if we lost the Home Assistant machine, but how to integrate Circadian Lighting (i.e. lighting that changes colour and brightness based on the time of day) with motion sensors and native Philips Hue automation.
Home Assistant Flux Switch
There are numerous ways to achieve Circadian Lighting within Home Assistant, but the easiest one I've found to use is the Flux Switch. To apply the Flux Switch to a set of lights, you need to add code to the configuration.yaml file (if you don't have it, install Visual Studio Code within Home Assistant to make this easy). The following is an example, but you can visit the Integrations page on the Home Assistant website for more details:
The above configuration will update the colour and brightness of three lights every 60 seconds and have it transition slowly over 30 seconds. There are colour temperatures set in Kelvin for the day (start to sunset) and for the evening (sunset to stop). The colour will remain constant between the stop and start time the following day.
This is great, but if I want to use the Philips Hue motion sensor to automatically turn the lights on in my halls and staircases, we run into a problem. The Philips Hue motion sensor is set up to turn the lights on to one of two lighting scenes depending on the time of day. This doesn't give us the slowly changing light throughout the day though. Another way, is to just use the motion sensor to turn the lights on and off and not set a scene. Then we can rely on the Flux Switch to set the colour and brightness. Perfect! Only, not quite. When the Philips Hue turns the lights off after the configurable time, it first dims them to give a warning that they are going to turn off. So, if we get the motion sensor to just turn the lights on, they will come on at the previous colour and a dim brightness. We will then have to wait for the Flux Switch to trigger an update (every minute in the above example) and for it to then change the settings (30 seconds in the above example). So, with the above configuration, we could be waiting up to 90 seconds for the lights to arrive at the right colour and brightness.
I tried solving this using an automation on Home Assistant to monitor for the light turning on and triggering the Flux Switch straight away, but it could still take several seconds before the light is close to where it should be. I also needed to set up a separate Flux Switch for every room/area so that when the motion sensor turns a light on in the hall, it doesn't change the lights in another room/area that I might have set a specific scene for.
The solution...
Virtual Lights & Updating Scenes
The solution I use is to create a virtual light that I apply the flux switch to and I can refer to at any time of the day to get a reading of the current colour and brightness. I then use these values to update a set of Philips Hue scenes on a regular cadence throughout the day via a Node-RED automation. The advantage of doing this is that we can have other scenes set on the lights that won't be affected by the Circadian Lighting automation. Also, if Home Assistant stops working for some reason, the motion-activated lights all still work, they just won't update their colour and brightness throughout the day.
There are a few ways to create virtual lights in Home Assistant. Many people create an MQTT Light, but this needs an MQTT broker and I found that it wasn't as easy to control as a Virtual Light from the Virtual Components integration available via the Home Assistant Community Store (HACS). To get this, first follow the HACS Installation Guide, then browse the Integrations list and select Virtual Components.
Once installed (and you've restarted your Home Assistant server) you can create your virtual light in the configuration.yaml file as follows:
The settings here aren't important, other than enabling the colour temperature support, but the initial settings do no harm. Now you can create a Flux Switch for this light as above.
Now we need to setup a few scenes on the Philips Hue in order to use this new virtual light. Go to each area that is controlled by a motion sensor and create a new scene (it doesn't matter what colour or brightness you choose as we'll overwrite it later, we just need the scene to be created in the Philips Hue Bridge). I have called mine '<Area> Fluxer' so that I can recognise them easily in the Philips Hue app. Now assign these scenes to the appropriate motion sensors for the daytime scene in the Hue app.
Once you have done this, you now need to 'find' those scenes on your Bridge (they will have a random unique ID, which we need for the Node-RED automation). You can do this via the built-in API. Open a web browser and navigate to your Philips Hue IP address, e.g. https://192.168.0.100/debug/clip.html. Follow the instructions at the meethue website to get connected and register an API user.
Once you have successfully created an account, you can get a list of all the scenes on your Bridge, by entering /api/<username>/scenes in the URL field of the form and clicking 'GET'. Then scroll through the Command Response to find your scenes and take note of the IDs, which will look something like "SUNGq4GKlDwFLQK". Once you have a list of all the IDs, you can then access each of them to take note of the 'lightstates'. This can be done easily by adding the ID to the end of the URL field above, e.g. /api/<username>/scenes/SUNGq4GKlDwFLQK and clicking on the GET button. You should see something like the following returned:
"name": "Utility Room Fluxer",
"type": "GroupScene",
"group": "2",
"lights": [
"19",
"22"
],
"owner": "abc01234-dad2-47ba-9021-abcd12345678",
"recycle": false,
"locked": true,
"appdata": {
"version": 1,
"data": "bruZZ_r67"
},
"picture": "",
"lastupdated": "2021-04-12T16:43:50",
"version": 2,
"lightstates": {
"19": {
"on": true,
"bri": 254,
"ct": 313
},
"22": {
"on": true,
"bri": 254,
"ct": 313
}
}
}
From the above we can see that there are 2 bulbs in this scene with IDs 19 and 22. Now we can use Node-RED to update the 'lightstates' periodically to match our reference fluxer light, so that when the motion sensor turns the lights on to this scene it comes on straight to the right colour and brightness.
If you haven't already, install Node-RED through the Add-on Store under the Home Assistant Configuration settings. This will give you all the nodes you need, as it's not actually very complicated. You only need 3 nodes: poll state, function and http request as below:
In the poll state node set the entity ID to your virtual light (e.g. light.virtual_fluxer_reference_light) and set the update interval to a reasonable value (I update mine every 16 minutes). Next, configure the http request node so that the method is ' - set by msg.method - ' and the return is 'a parsed JSON object'. Leave the URL blank in this node as we will set it in the function node. You will want to enable the secure connection option as well, but it's not necessary if you're going to use HTTP rather than HTTPS.
The final part of this flow is to create the code for the function node. Again, this isn't complicated. We're going to create a new msg object to pass to the http request node with all the parameters that we need to update the Hue Bridge. Enter the following code in the function node:
newMsg.topic = "HTTP Request";
newMsg.headers = {};
newMsg.method = "PUT";
newMsg.url = "https://<bridge IP>/api/<username>/scenes/<scene ID>";
newMsg.headers["content-type"] = "application/json";
newMsg.payload = {"lightstates":
All we are doing in this code is reading the brightness and colour temperature (ct) from the reference light via the output from the poll state node and writing it into the body of a PUT request to the Philips Hue Bridge.
Now deploy this flow and you're done!
Multiple Scenes/Bridges
The above flow will update one scene on one Hue Bridge. However, I have multiple scenes sat across 4 Hue Bridges (yes every light in the house is Philips Hue so I have exceeded the capacity for a single Bridge). It's simple to expand this though, just replicate the function node so that you have one node per scene, then add a delay node after the function node of a few seconds and cascade them as below.
This is why we didn't set the URL in the http request node. The delay nodes make sure that we send one request at a time to the Hue Bridge and give it time to complete before sending the next one. It is easy to overwhelm the Bridge, so I suggest that you stick to adding a slight delay between each request, but it doesn't need to be 8 seconds as I have here.
One final note is that this solution doesn't update the colour or brightness of the bulbs while they're on. This isn't a problem for me though, as these bulbs are all in halls, etc., so they don't stay on for long as you tend to pass through the areas. If you want to update lights that stay on, you can monitor for a switch on event in Node-RED and turn an individual Flux Switch on for each area and even base it on how they were turned on, e.g. use Circadian Lighting if the lights turn on via motion sensor, but turn the flux switch off if you used a button/switch to turn the lights on.
Comments
Post a Comment