Zigbee2MQTT Lutron Aurora Dimmer Control

First, thank you for sharing this. I was just beating my head against the wall trying to get off of using only binding (I know the value for redundancy but for a variety of reasons I prefer to use HA)

Second, just for anyone else who can be an idiot like me, when it comes to adding the sensor it goes under “mqtt:” not under template or sensors or whatever else. I don’t have any other custom MQTT devices so it threw me off for a bit trying to find where it went. Also from what I know, unique_id can be whatever as long as it’s unique.

Here’s an example of a complete setup in your HA config file:

mqtt:
  - sensor:
    - name: "Dining Room Switch K MQTT"                                           
      unique_id: "1958669490006"
      state_topic: "zigbee2mqtt/Dining Room Switch K"  
      value_template: "{{ value_json.action }}"
      json_attributes_topic: "zigbee2mqtt/Dining Room Switch K"
      json_attributes_template: "{{ value_json | tojson }}"

Hi,

I’m a bit of a newb to this, but I’m getting the following error in relation to this automation:

Logger: homeassistant.components.automation.zigbee2mqtt_lutron_aurora_dimmer_control
Source: components/automation/__init__.py:669
integration: Automation (documentation, issues)
First occurred: 3:43:07 AM (1 occurrences)
Last logged: 3:43:07 AM

Error rendering variables: UndefinedError: 'dict object' has no attribute 'to_state'

And the following warning as well:

Logger: homeassistant.helpers.template
Source: helpers/template.py:2613
First occurred: 3:42:50 AM (37 occurrences)
Last logged: 3:45:48 AM

Template variable warning: 'homeassistant.helpers.template.Wrapper object' has no attribute 'action' when rendering '{{ attrs["action"] }}'
Template variable warning: 'homeassistant.helpers.template.Wrapper object' has no attribute 'action_level' when rendering '{{ attrs["action_level"] }}'
Template variable warning: 'homeassistant.helpers.template.Wrapper object' has no attribute 'action_transition_time' when rendering '{{ attrs["action_transition_time"] }}'
Template variable error: 'dict object' has no attribute 'to_state' when rendering '{{ trigger.to_state.attributes }}'

Any idea how to fix? I added the entry to my config similar as to how Robert did it in the message above mine.

This works…

1.) Import blueprint from drinfernoo

2.) Make a new sensor referencing wmaker’s post. You can either make a separate yaml or include it directly in your configuration.yaml. Use the file editor add-on to make your life easier.

# Custom Additions:
# You can uncomment the line below and optionally place the sensor below
# inside of sensor.yaml - it's up to you!
#sensor: !include sensor.yaml

mqtt:
  sensor:
    - name: "Switch_Lutron-Aurora-1"
      unique_id: "0xffff000fe7fb806b"
      state_topic: "zigbee2mqtt/Switch_Lutron-Aurora-1"
      value_template: "{{ value_json.action }}"
      json_attributes_topic: "zigbee2mqtt/Switch_Lutron-Aurora-1"
      json_attributes_template: "{{ value_json | tojson }}"

3.) When you create the automation from the blueprint use the new sensor you just created (name above) and NOT the action or brightness entities.

4.) Voila! Click for on/off. Turn to dim. Only minor caveat, the dimming isn’t very graceful. But it works!

I think I was able to fix the stuttery dimming by adding a transition to setting the brightness of the light. Using the 0.02 transition timing (that the aurora uses) wasn’t great, but using something like 0.2 is much more appealing. It’s a bit laggy, but you can tune that time to balance between smoothness and laginess.

This no longer seems to be working in Z2M 2.0.0 even with the custom sensor from wmaker’s post.

I ended up binding my dimmers to the lights and light groups in Z2M. Seems to be more responsive that way too.

Yeah I haven’t gotten around to fixing this with the new 2.0.0 upgrade.
In the meantime, can you provide a writeup of how you did the binding?

I’m having my people flip on legacy until I fix mine so everything still works as before. I’m going to use the event entity method If I can make it work. I won’t use devices if I can help it. FYI.

How did you do this?
I tried something per page 5 of the Advanced Install Guide of Aurora, and while controlling the light on and off works perfectly, the brightness value of the light and the dimmer - at least per z2m - are not in sync.

Chances are this works best if the dimmers and lights are the same mfgr. Not all combinations will bind well.

However Lutron, who makes this Aurora dimmer, does not make any smart bulb… so “the same manufacturer” would not be possible.

Then if you are lucky it will work, if not it won’t.
Mine have never worked.

I’ve been playing around with the event entity, (one has to first enable Z2M’s Home Assistant experimental event entities).

I haven’t been able to get a trigger to fire. I’m kinda thinking there is a bug.

The event entity lists the possible event types and the only one is:

brightness

Yet when I push the Aurora button, I get an error log saying

WARNING (MainThread) [homeassistant.components.mqtt.event] Invalid event type brightness_move_to_level for event.
fireplace_dimmer_action received on topic zigbee2mqtt/Fireplace Dimmer, payload {"event_type":"brightness_move_to_level"}

