ZHA/Z2M - Control light color, hue, brightness with ERS dial

An automation blueprint to control the color, hue (warm/cold) and brightness of a light (or group of lights) using an ERS knob. As featured on Byte My Bits.

This automation will allow you to toggle through four modes:

  • Color - rotating the dial left or right changes the color (full RGB spectrum, looping)
  • Hue - rotating the dial left or right changes the hue (min 2000, max 6500)
  • Brightness - rotating the dial left or right changes the brightness (min 0, max 255)
  • Off - rotating the dial left or right does nothing

Blueprint

ZHA

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

# Instructions: https://community.home-assistant.io/t/zha-z2m-control-light-color-hue-brightness-with-ers-dial/595002

blueprint:
  name: ERS Rotary Dial - Light Control (ZHA) - COMMAND mode
  description: Control light brightness, hue and color with an ERS rotary dial

  source_url: https://raw.githubusercontent.com/nwithan8/configs/main/home_assistant/blueprints/automations/ers_rotary_dial_light_control_zha.yaml

  domain: automation

  input:
    light:
      name: Light
      description: The Light entity or Light Group entity to control
      selector:
        entity:
          filter:
            - domain:
                - light
                - group
          multiple: false

    dial:
      name: Rotary dial
      description: Select the rotary dial you wish to use to control the light
      selector:
        device:
          filter:
            integration: zha
            model: TS004F

    mode_tracker:
      name: Mode tracker
      description: An input number helper to store the current mode in (1-4)
      selector:
        entity:
          filter:
            domain: input_number

    color_tracker:
      name: Color tracker
      description: An input number helper to store the current RGB value in (0-1535)
      selector:
        entity:
          filter:
            domain: input_number

    hue_tracker:
      name: Hue tracker
      description: An input number helper to store the current hue in (2000-6500)
      selector:
        entity:
          filter:
            domain: input_number

    brightness_tracker:
      name: Brightness tracker
      description: An input number helper to store the current brightness in (0-255)
      selector:
        entity:
          filter:
            domain: input_number

# Queued, to ignore non-matched events but capture existing ones
mode: queued
max: 20
max_exceeded: silent

variables:
  light: !input "light"
  dial: !input "dial"
  mode_tracker: !input "mode_tracker"
  hue_tracker: !input "hue_tracker"
  brightness_tracker: !input "brightness_tracker"
  color_tracker: !input "color_tracker"
  command: "{{ trigger.event.data.command }}"
  single_pressed: "{{ command == 'toggle' }}"
  # double_pressed: "{{ command == 'move_saturation' }}" # dumb: https://github.com/zigpy/zha-device-handlers/blob/92c9fbc6d01a5d86f78d64183302b906aa7d8215/zhaquirks/tuya/ts004f.py#L146C37-L146C37
  rotated: "{{ command == 'step' }}"
  positive: "{{ rotated and trigger.event.data.params.step_mode == 0 }}"
  step_size: >
    {% if rotated %}
      {{ trigger.event.data.params.step_size | float(0) }}
    {% else %}
      {{ 0 }}
    {% endif %}
  # How many steps to go full rotation (min 13 per step * 20 steps per full rotation)
  full_rotate_step_count: "{{ 13 * 20 | int }}"
  current_mode: "{{ states(mode_tracker) | int }}"
  min_mode: "{{ state_attr(mode_tracker, 'min') | int }}"
  max_mode: "{{ state_attr(mode_tracker, 'max') | int }}"
  # always increment, looping
  next_mode: >
    {% set val = current_mode + 1 %} 
    {% if val > max_mode %} 
      {% set val = min_mode %}
    {% endif %}
    {{ val | int }}
  min_hue: "{{ state_attr(hue_tracker, 'min') | int }}"
  max_hue: "{{ state_attr(hue_tracker, 'max') | int }}"
  # How many steps to go full min-max spectrum
  hue_steps: "{{ full_rotate_step_count * 2 | int }}"
  hue_delta: "{{ (step_size | float(0) / hue_steps) * (max_hue - min_hue) }}"
  # don't loop when reached max or min
  next_hue: >
    {%- set val = states(hue_tracker) | float(0) -%}
    {%- set delta = hue_delta -%}
    {%- if not positive -%}
      {%- set delta = delta * -1 -%}
    {%- endif -%}
    {%- set val = val + delta | int -%}
    {%- if positive and val > max_hue -%}
      {%- set val = max_hue -%}
    {%- elif not positive and val < min_hue -%}
      {%- set val = min_hue -%}
    {%- endif -%}
    {{ val | int }}
  min_brightness: "{{ state_attr(brightness_tracker, 'min') | int }}"
  max_brightness: "{{ state_attr(brightness_tracker, 'max') | int }}"
  # How many steps to go full min-max spectrum
  brightness_steps: "{{ full_rotate_step_count * 2 | int }}"
  brightness_delta: "{{ (step_size | float(0) / brightness_steps) * (max_brightness - min_brightness) }}"
  # don't loop when reached max or min
  next_brightness: >
    {%- set val = states(brightness_tracker) | float(0) -%}
    {%- set delta = brightness_delta -%}
    {%- if not positive -%}
      {%- set delta = delta * -1 -%}
    {%- endif -%}
    {%- set val = val + delta | int -%}
    {%- if positive and val > max_brightness -%} 
      {%- set val = max_brightness -%}
    {%- elif not positive and val < min_brightness -%}
      {%- set val = min_brightness -%}
    {%- endif -%}
    {{ val | int }}
  min_color: "{{ state_attr(color_tracker, 'min') | int }}"
  max_color: "{{ state_attr(color_tracker, 'max') | int }}"
  # How many steps to go full min-max spectrum
  color_steps: "{{ full_rotate_step_count * 3 | int }}"
  color_delta: "{{ (step_size | float(0) / color_steps) * (max_color - min_color) }}"
  # loop when reached max or min
  next_color: >
    {%- set val = states(color_tracker) | float(0) -%}
    {%- set delta = color_delta -%}
    {%- if not positive -%}
      {%- set delta = delta * -1 -%}
    {%- endif -%}
    {%- set val = val + delta | int -%}
    {%- if positive and val > max_color -%}
      {%- set val = val % max_color -%}
    {%- elif not positive and val < min_color -%}
      {%- set diff = min_color - val -%}
      {%- set val = max_color - (diff % max_color) -%}
    {%- endif -%}
    {{ val | int }}

