Two lights, one toggle to rule them all
How to ensure two lights are switched on and off together even if one is on/off and the the other is off/on
I was recently in Aldi (or Lidl) and, in their discounted section, they had some ZigBee controllable bulbs. I thought to myself “I’ll have one of those, I’ll think of somewhere to use it when I get home”. And sure enough, I decided to use it on the landing. I already had one in the hall at the bottom of the stairs so having one at the top seemed to make sense, but…!
The hall light was controlled by a button on my NSPanel (you can see more in my earlier post below). But basically, the NSPanel is on my wall in the hall and by pressing the button it toggles the hall light - if it’s on it goes off, and if it’s off (you get the idea). All I need to do, I thought, is add the new landing light to the logic for the button and it would also come on/off with the hall light.
The problem
Adding the new light to the NSPanel button was simplicity itself - just copy and paste the 4 lines of yaml code for the hall light toggle and replace the hall light id with the new landing light id. Here’s the code (the last 4 lines are the ones to duplicate):
- platform: gpio
name: $device_name Right Button
pin:
number: 27
inverted: true
on_click:
then:
- homeassistant.service:
service: light.toggle
data:
entity_id: light.HallLight_on_off
Remember the button on the NSPanel is exactly that, a button, not a switch. It has no on and off, hence the need to use a toggle.
So, quickly coded, uploaded and tested. Perfect, press the button, both lights come on, press again, both lights go out. All use cases tested. Nothing can go wrong now can it! Oh yes it can. I’d tested it during the day.
I have an automation that switches the hall light on at dusk and switches it off later when we’ve probably gone to bed. I’d forgotten this and, when I went to bed, I pressed the button so the landing light would also come on. But as the controls behind the button for the lights are toggles, the landing light came on as expected but of course the hall light switched off! Doh, I now had “traffic lights”. Press the button, one goes off, the other comes on. Press again and the opposite happens. My logic only works as I want when both lights are on or off. Back to the drawing board!
One button to rule the lights
There is probably more than one way to solve this. In the code behind the NSPanel, I could perhaps inspect the current state of each light and then, when the button is pressed, only toggle one light if the lights are in opposite off/on states. However, given my experience with coding the NSPanel backend, I know this would be awkward and hard to test (every change to the NSPanel yaml code requires uploading - a time consuming ballache!). I quickly decided against this approach.
An easier approach is to do the logic in an automation - in my case I did this in Node Red. My full solution is as follows:
I no longer control the lights directly from the NSPanel code. I’ve introduced a boolean helper unimaginatively called input_boolean.hall_landing_lights. My NSPanel code now simply toggles this helper:
- homeassistant.service:
service: input_boolean.toggle
data:
entity_id: input_boolean.hall_landing_lights
I could then in theory simply switch both bulbs on and off in Node Red whenever the helper toggles. However, the bulbs can be adjusted in Home Assistant for both brightness and colour temperature but this is not available in Node Red. Thus it’s possible a bulb has its brightness and/or colour temperature changed which would mean next time it’s switched on it would take up the new settings. I want the two bulbs to look the same every time they’re toggled on from the NSPanel. The easiest way to ensure consistent settings for multiple bulbs is to use a Scene. So I created two scenes - one for on and one for off (strictly speaking, an off scene isn’t needed as I could switch off both bulbs individually, but this way keeps everything consistent). So I now have two scenes, again unimaginatively called Hall landing lights on and Hall landing lights off.
And in Node Red, I simply activate the appropriate scene whenever the state of the boolean helper changes:
Finally, it’s possible that the boolean helper input_boolean.hall_landing_lights is true when both lights are off (they might be manually switched off from Home Assistant for example). This would mean pressing the button on the NSPanel would toggle input_boolean.hall_landing_lights to off and the lights don’t come on as expected - not a huge issue, press again and the lights will come on, but unclean! I therefore added a Home Assistant automation that checks on the state of both bulbs and, if they’re both off, it sets input_boolean.hall_landing_lights to false, thereby ensuring the NSPanel button will always switch on the lights when pressed with both off:
Of course I could make things more complex, worrying about what to do if only one light is on and whether to do something different depending on if it’s the hall or landing light on. But this solution deals with most situations satisfactorily while being simple and, by using scenes, I can change the look (brightness or colour temperature) of the lights without worrying about any of the logic.
I now have one button to rule the lights!