Syncing two z-wave dimmer brightness levels works, turning off doesn't

I have two GE Z-Wave Plus dimmers in the kitchen that when both are on I’d like for them to be in sync for brightness levels. I actually have that working. The gotcha comes when I attempt to turn one of them off. If I tap the dimmer it starts to dim a bit and then appears to jump back up to the level of the other device. When I look into the database at the historical values detected I can see that the dimmers are now at a imperceptibly lower brightness value. For example, if they’re both on brightness 64, tap one dimmer, I’ll see that they are both now on brightness 60.

I suspect what’s happening is that I’ll have one start to turn off it starts dimming slowly, which then updates HASS with a lower value, who then sets opposite dimmer to that new new value, which then updates HASS with the lower value, and then bounces the new value back to the original dimmer.

To walk you through the code here, you’ll see that I’m passing the values through as sensors. This is a workaround as I want any change to the state to make the automation update. numeric_state only works as you pass a threshold whereas if you bundle the brightness attribute’s value in a sensor as a state, you can then then trigger off of any kind of state change. The rest is pretty straightforward.

At some point I tried an outlier filter, but that just put out a really low value and dropped the opposite dimmer to below the threshold of “on” for the LEDs in the can lights.

- platform: template
  sensors:
    stove_dimmer_brightness:
      value_template: '{{ states.light.stove_dimmer_level.attributes.brightness | int | default(0) }}'
      entity_id: light.stove_dimmer_level

- platform: template
  sensors:
    butlers_pantry_brightness:
      value_template: '{{ states.light.level_2.attributes.brightness | int | default(0) }}'
      entity_id: light.level_2

- alias: Kitchen Can Brightness Sync A
  trigger:
    platform: state
    entity_id: sensor.stove_dimmer_brightness
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: light.stove_dimmer_level
        state: 'on'
      - condition: state
        entity_id: light.level_2
        state: 'on'
  action:
    service: light.turn_on
    entity_id: light.level_2
    data_template:
      brightness: '{{ states.sensor.stove_dimmer_brightness.state | int }}'
- alias: Kitchen Can Brightness Sync B
  trigger:
    platform: state
    entity_id: sensor.butlers_pantry_brightness
  condition:
    condition: and
    conditions: 
      - condition: state
        entity_id: light.stove_dimmer_level
        state: 'on'
      - condition: state
        entity_id: light.level_2
        state: 'on'
  action:
    service: light.turn_on
    entity_id: light.stove_dimmer_level
    data_template:
      brightness: '{{ states.sensor.butlers_pantry_brightness.state | int }}'

So this is a hard one and might take some adjustments but I think I have a solution that may work for you. I don’t know the shape of the events, I’m taking a guess. The triggers may need to change in the automation. Either way here is a description of what these 2 things are doing. First, we are going to make a new sensor, you can remove your old senors. What this new sensor does is sorts your lights by last changed and then returns the ‘other entity’ and the brightness it should be at. This basically means that the sensor will tell us which light to change to what brightness. It also minimizes our sensors.

- platform: template
  sensors:
    kitchen_lights_sync:
      value_template: >
        {% set my_lights = [ states.light.stove_dimmer_level, states.light.level_2 ] %}
        {% for l in my_lights | sort(attribute='last_updated') %}
          {% if loop.last %}
            {{ my_lights[0].entity_id }},{{ l.attributes.brightness }}
          {% endif %}
        {% endfor %}

Second, and the one that solves your issue, we need to change your trigger. Your triggers are what are causing this to fire all the time because it’s firing off your brightness changing instead of a service being called. So we are going to try to capture the events and use them to fire the automation. Be warned, I do not remember the shape of the events. These triggers might need to be changed. Anyways, with the value_template condition, this should only sync your lights when the trigger.to_state.state is on, meaning when you trigger ‘off’, it won’t fire.

- alias: Sync Kitchen
  trigger:
    - platform: event
      event_type: state_changed
      event_data:
        entity_id: light.stove_dimmer_level
    - platform: event
      event_type: state_changed
      event_data:
        entity_id: light.level_2
  condition:
    condition: template
    value_template: "{{ trigger.to_state.state == 'on' }}"
  action:
    service: light.turn_on
    data_template: 
      entity_id: >
        {% set entity_id, brightness = states('kitchen_lights_sync').split(',') %}
        {{ entity_id }}
      brightness:
        {% set entity_id, brightness = states('kitchen_lights_sync').split(',') %}
        {{ brightness | int }}
1 Like

I determined there were a couple of bugs in the sensor and this is what appears to behave as you’ve described it should. To anybody else who uses this, coded as is it’s only useful for syncing two lights.

- platform: template
  sensors:
    kitchen_lights_sync:
      value_template: >
        {% set my_lights = [ states.light.stove_dimmer_level, states.light.level_2 ] %}
        {% for l in my_lights | sort(attribute='last_updated') %}
          {%- if loop.first %}{{ l.entity_id }}{% elif loop.last -%},{{ l.attributes.brightness | default(0) }}{% endif -%}
        {%- endfor %}