trigger:
  - platform: event
    event_type: zha_event
    event_data:
      device_id: !input dial

action:
  # Process current event
  - choose:
      # If event was a dial turn
      - conditions:
          - condition: template
            value_template: "{{ rotated }}"
            alias: Dial turned (0 for right, 1 for left)
        sequence:
          # Process different actions based on current mode
          - choose:
              # In Mode 1 (don't do anything; prevent accidental knob rotation)
              - conditions:
                  - condition: template
                    value_template: "{{ current_mode == 1 }}"
                    alias: In Mode 1 (Power)
                sequence: [ ]
              # In Mode 2 (Brightness)
              - conditions:
                  - condition: template
                    value_template: "{{ current_mode == 2 }}"
                    alias: In Mode 2 (Brightness)
                sequence:
                  - service: input_number.set_value
                    entity_id: !input brightness_tracker
                    data:
                      value: "{{ next_brightness }}"
                    alias: Update brightness tracker
                  - service: light.turn_on
                    data:
                      brightness: "{{ states(brightness_tracker) | int }}"
                    target:
                      entity_id: !input light
                    alias: Change light brightness
              # In Mode 3 (Hue)
              - conditions:
                  - condition: template
                    value_template: "{{ current_mode == 3 }}"
                    alias: In Mode 3 (Hue)
                sequence:
                  - service: input_number.set_value
                    entity_id: !input hue_tracker
                    data:
                      value: "{{ next_hue }}"
                    alias: Update hue tracker
                  - service: light.turn_on
                    data:
                      kelvin: "{{ states(hue_tracker) | int }}"
                    target:
                      entity_id: !input light
                    alias: Change light hue
              # In Mode 4 (Color)
              - conditions:
                  - condition: template
                    value_template: "{{ current_mode == 4 }}"
                    alias: In Mode 4 (Color)
                sequence:
                  - service: input_number.set_value
                    entity_id: !input color_tracker
                    data:
                      value: "{{ next_color }}"
                    alias: Update color tracker
                  - service: light.turn_on
                    data:
                      # Calculate RGB codes based on 0-1535 index (max 2 channels, one always off)
                      rgb_color: >
                        {%- set r = 0 -%}
                        {%- set g = 0 -%}
                        {%- set b = 0 -%}
                        {%- set index = states(color_tracker) | int -%}
                        {%- if index > 0 and index <= 256 -%}
                          {%- set r = 255 -%}
                          {%- set g = index -%}
                          {%- set b = 0 -%}
                        {%- elif index > 256 and index <= 512 -%}
                          {%- set r = 512 - index -%}
                          {%- set g = 255 -%}
                          {%- set b = 0 -%}
                        {%- elif index > 512 and index <= 768 -%}
                          {%- set r = 0 -%}
                          {%- set g = 255 -%}
                          {%- set b = index - 512 -%}
                        {%- elif index > 768 and index <= 1024 -%}
                          {%- set r = 0 -%}
                          {%- set g = 1024 - index -%}
                          {%- set b = 255 -%}
                        {%- elif index > 1024 and index <= 1280 -%}
                          {%- set r = index - 1024 -%}
                          {%- set g = 0 -%}
                          {%- set b = 255 -%}
                        {%- elif index > 1280 and index <= 1536 -%}
                          {%- set r = 255 -%}
                          {%- set g = 0 -%}
                          {%- set b = 1536 - index -%}
                        {%- endif -%}
                        {%- set r = r | string -%}
                        {%- set g = g | string -%}
                        {%- set b = b | string -%}
                        {{ r + "," + g + "," + b }}
                    target:
                      entity_id: !input light
                    alias: Change light color
            alias: Determine action based on mode
      # If event was a dial button short push
      - conditions:
          - condition: template
            value_template: "{{ single_pressed }}"
        sequence:
          # Change mode (cycling back if reached the end)
          - service: input_number.set_value
            entity_id: !input mode_tracker
            data:
              value: "{{ next_mode }}"
            alias: Switch to next mode