So I think Z2M is telling HA via autodiscovery that only brightness is supported, yet Z2M is instead sending brightness_move_to_level

Actual triggers are straight forward. Brightness, don’t know. Look in

Open your Home Assistant instance and show your event developer tools.

for that event and see what is available in the data. It’s probably something there.

For now, there is a PR on this device for Z2M 2.0.0

1 Like

Bindings

I was finally able to get bindings to work in my setup (Aurora Dimmer to a couple of Philips Hue bulbs), so thought I would provide a quick write-up.

Binding is reasonably easy to setup using the Z2M UI, but the problem I kept running into was finding the right clusters to bind with that would actually allow the Aurora Dimmer to control the bulbs.

Steps

  1. Pre-check: Determining Endpoints and Clusters
    a. Goto Z2M-UI Philips Hue Device and see what clusters it supports and in which endpoint.
    For mine, the Endpoint was 11 which has Level Control, OnOff, Touchlink, and other clusters of interest
    b. Goto Z2M-UI Aurora Device and see what clusters it supports and in which endpoint.
    Endpoint 1 has Level Control, OnOff, Touchlink, and other clusters of interest
    c. Have the bulbs near the Aurora Dimmer. My Bulbs are at most 10 feet away

  2. Goto Z2M-UI Aurora Dimmer and goto the Bind Tab.
    a. There are an empty set of boxes available for adding a new binding entry (don’t mess with the existing binding with the Coordinator). I set mine as follows:
    Source Endpoint =1
    Destination = “My Philips Hue 1”
    Destination Endpoint = 11
    LevelCtrl = ticked (all other clusters unticked)

    b.Click on “Bind” button and quickly (within a couple of seconds),
    go over to the Aurora Dimmer and tap the switch to wake it up.
    It should show in the UI that the binding of LevelCtrl was successful.
    Around 20 seconds later you may get a failure indicator regarding Change Reports failed to be setup, but this doesn’t seem to matter.

Only binding the LevelCtrl to the Philips Hue worked for me. Any other combination of clusters to bind would be successful at binding, but left the Aurora Dimmer unable to actually control the Philips Hue (nothing would happen when tapping/dimming). As an FYI, this HA Community Forum user was successful with their IKEA bulbs by binding LevelCtrl, OnOff, and Touchlink clusters with their IKEA Bulbs. So which clusters to bind may vary depending on your situation.

I should also add that I wanted the same Aurora Dimmer to control a second Philips Hue bulb, so I repeated the process above for the second bulb. It may have been possible to put the bulbs in a ZigBee Group and to have done the binding on the Group, but I did not try this.

1 Like

This was the solution I have been looking for! (down the page)

alias: Lutron Aurora Dimmer (Upstairs Hall Lamp)
description: MQTT trigger for Lutron Aurora Dimmer Knob
triggers:

  • trigger: mqtt
    topic: zigbee2mqtt/Upstairs Hall Light Control
    payload: brightness_move_to_level
    value_template: “{{ value_json.action }}”
    actions:
  • choose:
    • conditions:
      • condition: template
        value_template: “{{ action_level == 0 }}”
        sequence:
      • data:
        transition: “{{ transition_time }}”
        target:
        device_id: 7eccead43f6ade7b1d32845a44887092
        action: light.turn_off
        default:
    • target:
      device_id: 7eccead43f6ade7b1d32845a44887092
      data:
      transition: “{{ transition_time }}”
      brightness: “{{ action_level }}”
      action: light.turn_on
      mode: queued
      max_exceeded: silent
      variables:
      action: “{{ trigger.payload_json.action }}”
      action_level: “{{ trigger.payload_json.action_level }}”
      transition_time: “{{ trigger.payload_json.action_transition_time }}”

I had the same problem with updated Zigbee2MQTT. The last reply almost worked for me. However, I noticed action_level goes to “null” when I turn the dimmer on by pressing the button. That wasn’t working. You can’t test for null as a value as far as I can tell. I beat my head against it for a while until realizing that you can make turning on via null the “default action” and make the brightness adjustment a second option. Also I like using entity names instead of a device id since I control multiple lights with my dimmer. Here is my version. As above you have to edit your topic and the target entity IDs to match your dimmer and lights.

alias: Lutron Aurora Dimmer (Basement)
description: MQTT trigger for Lutron Aurora Dimmer Knob
triggers:
  - trigger: mqtt
    topic: zigbee2mqtt/basement_dimmer
    payload: brightness_move_to_level
    value_template: "{{ value_json.action }}"
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ action_level == 0 }}"
        sequence:
          - data:
              transition: "{{ transition_time }}"
            action: light.turn_off
            target:
              entity_id:
                - light.basement_lights_2
                - light.wled
                - light.wled_2
      - conditions:
          - condition: template
            value_template: "{{ action_level > 0 }}"
        sequence:
          - data:
              transition: "{{ transition_time }}"
              brightness: "{{ action_level }}"
            action: light.turn_on
            target:
              entity_id:
                - light.basement_lights_2
                - light.wled
                - light.wled_2
    default:
      - data:
          transition: "{{ transition_time }}"
          brightness: "255"
        action: light.turn_on
        target:
          entity_id:
            - light.basement_lights_2
            - light.wled
            - light.wled_2
