A followup to my Hue Dimmer setup


I was pretty satisfied with my setup, in general. But zigbee nuances makes it not work in some cases. And I’ll explain why and a solution.

ZigBee battery devices are generally not active unless they’re activated locally. For a dimmer, that’d mean pressing a button. As a consequence, when you press a button, it doesn’t know the state of the lights it manages. The new hue dimmer, version 2, this will give this effect:

  • Pressing the toggle button might fail on the first press. This is because the action you expected it to do was already done by other means. If the light was on, but then something (in my case, it was a scene switch also triggered by the dimmer) turns off the light, the dimmer still thinks that next time you press the button, it should turn the light off. It hasn’t gotten the state change when the scene switched it.
  • Pressing the hue button will switch between scene 0 and 1 in the same fashion. It will not know whether the lights are actually in line with scene 0, if you switched to scene 1 with the hue button last time, it will now switch to scene 0. In my case, I have set the scenes to «all off» and «all on» for a group of lights, so I might try to turn all on, but the button might recall the all off scene even if all lights are off.

I have so far only solved case 1. Case two should be pretty similar, but might have more edge cases. It’s also not as crucial to solve for me, personally, so I’ll do it later. I still wanted to present the general solution.

The bad news is, there’s no zigbee solution for it. Zigbee dimmers work they way they do, and you simply can’t let it get state changes, because that would make them always-on-devices and would make them eat batteries for breakfast.

The good news is, you can of course solve it in your home automation solution. Or, via a Zigbee2Mqtt external extensions, but I decided to do it in home assistant.

So, what happens when you press the toggle button? For my Stuedimmer, zigbee2mqt will send out an MQTT topic, zigbee2mqtt/Stuedimmer/action, with the payload on_press. It doesn’t matter if you try to turn it on or off, the Hue dimmer version two will always give the event on_press for the top button.

The solution I ended on, was:

  • Listen for zigbee2mqtt/Stuedimmer/action with on_press.
  • Set the desired_state to the opposite of the state it is.
  • Sleep for 500 milliseconds
  • Check if the state of the light has changed for the last second
  • If the state has changed, change the state to desired_state.

This should be fairly race-condition-resistant, but might fail on rapid button-presses. In normal use, I guess it shouldn’t be a problem. It will, in effect, mean that if the button press is pressed and it doesn’t cause a change in the light, home assistant will change it after 500 milliseconds! The 1 second limit is the limit to how close to each other you can do key presses and still have this work. It needs to be high enough that all latency (sotware, network etc) shouldn’t exceed it. I’m not totally sure I need the 500 millisecond delay, but it stays for now, as it potentially avoids some race conditions and probably is low enough not to be annoying.

If home assistant is down? Well, then you’ll have to live with having to press a second time if nothing happened.

The other downside is that you get this 500 millisecond delay. If you for some reason should stop having anything else than the toggle button change the state of the light, you might get into a state where this 500 millisecond delay is always there. This is because once this logic fired, and you wanted to turn it off, the button might actually think it has turned it on. Next time you press it, you will get the opposite, a 500 millisecond delay, the button thinks it turns it off, but home assistant turns it off. For me, I think this is better than having to press it two times when the state is wrong, because I’ll constantly alter between turning on all and turning on only one light. I also sometimes use google assistant or some other mechanisms to make home assistant turn on/off the lights, so it will happen quite often that there is a mismatch between what the button thinks the state is and what the state actual is….

So, with all these tradeoffs, here’s the automation for my Stuedimmer who toggles my Stuetak lights:

alias: Stuetakfix
description: ""
triggers:
- topic: zigbee2mqtt/Stuedimmer/action
payload: on_press
trigger: mqtt
conditions: []
actions:
- delay:
hours: 0
minutes: 0
seconds: 0
milliseconds: 500
- variables:
lamp: light.stuetak
topic: zigbee2mqtt/Stuetak/set
new_state: "{{ 'OFF' if is_state(lamp, 'on') else 'ON' }}"
- condition: template
value_template: |
{{ (as_timestamp(now()) - as_timestamp(states[lamp].last_changed)) > 1 }}
- data:
topic: "{{ topic }}"
payload: |
{{ '{"state":"' ~ new_state ~ '"}' }}
action: mqtt.publish
mode: restart

The last mqtt.publish is how you tell zigbee2mqtt to switch the state of a light. Doing this with homeassistant mechanism, it would be:

action: light.toggle
target:
entity_id: light.stuetak
data: {}

These two are pretty equivalent, but since I am already pretty zigbee-dependent in my automation, I don’t really need to make it more general, and in theory, I guess doing it directly might be slightly more effective.

I’ll update this blog post if I solve the hue button automation or if I improve it in another way, but at least this blog post shows my intention: Make my lighting resilient to component downtime, i.e. have basic functionality being built into the zigbee network, but have my home automation system augment it with more functionality.

Over time, I might add automations for stuff like long presses, double-presses, etc, where the functionality lives in home assistant, but turning on/off a light and dimming it? It stays possible with direct binding, even if home assistant goes down.


Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *

This site uses Akismet to reduce spam. Learn how your comment data is processed.