Zigbee2MQTT

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

# Instructions: https://community.home-assistant.io/t/zha-z2m-control-light-color-hue-brightness-with-ers-dial/595002

blueprint:
  name: ERS Rotary Dial - Light Control (Z2M) - COMMAND mode
  description: >
    Control light brightness, hue and color with an ERS rotary dial.
    Device needs to be in COMMAND mode (triple-press the button to switch modes).
    Needs "Home Assistant legacy entity attributes" checked.

  source_url: https://raw.githubusercontent.com/nwithan8/configs/main/home_assistant/blueprints/automations/ers_rotary_dial_light_control_z2m.yaml

  domain: automation

  input:
    light:
      name: Light
      description: The Light entity or Light Group entity to control
      selector:
        entity:
          filter:
            - domain:
                - light
                - group
          multiple: false

    dial:
      name: Rotary dial
      description: Select the rotary dial you wish to use to control the light
      selector:
        device:
          filter:
            integration: mqtt

    mode_tracker:
      name: Mode tracker
      description: An input number helper to store the current mode in (1-4)
      selector:
        entity:
          filter:
            domain: input_number

    color_tracker:
      name: Color tracker
      description: An input number helper to store the current RGB value in (0-1535)
      selector:
        entity:
          filter:
            domain: input_number

    hue_tracker:
      name: Hue tracker
      description: An input number helper to store the current hue in (2000-6500)
      selector:
        entity:
          filter:
            domain: input_number

    brightness_tracker:
      name: Brightness tracker
      description: An input number helper to store the current brightness in (0-255)
      selector:
        entity:
          filter:
            domain: input_number

# Queued, to ignore non-matched events but capture existing ones
mode: queued
max: 20
max_exceeded: silent

trigger:
  - platform: state
    entity_id: !input dial
    not_to: ""
    attribute: action