mode: queued
max_exceeded: silent
variables:
  action: "{{ trigger.payload_json.action }}"
  action_level: "{{ trigger.payload_json.action_level }}"
  transition_time: "{{ trigger.payload_json.action_transition_time }}"

Hi all, the most recent reply here was working for me but wasn’t ideal for use with adaptive lighting or when also controlling via a second source (in my case a pico remote).

  • The above automation bypassed adaptive lighting (when take_over_control is enabled) and turned the lights to full brightness everytime.
  • Using the pico remote sometimes resulted in the states getting misaligned which would require a couple clicks to turn the lights off, which can be annoying if you already started walking away before realizing the lights didn’t actually turn off.

Fixing the adaptive lighting compatibility isn’t too hard, you just need to send no brightness value when turning the lights on and enable adapt_only_on_bare_turn_on. Unfortunately, preventing the occasional need for double clicks required a bit of a hack. The configuration below relies on the transition_time of the mqtt command to differentiate between button clicks and twisting the knob to know if I’m trying to toggle the light or adjust the brightness. It is of course subject to break if the values being sent for the transition time ever change or aren’t the same for you.

Known issues

  • Sometimes the light seems to get “stuck” at a certain level and I need to twist the knob in the opposite direction or wait a second to get it unstuck. Not sure why this happens but I’ll post an update if I mange to figure it out.

P.S. I used ChatGPT to create this and I’m new to fiddling with HA yaml so feedback is welcome. Hope this is helpful!

alias: Living Room Lights Dimmer Automation
description: Control lights from Lutron Aurora via Zigbee2MQTT (click-to-toggle + dimmer rules)
mode: restart

variables:
  # ---- EDIT THESE FOR YOUR SETUP ----
  lights_target:
    - light.living_room_lights
  mqtt_topic: zigbee2mqtt/Switch - Kitchen 1
  # -----------------------------------

  # Payload helpers (no need to edit)
  lvl: >-
    {% if trigger and trigger.payload_json.action_level is defined %}
      {{ trigger.payload_json.action_level }}
    {% elif trigger and trigger.payload_json.brightness is defined %}
      {{ trigger.payload_json.brightness }}
    {% else %}
      {{ none }}
    {% endif %}
  t: "{{ trigger.payload_json.action_transition_time | default(0) if trigger else 0 }}"
  act: "{{ trigger.payload_json.action | default('') if trigger else '' }}"
  is_click: >-
    {{ act == 'brightness_move_to_level' and (t | float(0) >= 0.06) }}

trigger:
  - platform: mqtt
    # NOTE: templates aren't supported here; keep this literal.
    topic: zigbee2mqtt/Switch - Kitchen 1

condition:
  - condition: template
    value_template: "{{ trigger.payload_json.action == 'brightness_move_to_level' }}"

action:
  - choose:
      # A) CLICK toggle behavior
      - conditions:
          - condition: template
            value_template: "{{ is_click and expand(lights_target) | selectattr('state','eq','on') | list | count > 0 }}"
        sequence:
          - service: light.turn_off
            target:
              entity_id: "{{ lights_target }}"
            data:
              transition: "{{ t | float(0) }}"

      - conditions:
          - condition: template
            value_template: "{{ is_click and expand(lights_target) | selectattr('state','eq','on') | list | count == 0 }}"
        sequence:
          - service: light.turn_on
            target:
              entity_id: "{{ lights_target }}"
            data:
              transition: "{{ t | float(0) }}"

      # B) DIMMER: all targets OFF → turn ON (no brightness)
      - conditions:
          - condition: template
            value_template: >
              {{ not is_click and expand(lights_target) | selectattr('state','eq','on') | list | count == 0 }}
        sequence:
          - service: light.turn_on
            target:
              entity_id: "{{ lights_target }}"
            data:
              transition: "{{ t | float(0) }}"

      # C) DIMMER: some ON and level == 0 → turn OFF
      - conditions:
          - condition: template
            value_template: >
              {{ not is_click and (lvl | int(0) == 0) and expand(lights_target) | selectattr('state','eq','on') | list | count > 0 }}
        sequence:
          - service: light.turn_off
            target:
              entity_id: "{{ lights_target }}"
            data:
              transition: "{{ t | float(0) }}"

    # D) DIMMER: otherwise set the provided brightness
    default:
      - choose:
          - conditions:
              - condition: template
                value_template: "{{ not is_click and (lvl is not none) }}"
            sequence:
              - service: light.turn_on
                target:
                  entity_id: "{{ lights_target }}"
                data:
                  brightness: "{{ lvl | int }}"
                  transition: "{{ t | float(0) }}"
        default: []
1 Like

Kudos to you, Joey. And all that came before, as well.

That is to say, this worked so well for me that I need to cool my jets. With 15 or so Aurora’s throughout the home, I’m excited to see how well this can work out for all of 'em.

Thanks