Here’s the challenge though, the trigger never sees the state change to off when it’s enabled. I’ve fiddled with the automation trigger a bit, but it’s not fixed. It does at least behave properly as far as off being triggered from the webapp, and levels syncing. For my test that generated the data below (reverse order) I disabled the automation trigger and then tapped the off half of the dimmer paddle. What we see here is that the dimmer starts to dim but remains firmly in the ‘on’ state and reports back this new value. The sensor picks it up and then the trigger would have normally fired. Instead the dimmer completely dims and turns to off. The sensor has no way of knowing that the dimmer is going to continue to go to off.

   758413 | state_changed | {"entity_id": "light.level_2", "old_state": {"entity_id": "light.level_2", "state": "on", "attributes": {"brightness": 134, "min_mireds": 153, "max_mireds": 500, "node_id": 12, "value_index": 0, "value_instance": 1, "value_id": "72057594244071425", "friendly_name": "Butler's Pantry", "supported_features": 33}, "last_changed": "2018-06-03T11:40:58.200059+00:00", "last_updated": "2018-06-03T11:56:23.385900+00:00"}, "new_state": {"entity_id": "light.level_2", "state": "off", "attributes": {"node_id": 12, "value_index": 0, "value_instance": 1, "value_id": "72057594244071425", "friendly_name": "Butler's Pantry", "supported_features": 33}, "last_changed": "2018-06-03T11:56:24.908122+00:00", "last_updated": "2018-06-03T11:56:24.908122+00:00"}}                                                         | LOCAL  | 2018-06-03 07:56:24.908144-04 | 2018-06-03 11:56:24.920355-04
   758411 | state_changed | {"entity_id": "sensor.kitchen_lights_sync", "old_state": {"entity_id": "sensor.kitchen_lights_sync", "state": "light.level_2,142", "attributes": {"friendly_name": "kitchen_lights_sync"}, "last_changed": "2018-06-03T11:47:47.533629+00:00", "last_updated": "2018-06-03T11:47:47.533629+00:00"}, "new_state": {"entity_id": "sensor.kitchen_lights_sync", "state": "light.stove_dimmer_level,134", "attributes": {"friendly_name": "kitchen_lights_sync"}, "last_changed": "2018-06-03T11:56:23.397631+00:00", "last_updated": "2018-06-03T11:56:23.397631+00:00"}}                                                                                                                                                                                                                                                             | LOCAL  | 2018-06-03 07:56:23.39768-04  | 2018-06-03 11:56:23.414848-04
   758410 | state_changed | {"entity_id": "light.level_2", "old_state": {"entity_id": "light.level_2", "state": "on", "attributes": {"brightness": 142, "min_mireds": 153, "max_mireds": 500, "node_id": 12, "value_index": 0, "value_instance": 1, "value_id": "72057594244071425", "friendly_name": "Butler's Pantry", "supported_features": 33}, "last_changed": "2018-06-03T11:40:58.200059+00:00", "last_updated": "2018-06-03T11:47:47.407454+00:00"}, "new_state": {"entity_id": "light.level_2", "state": "on", "attributes": {"brightness": 134, "min_mireds": 153, "max_mireds": 500, "node_id": 12, "value_index": 0, "value_instance": 1, "value_id": "72057594244071425", "friendly_name": "Butler's Pantry", "supported_features": 33}, "last_changed": "2018-06-03T11:40:58.200059+00:00", "last_updated": "2018-06-03T11:56:23.385900+00:00"}} | LOCAL  | 2018-06-03 07:56:23.385938-04 | 2018-06-03 11:56:23.405452-04

Below is my final solution. I would up slipping in a limiter so that if the change was less than 10 (as in the case with dimming towards off) then to ignore it. I also tweaked it a bit to add support for turning on to match the brightness of the other light, instead of defaulting to the initial value of 3, and to properly handle the case when both are off but only one is wanted to be turned on.

- platform: template
  sensors:
    kitchen_lights_sync:
      value_template: >
        {% set my_lights = [ states.light.stove_dimmer_level, states.light.level_2 ] %}
        {% for l in my_lights | sort(attribute='last_updated') %}
          {%- if loop.first %}{{ l.entity_id }}{% elif loop.last -%},{{ l.attributes.brightness | default(0) }}{% endif -%}
        {%- endfor %}

- alias: Sync Kitchen
  trigger:
    - platform: state
      entity_id: light.stove_dimmer_level
    - platform: state
      entity_id: light.level_2
  condition:
    condition: and
    conditions:
      - condition: template
        value_template: "{{ states('sensor.kitchen_lights_sync').split(',')[1] | int > 0 }}"
      - condition: state
        entity_id: light.stove_dimmer_level
        state: 'on'
      - condition: state
        entity_id: light.level_2
        state: 'on'
      - condition: or
        conditions:
          - condition: template
            value_template: "{{ trigger.from_state.attributes.brightness | int | default(0) > 5 + trigger.to_state.attributes.brightness | int | default(0) }}"
          - condition: template
            value_template: "{{ trigger.from_state.attributes.brightness | int | default(0) < trigger.to_state.attributes.brightness | int | default(0) }}"
  action:
    service: light.turn_on
    data_template:
      entity_id: >
        {% set entity_id, brightness = states('sensor.kitchen_lights_sync').split(',') %}
        {{ entity_id }}
      brightness: >
        {% set entity_id, brightness = states('sensor.kitchen_lights_sync').split(',') %}
        {%- if brightness | int | default(0) < 10 -%}
        {% set brightness = [states.light.stove_dimmer_level.brightness | int | default(0), states.light.level_2.brightness | int | default(0)]|max %}
        {%- endif -%}  
        {{ brightness | int }}
1 Like

Hello, i tried to use this code but i its only syncing dimmers when they are both on, how can i adjust this automation to turn on or off the dimmer2 when i turn on/off the first dimmer1 and vice versa.