action:
  - variables:
      light: !input "light"
      dial: !input "dial"
      mode_tracker: !input "mode_tracker"
      hue_tracker: !input "hue_tracker"
      brightness_tracker: !input "brightness_tracker"
      color_tracker: !input "color_tracker"
      dial_topic: "{{ base_topic }}/{{ device_attr(dial, 'name') }}/action"
      # Ref: https://community.home-assistant.io/t/zigbee2mqtt-tuya-moes-smart-knob-ers-10tzbvk-aa/419989/26
      command: "{{ trigger.to_state.state }}"
      single_pressed: "{{ command == 'toggle' }}"
      double_pressed: "{{ command == 'double' }}"
      rotated: "{{ command in ['brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'] }}"
      positive: "{{ command in ['brightness_step_up', 'color_temperature_step_up'] }}"
      step_size: "{{ trigger.to_state.attributes.action_step_size }}"
      # How many steps to go full rotation (min 13 per step * 20 steps per full rotation)
      full_rotate_step_count: "{{ 13 * 20 | int }}"
      current_mode: "{{ states(mode_tracker) | int }}"
      min_mode: "{{ state_attr(mode_tracker, 'min') | int }}"
      max_mode: "{{ state_attr(mode_tracker, 'max') | int }}"
      # always increment, looping
      next_mode: >
        {% set val = current_mode + 1 %} 
        {% if val > max_mode %} 
          {% set val = min_mode %}
        {% endif %}
        {{ val | int }}
      min_hue: "{{ state_attr(hue_tracker, 'min') | int }}"
      max_hue: "{{ state_attr(hue_tracker, 'max') | int }}"
      # How many steps to go full min-max spectrum
      hue_steps: "{{ full_rotate_step_count * 2 | int }}"
      hue_delta: "{{ (step_size | float(0) / hue_steps) * (max_hue - min_hue) }}"
      # don't loop when reached max or min
      next_hue: >
        {%- set val = states(hue_tracker) | float(0) -%}
        {%- set delta = hue_delta -%}
        {%- if not positive -%}
          {%- set delta = delta * -1 -%}
        {%- endif -%}
        {%- set val = val + delta | int -%}
        {%- if positive and val > max_hue -%}
          {%- set val = max_hue -%}
        {%- elif not positive and val < min_hue -%}
          {%- set val = min_hue -%}
        {%- endif -%}
        {{ val | int }}
      min_brightness: "{{ state_attr(brightness_tracker, 'min') | int }}"
      max_brightness: "{{ state_attr(brightness_tracker, 'max') | int }}"
      # How many steps to go full min-max spectrum
      brightness_steps: "{{ full_rotate_step_count * 2 | int }}"
      brightness_delta: "{{ (step_size | float(0) / brightness_steps) * (max_brightness - min_brightness) }}"
      # don't loop when reached max or min
      next_brightness: >
        {%- set val = states(brightness_tracker) | float(0) -%}
        {%- set delta = brightness_delta -%}
        {%- if not positive -%}
          {%- set delta = delta * -1 -%}
        {%- endif -%}
        {%- set val = val + delta | int -%}
        {%- if positive and val > max_brightness -%} 
          {%- set val = max_brightness -%}
        {%- elif not positive and val < min_brightness -%}
          {%- set val = min_brightness -%}
        {%- endif -%}
        {{ val | int }}
      min_color: "{{ state_attr(color_tracker, 'min') | int }}"
      max_color: "{{ state_attr(color_tracker, 'max') | int }}"
      # How many steps to go full min-max spectrum
      color_steps: "{{ full_rotate_step_count * 3 | int }}"
      color_delta: "{{ (step_size | float(0) / color_steps) * (max_color - min_color) }}"
      # loop when reached max or min
      next_color: >
        {%- set val = states(color_tracker) | float(0) -%}
        {%- set delta = color_delta -%}
        {%- if not positive -%}
          {%- set delta = delta * -1 -%}
        {%- endif -%}
        {%- set val = val + delta | int -%}
        {%- if positive and val > max_color -%}
          {%- set val = val % max_color -%}
        {%- elif not positive and val < min_color -%}
          {%- set diff = min_color - val -%}
          {%- set val = max_color - (diff % max_color) -%}
        {%- endif -%}
        {{ val | int }}
  # Process current event
  - choose:
      # Verify that the dial is the one that triggered the event
      - conditions:
          - "{{ trigger.payload != ''}}"
          - "{{ trigger.topic == dial_topic }}"
        sequence:
          - choose:
              # If event was a dial turn
              - conditions:
                  - condition: template
                    value_template: "{{ rotated }}"
                    alias: Dial turned (0 for right, 1 for left)
                sequence:
                  # Process different actions based on current mode
                  - choose:
                      # In Mode 1 (don't do anything; prevent accidental knob rotation)
                      - conditions:
                          - condition: template
                            value_template: "{{ current_mode == 1 }}"
                            alias: In Mode 1 (Power)
                        sequence: [ ]
                      # In Mode 2 (Brightness)
                      - conditions:
                          - condition: template
                            value_template: "{{ current_mode == 2 }}"
                            alias: In Mode 2 (Brightness)
                        sequence:
                          - service: input_number.set_value
                            entity_id: !input brightness_tracker
                            data:
                              value: "{{ next_brightness }}"
                            alias: Update brightness tracker
                          - service: light.turn_on
                            data:
                              brightness: "{{ states(brightness_tracker) | int }}"
                            target:
                              entity_id: !input light
                            alias: Change light brightness
                      # In Mode 3 (Hue)
                      - conditions:
                          - condition: template
                            value_template: "{{ current_mode == 3 }}"
                            alias: In Mode 3 (Hue)
                        sequence:
                          - service: input_number.set_value
                            entity_id: !input hue_tracker
                            data:
                              value: "{{ next_hue }}"
                            alias: Update hue tracker
                          - service: light.turn_on
                            data:
                              kelvin: "{{ states(hue_tracker) | int }}"
                            target:
                              entity_id: !input light
                            alias: Change light hue
                      # In Mode 4 (Color)
                      - conditions:
                          - condition: template
                            value_template: "{{ current_mode == 4 }}"
                            alias: In Mode 4 (Color)
                        sequence:
                          - service: input_number.set_value
                            entity_id: !input color_tracker
                            data:
                              value: "{{ next_color }}"
                            alias: Update color tracker
                          - service: light.turn_on
                            data:
                              # Calculate RGB codes based on 0-1535 index (max 2 channels, one always off)
                              rgb_color: >
                                {%- set r = 0 -%}
                                {%- set g = 0 -%}
                                {%- set b = 0 -%}
                                {%- set index = states(color_tracker) | int -%}
                                {%- if index > 0 and index <= 256 -%}
                                  {%- set r = 255 -%}
                                  {%- set g = index -%}
                                  {%- set b = 0 -%}
                                {%- elif index > 256 and index <= 512 -%}
                                  {%- set r = 512 - index -%}
                                  {%- set g = 255 -%}
                                  {%- set b = 0 -%}
                                {%- elif index > 512 and index <= 768 -%}
                                  {%- set r = 0 -%}
                                  {%- set g = 255 -%}
                                  {%- set b = index - 512 -%}
                                {%- elif index > 768 and index <= 1024 -%}
                                  {%- set r = 0 -%}
                                  {%- set g = 1024 - index -%}
                                  {%- set b = 255 -%}
                                {%- elif index > 1024 and index <= 1280 -%}
                                  {%- set r = index - 1024 -%}
                                  {%- set g = 0 -%}
                                  {%- set b = 255 -%}
                                {%- elif index > 1280 and index <= 1536 -%}
                                  {%- set r = 255 -%}
                                  {%- set g = 0 -%}
                                  {%- set b = 1536 - index -%}
                                {%- endif -%}
                                {%- set r = r | string -%}
                                {%- set g = g | string -%}
                                {%- set b = b | string -%}
                                {{ r + "," + g + "," + b }}
                            target:
                              entity_id: !input light
                            alias: Change light color
                    alias: Determine action based on mode
              # If event was a dial button short push
              - conditions:
                  - condition: template
                    value_template: "{{ single_pressed }}"
                sequence:
                  # Change mode (cycling back if reached the end)
                  - service: input_number.set_value
                    entity_id: !input mode_tracker
                    data:
                      value: "{{ next_mode }}"
                    alias: Switch to next mode
              # If event was a dial button long press
              - conditions:
                  - condition: template
                    value_template: "{{ double_pressed }}"
                sequence:
                  # Toggle light power
                  - service: light.toggle
                    data: { }
                    target:
                      entity_id: !input light
                    alias: Toggle light power

Install

  1. Click the “Import Blueprint” butto above and follow the on-screen instructions to import the blueprint into your Home Assistant.
  2. Create the four required helpers:
    • Create a new “Number” helper to keep track of the current mode the dial is in (suggested name: Dial Mode Tracker):
      • Minimum value: 1
      • Maximum value: 4
      • Step size: 1
    • Create a new “Number” helper to keep track of the current RGB color index for the light’s color (suggested name: Dial Color Tracker):
      • Minimum value: 0
      • Maximum value: 1530
      • Step size: 1
    • Create a new “Number” helper to keep track of the current brightness level for the light (suggested name: Dial Brightness Tracker):
      • Minimum value: 0
      • Maximum value: 255
      • Step value: 1
    • Create a new “Number” helper to keep track of the current hue for the light (suggested name: Dial Hue Tracker) (
      • NOTE: These values are based on most typical RGB-capable lights. Your lights may have a different minimum or maximum; adjust these values accordingly
      • Minimum value: 2000
      • Maximum value: 6500
      • Step size: 1
  3. Create a new automation using the blueprint (Settings → Automations & Scenes → “Create Automation” → Select “ERS Rotary Dial - Light Control” from the list)
    1. Light: Select the light or light group entity you wish to control.
    2. Rotary dial: Select the ERS rotary dial you wish to use to control the lights.
    3. Mode tracker: Select the mode tracker helper you made in the previous step.
    4. Color tracker: Select the color tracker helper you made in the previous step.
    5. Hue tracker: Select the hue tracker helper you made in the previous step.
    6. Brightness tracker: Select the brightness tracker helper you made in the previous step.

Usage

Click the center button on the dial device to switch between the four available modes (brightness, hue, color, off).

Rotating the dial to the left or the right in any mode (other than off) will update the lights.

Behind the scenes, the helpers will also be updated. Do not edit the helpers manually!

Holding down the center button on the dial device will toggle the lights on and off (this only works on the Zigbee2MQTT variant).

Brightness Mode

The target light’s brightness will increase/decrease between 0 (minimum) and 255 (maximum). You can go from minimum to maximum in two full rotations of the dial.

Hue Mode

The target light’s hue will increase/decrease between 2000 (cold) (minimum) and 6500 (warm) (maximum). You can go from minimum to maximum in two full rotations of the dial.

Color Mode

The target light’s color will change, looping through all RGB values in rainbow order, looping back around when you reach the minimum or maximum value.

image

You can go from minimum (left) to maximum (right) in three full rotations of the dial.

Off Mode

Rotating the dial does nothing. This mode acts as a safety to prevent accidental rotations.

Warning

The ERS dial is capable of acting in two different modes: COMMAND and EVENT. You can toggle between these modes by triple-pressing the center button on the device.

  • For the ZHA blueprint, the device must be in COMMAND mode.
  • For the Zigbee2MQTT blueprint, the device must be in COMMAND mode.

If you notice your automation is not being triggered, please try switching the mode.

Release History:

1.0.0 (July 23, 2023):

  • Initial release

1.0.1 (August 4, 2023):

  • Fix bug making it impossible to switch modes due to expected parameters missing.

1.1.0 (August 15, 2023):

  • Add Zigbee2MQTT variant
  • Remove inaccessible double-click functionality in ZHA variant
  • Clean up command and parameter calculations

1.2.0 (August 23, 2023):

  • Use COMMAND mode instead of EVENT mode for Z2M variant

1.3.0 (September 25, 2023):

  • Change trigger for Z2M variant
5 Likes

Is it possible to get a Blueprint for Zigbee2MQTT as opposed to ZHA?

Y’all Z2M people are abundant, lol. Every day I doubt my choice to embrace ZHA when I started.

I’m working on determining the Z2M codes for it, and I’ll see what I can do.

3 Likes

I’ll be honest, I have no idea which is better or worse. I just choose a direction and went for it. It was my understanding there was wider support for devices via Z2M, as opposed to ZHA, but again that was just from reading around. Thank you for adapting this to work. I’ve had the ERS Dial for a while and wasn’t impressed because it was pretty slow response. I’m hoping this will work better and faster. Thanks again for your work! Love the HA community!

Mode switching does not work

Can you provide more details?

Since you’ve been using the dial on Z2M for a while now, can you confirm that these mappings are correct?

https://www.zigbee2mqtt.io/devices/ERS-10TZBVK-AA.html

If so, I can port the blueprint to Z2M pretty easily.

I’m out of town until late next week. If someone doesn’t get to it beforehand, I will test late next week for you.

1 Like

@nwithan8 These are the commands I’m seeing from the device after testing.

brightness_step_up
brightness_step_down
toggle
hue_move
hue_stop
color_temperature_step_up
color_temperature_step_down

1 Like

Thanks. Will mess with it this weekend.

I found a bug that was stopping modes from switching, which has been fixed if you re-import the blueprint. No changes needed to the configuration.

I have added a Z2M variant to the script in the original post. I don’t have Z2M personally, so it’s untested. If you don’t mind being a guinea pig, let me know how it works!

Hi, so I tested this, but you can’t actually add the dial as shown below.

I think this is the issue.

dial:
  name: Rotary dial
  description: Select the rotary dial you wish to use to control the light
  selector:
    device:
      filter:
        integration: zha
        model: TS004F

I changed this to the following for now, but probably should have the right filter on there (sorry I’m not great at changing these so I’m not sure how to do that)

dial:
  name: Rotary dial
  description: Select the rotary dial you wish to use to control the light
  selector:
    entity:
      integration: mqtt

Once I got that in place, it still doesn’t fire when using the ERS Dial. I think the issue is probably, but I have no idea how to change this part :frowning:

trigger:

  • platform: event
    event_type: zha_event
    event_data:
    device_id: !input dial

My apologies for not knowing how to help more with this. Sorry still new to some of this stuff. Thanks again for your help!

Oops, yep, you’re right! Working on the fix now!

Hey, I’ve updated the Z2M script to actually listen for Z2M events now, thanks for the catch.

No gaurantees it works, looked at some other popular Z2M blueprints to get a sense of how to handle Z2M triggers, looks like it’s pretty chaotic.

If you could try it out and let me know, that’d be great!

Hey we made some progress here, but as you suspected still not quite right :slight_smile: . The automation is triggering at least now. I’ll do my best to include what I’m seeing, but I’m sure you might need something else. Let me know what I can provide to help. This isn’t necessarily all the same timeframe, but hopefully these messages will help with what is being sent/received. If you need something else, please let me know and I’ll try to get it for you.

MQTT Explorer Messages
{“level”:“info”,“message”:“MQTT publish: topic ‘zigbee2mqtt/SmartKnob’, payload ‘{“action”:“rotate_right”,“action_rate”:null,“action_step_size”:null,“action_transition_time”:null,“battery”:71,“linkquality”:83,“operation_mode”:“event”,“voltage”:2800}’”}

{“level”:“info”,“message”:“MQTT publish: topic ‘zigbee2mqtt/SmartKnob’, payload '{“action”:”",“action_rate”:null,“action_step_size”:null,“action_transition_time”:null,“battery”:71,“linkquality”:83,“operation_mode”:“event”,“voltage”:2800}’"}

{“level”:“info”,“message”:“MQTT publish: topic ‘zigbee2mqtt/SmartKnob/action’, payload ‘rotate_right’”}

{“action”:"",“action_rate”:null,“action_step_size”:null,“action_transition_time”:null,“battery”:71,“linkquality”:72,“operation_mode”:“event”,“voltage”:2800}

Zigbee2MQTT Logs
2023-08-17 08:54:14Received Zigbee message from 'SmartKnob', type 'raw', cluster 'genOnOff', data '{"data":[1,120,252,0],"type":"Buffer"}' from endpoint 1 with groupID 0

Info 2023-08-17 08:54:14MQTT publish: topic 'zigbee2mqtt/SmartKnob', payload '{"action":"rotate_right","action_rate":null,"action_step_size":null,"action_transition_time":null,"battery":71,"linkquality":51,"operation_mode":"event","voltage":2800}'

Info 2023-08-17 08:54:14MQTT publish: topic 'zigbee2mqtt/SmartKnob', payload '{"action":"","action_rate":null,"action_step_size":null,"action_transition_time":null,"battery":71,"linkquality":51,"operation_mode":"event","voltage":2800}'

Info 2023-08-17 08:54:14MQTT publish: topic 'zigbee2mqtt/SmartKnob/action', payload 'rotate_right'

Debug 2023-08-17 08:54:15Received Zigbee message from 'SmartKnob', type 'raw', cluster 'genOnOff', data '{"data":[1,120,252,0],"type":"Buffer"}' from endpoint 1 with groupID 0

Cool. this will be very helpful, thanks!

So, I figured out where in my blueprint there’s a bug, has to do with how I’m attempting to grab the rotation distance.

That said, even if I fix it, the fact that these values are null on a rotation means the automation basically won’t do anything.

"action_rate":null,"action_step_size":null,"action_transition_time":null,

Do the payloads change if you put the device in a different COMMAND/EVENT mode (triple-click the center button quickly)?

Ni Nate, so I tested this a number of different ways, event vs command, dropping the device and re-adding it but those values are always null. I’m not sure if anyone else might have suggestions, but everything I’ve tried, those values are always null :frowning:

I found another blueprint that uses this device, going to steal their code, lol: