Philips Hue Tap Dial Switch - ZHA

After further sleepless nights of meddling with the blueprint I finally came up with a solution that works:

  - choose:
      - conditions:
          - "{{ command == 'recall' }}"
          - "{{ scene == 1 }}"
        sequence:
          - choose:
              - conditions:
                  - "{{ expand(first_light.entity_id) | selectattr('state', '==', 'on') | list | count > 0 }}"
                  - "{{ expand(current_light) | selectattr('state', '!=', 'first_light') | list | count > 0 }}"
                sequence:
                  - service: input_text.set_value
                    target:
                      entity_id: !input "current_light"
                    data:
                      value: first_light
              - conditions:
                  - "{{ expand(first_light.entity_id) | selectattr('state', '==', 'on') | list | count > 0 }}"
                sequence:
                  - service: homeassistant.turn_off
                    target: !input "first_light"
              - conditions:
                  - "{{ expand(first_light.entity_id) | selectattr('state', '==', 'off') | list | count > 0 }}"
                sequence:
                  - service: input_text.set_value
                    target:
                      entity_id: !input "current_light"
                    data:
                      value: first_light
                  - service: homeassistant.turn_on
                    target: !input "first_light"      
1 Like

I tried to look at adapting this blueprint for zigbee2mqtt myself, and I’m pretty stumped right now.

Here is the zigbee2mqtt documentation page for the Phillips Hue Tap Dial. Quoting from there:

Action (enum)
Triggered action (e.g. a button click). Value can be found in the published state on the action property. It’s not possible to read (/get) or write (/set) this value. The possible values are: button_1_press, button_1_press_release, button_1_hold, button_1_hold_release, button_2_press, button_2_press_release, button_2_hold, button_2_hold_release, button_3_press, button_3_press_release, button_3_hold, button_3_hold_release, button_4_press, button_4_press_release, button_4_hold, button_4_hold_release, dial_rotate_left_step, dial_rotate_left_slow, dial_rotate_left_fast, dial_rotate_right_step, dial_rotate_right_slow, dial_rotate_right_fast.

So for example, I have a HA entity called sensor.hue_tap_dial_1_action - and the state value for that is initially empty. When I press the first button on the Hue tap dial, the state value gets set to button_1_press, then when I release the button it changes to button_1_release, before going back to empty.

Here is a sample HA event for pressing button 1, which I got from the Developer Tools → Events page in HA:

event_type: state_changed
data:
  entity_id: sensor.hue_tap_dial_1_action
  old_state:
    entity_id: sensor.hue_tap_dial_1_action
    state: button_1_press_release
    attributes:
      icon: mdi:gesture-double-tap
      friendly_name: hue_tap_dial_1_action
    last_changed: "2022-12-26T10:36:36.960161+00:00"
    last_updated: "2022-12-26T10:36:36.960161+00:00"
    context:
      id: 01GN702XQ0Q3TB3WTPDTB2ZWDA
      parent_id: null
      user_id: null
  new_state:
    entity_id: sensor.hue_tap_dial_1_action
    state: ""
    attributes:
      icon: mdi:gesture-double-tap
      friendly_name: hue_tap_dial_1_action
    last_changed: "2022-12-26T10:36:36.964282+00:00"
    last_updated: "2022-12-26T10:36:36.964282+00:00"
    context:
      id: 01GN702XQ4V999W8Y59DRBJMJP
      parent_id: null
      user_id: null
origin: LOCAL
time_fired: "2022-12-26T10:36:36.964282+00:00"
context:
  id: 01GN702XQ4V999W8Y59DRBJMJP
  parent_id: null
  user_id: null

And here is the HA event for turning the dial left one notch:

event_type: state_changed
data:
  entity_id: sensor.hue_tap_dial_1_action
  old_state:
    entity_id: sensor.hue_tap_dial_1_action
    state: dial_rotate_left_step
    attributes:
      icon: mdi:gesture-double-tap
      friendly_name: hue_tap_dial_1_action
    last_changed: "2022-12-26T15:09:25.015705+00:00"
    last_updated: "2022-12-26T15:09:25.015705+00:00"
    context:
      id: 01GN7FPE4QPXCKAVCPMCMGDV71
      parent_id: null
      user_id: null
  new_state:
    entity_id: sensor.hue_tap_dial_1_action
    state: ""
    attributes:
      icon: mdi:gesture-double-tap
      friendly_name: hue_tap_dial_1_action
    last_changed: "2022-12-26T15:09:25.016821+00:00"
    last_updated: "2022-12-26T15:09:25.016821+00:00"
    context:
      id: 01GN7FPE4RP928XG1NJP6C35GZ
      parent_id: null
      user_id: null
origin: LOCAL
time_fired: "2022-12-26T15:09:25.016821+00:00"
context:
  id: 01GN7FPE4RP928XG1NJP6C35GZ
  parent_id: null
  user_id: null

In this case, it seems that there isn’t the rich command, args, or params fields that your blueprint refers to.

Are those all special fields that get generated by ZHA for the Hue tap dial?

You wouldn’t have any idea on how to adapt your blueprint to suit these types of state_changed events, would you?

(I did see somebody else has a blueprint for the Hue tap dial and zigbee2mqtt here - however, the functionality is quite basic, and doesn’t have your cool “turn the dial to dim the last toggled light”, which I really want…).

You’ve got the events there. So it should be nearly as simple as changing the variable templates in my blueprint to instead match the makeup of these event objects you’ve posted. Then some adjustments on the “command” being looked for in the conditions would need to change. Looks like the state from your events should be mapped to that.

Thanks for getting back!

I might just be tired, and not thinking straight, aha. Hmm, do you happen to have a sample event from ZHA please?

I’m trying to understand this stanza in the blueprint:

action:
  - variables:
      command: "{{ trigger.event.data.command }}"
      args: "{{ trigger.event.data.args }}"
      params: "{{ trigger.event.data.params }}"
      scene: "{{ trigger.event.data.params.scene_id }}"
      step_mode: "{{ trigger.event.data.params.step_mode }}"
      step_size: "{{ trigger.event.data.params.step_size }}"

It seems ZHA returns things like step_mode and step_size, right?

What is the scene_id and args for?

event_type: zha_event
data:
  device_ieee: 00:17:88:01:0d:34:95:cd
  unique_id: 00:17:88:01:0d:34:95:cd:1:0x0005
  device_id: d09f3e60cc9ff0c98b50d7c41d984bad
  endpoint_id: 1
  cluster_id: 5
  command: recall
  args:
    - 51109
    - 1
  params:
    group_id: 51109
    scene_id: 1
    transition_time: null
origin: LOCAL
time_fired: "2022-12-27T16:57:43.210087+00:00"
context:
  id: 01GNA89F1ANDZTQK09870B02BW
  parent_id: null
  user_id: null

scene_id has to be used to get which button was pressed
args I thought would enable me to get long-press, double-press etc, but it didn’t. In the final version it is unused, just wasn’t removed from the variables section.
step_mode tells if it is clockwise or counterclockwise rotation
step_size corresponds to the velocity of the turn, which gets used to increment/decrement the brightness

The event above is just of a button press so it does not contain the step_size and step_mode

Hi, i’m also new to this topic, maye i just missed a post with the answer, but here es my question:

Has anybody figured out how to determine “hold, log_press” or “double_tab” ?

In ZHA it doesn’t seem to be possible. But in MQTT it seems enough information is sent to be able to handle that. See the last few posts for more on that.

@apollo1220 Would you be able to add some sample events from the jog dial please? (e.g. turning the dial, fast/slow etc.).

event_type: zha_event
data:
  endpoint_id: 1
  cluster_id: 8
  command: step_with_on_off
  args:
    - 0
    - 8
    - 4
  params:
    step_mode: 0
    step_size: 8
    transition_time: 4
origin: LOCAL
context:
  parent_id: null
  user_id: null
event_type: zha_event
data:
  endpoint_id: 1
  cluster_id: 8
  command: step_with_on_off
  args:
    - 1
    - 14
    - 4
  params:
    step_mode: 1
    step_size: 14
    transition_time: 4
origin: LOCAL
context:
  parent_id: null
  user_id: null

Hello everyone…i’m a newbie, could be possible to have an automation exemple without a blueprint?

Hey everyone, is it possible to modify this so it works with the hue bridge not ZHA? Since the new hue API provides more info.

Thank you.

Likely it could be possible. Don’t have a bridge, so can’t try it.

1 Like

Here is my take on the blueprint evolution:

  • If the light is off, a click will turn it on at 50%.
  • If the light is on, then clicking will turn it off only if that is the current light; otherwise, you have to click twice – once to select the current light, the second time to turn it off.
  • Rotation normally dims the current light.
blueprint:
  name: Philips Tap Dial Switch
  description: 'Control lights with a Philips Hue Tap Switch. Use the four buttons
    to control up to four light(s) with an on/off toggle. The dial can be used to
    dim the most recently used light. '
  domain: automation
  input:
    remote:
      name: Philips Hue Tap Switch
      selector:
        device:
          integration: zha
          manufacturer: Signify Netherlands B.V.
          model: RDM002
          multiple: false
    first_light:
      name: First Light
      description: The light(s) to control with first button
      selector:
        target:
          entity: {}
    second_light:
      name: (OPTIONAL) Second Light
      description: The light(s) to control with second button
      default: {}
      selector:
        target:
          entity: {}
    third_light:
      name: (OPTIONAL) Third Light
      description: The light(s) to control with third button
      default: {}
      selector:
        target:
          entity: {}
    forth_light:
      name: (OPTIONAL) Forth Light
      description: The light(s) to control with forth button
      default: {}
      selector:
        target:
          entity: {}
    current_light:
      name: (OPTIONAL) Current Light
      description: Text helper to track the current light to dim. Set for the dimmer
        controls to change which light they are controlling according to the last
        one turned on.
      default:
      selector:
        entity:
          domain: input_text
          multiple: false
    dim_scale:
      name: Diming Scale
      description: Scale factor for the dimming. This value will be multiplied by
        the value given from the dial. So lower number, more gradual dimming. Larger
        number, faster dimming.
      default: 1.0
      selector:
        number:
          min: 0.0
          max: 5.0
          step: 0.01
          mode: slider
  source_url: https://github.com/apollo1220/blueprints/blob/c588e4143f880b95b46791d6977f29bdac9cfc88/philips_zigbee_dial.yaml
mode: restart
max_exceeded: silent
variables:
  first_light: !input first_light
  second_light: !input second_light
  third_light: !input third_light
  forth_light: !input forth_light
  current_light: !input current_light
  dim_scale: !input dim_scale
  lights:
    first_light: !input first_light
    second_light: !input second_light
    third_light: !input third_light
    forth_light: !input forth_light
trigger:
- platform: event
  event_type: zha_event
  event_data:
    device_id: !input remote
action:
- variables:
    command: '{{ trigger.event.data.command }}'
    args: '{{ trigger.event.data.args }}'
    params: '{{ trigger.event.data.params }}'
    scene: '{{ trigger.event.data.params.scene_id }}'
    step_mode: '{{ trigger.event.data.params.step_mode }}'
    step_size: '{{ trigger.event.data.params.step_size }}'
- choose:
  - conditions:
    - '{{ command == ''recall'' }}'
    - '{{ scene == 1 }}'
    sequence:
      - choose:
        - conditions: '{{ states(first_light.entity_id) == ''off'' }}'
          sequence:
          - service: light.turn_on
            target: '{{ first_light }}'
            data:
              transition: 1
              brightness: 50
        default:
          - choose:
            - conditions: '{{ states(current_light) == ''first_light'' }}'
              sequence:
              - service: light.turn_off
                target: '{{ first_light }}'
      - choose:
        - conditions: '{{ current_light != none }}'
          sequence:
          - service: input_text.set_value
            target:
              entity_id: !input current_light
            data:
              value: '{{ ''first_light'' }}'
  - conditions:
    - '{{ command == ''recall'' }}'
    - '{{ second_light != none }}'
    - '{{ scene == 0 }}'
    sequence:
      - choose:
        - conditions: '{{ states(second_light.entity_id) == ''off'' }}'
          sequence:
          - service: light.turn_on
            target: '{{ second_light }}'
            data:
              transition: 1
              brightness: 50
        default:
          - choose:
            - conditions: '{{ states(current_light) == ''second_light'' }}'
              sequence:
              - service: light.turn_off
                target: '{{ second_light }}'
      - choose:
        - conditions: '{{ current_light != none }}'
          sequence:
          - service: input_text.set_value
            target:
              entity_id: !input current_light
            data:
              value: '{{ ''second_light'' }}'
  - conditions:
    - '{{ command == ''recall'' }}'
    - '{{ third_light != none }}'
    - '{{ scene == 5 }}'
    sequence:
      - choose:
        - conditions: '{{ states(third_light.entity_id) == ''off'' }}'
          sequence:
          - service: light.turn_on
            target: '{{ third_light }}'
            data:
              transition: 1
              brightness: 50
        default:
          - choose:
            - conditions: '{{ states(current_light) == ''third_light'' }}'
              sequence:
              - service: light.turn_off
                target: '{{ third_light }}'
      - choose:
        - conditions: '{{ current_light != none }}'
          sequence:
          - service: input_text.set_value
            target:
              entity_id: !input current_light
            data:
              value: '{{ ''third_light'' }}'
  - conditions:
    - '{{ command == ''recall'' }}'
    - '{{ forth_light != none }}'
    - '{{ scene == 4 }}'
    sequence:
      - choose:
        - conditions: '{{ states(forth_light.entity_id) == ''off'' }}'
          sequence:
          - service: light.turn_on
            target: '{{ forth_light }}'
            data:
              transition: 1
              brightness: 50
        default:
          - choose:
            - conditions: '{{ states(current_light) == ''forth_light'' }}'
              sequence:
              - service: light.turn_off
                target: '{{ forth_light }}'
      - choose:
        - conditions: '{{ current_light != none }}'
          sequence:
          - service: input_text.set_value
            target:
              entity_id: !input current_light
            data:
              value: '{{ ''forth_light'' }}'
  - conditions:
    - '{{ command == ''step_with_on_off'' }}'
    - '{{ step_mode == ''StepMode.Up'' }}'
    sequence:
    - choose:
      - conditions: '{{ current_light != none }}'
        sequence:
        - service: light.turn_on
          target: '{{ lights[states(current_light)] }}'
          data:
            brightness_step_pct: '{{ step_size * dim_scale }}'
            transition: 1
      default:
      - service: light.turn_on
        target: !input first_light
        data:
          brightness_step_pct: '{{ step_size * dim_scale }}'
          transition: 1
  - conditions:
    - '{{ command == ''step_with_on_off'' }}'
    - '{{ step_mode == ''StepMode.Down'' }}'
    sequence:
    - choose:
      - conditions: '{{ current_light != none }}'
        sequence:
        - service: light.turn_on
          target: '{{ lights[states(current_light)] }}'
          data:
            brightness_step_pct: '{{ -step_size * dim_scale }}'
            transition: 1
      default:
      - service: light.turn_on
        target: !input first_light
        data:
          brightness_step_pct: '{{ -step_size * dim_scale }}'
          transition: 1

Is it just my setup or does this blueprint not work with (light) scenes?

Is there someone who can explain me how to change this blueprint to function with Z2M integration?

I’ve only tested with lights and switches. If scenes respond to the home_assistant.turn_on and home_assistant.turn_off services then turning on and off should work. But I doubt the diming would work as the light service specifically is called for that.

@victorhooi has a few posts in here working on Z2M with this.

Hi there.

I just got this tap dial switch and it works with switching lights on off.
However i would like to use the dial for controlling the volume level.
Is that possible? I don’t know how to edit the blueprint so i can use the switches for lights and controlling the volume level. Just a noob. Did some one already made such thing working?
Just controlling my volume with the dial seems impossible for me.

You would want to change the part that handles the dial spin which would be this part

      - conditions:
          - "{{ command == 'step_with_on_off' }}"
          - "{{ step_mode == 'StepMode.Up' }}"
        sequence:
          - choose:
              - conditions: "{{ current_light != none }}"
                sequence:
                  - service: light.turn_on
                    target: "{{ lights[states(current_light)] }}"
                    data:
                      brightness_step_pct: "{{ step_size * dim_scale }}"
                      transition: 1
            default:
              - service: light.turn_on
                target: !input "first_light"
                data:
                  brightness_step_pct: "{{ step_size * dim_scale }}"
                  transition: 1
      - conditions:
          - "{{ command == 'step_with_on_off' }}"
          - "{{ step_mode == 'StepMode.Down' }}"
        sequence:
          - choose:
              - conditions: "{{ current_light != none }}"
                sequence:
                  - service: light.turn_on
                    target: "{{ lights[states(current_light)] }}"
                    data:
                      brightness_step_pct: "{{ -step_size * dim_scale }}"
                      transition: 1
            default:
              - service: light.turn_on
                target: !input "first_light"
                data:
                  brightness_step_pct: "{{ -step_size * dim_scale }}"
                  transition: 1

Instead of calling the light service you would want to call the media’s volume service.

Thnx. but cant get it to work.
The blueprint seems fine in file editor but when i make an automation it says not al valid value for dictionary value.

I also tried to delete all the lights in the blueprint and only put in the dial program.
4 hours later and no succes.

What i did get to work is making a zha_events trigger and control the volume.
It does work with all zigbee events so i do need to get te conditions right.
Does anyone knows how to filter out ZHA_events by its parameters and conditions?

UPDATE:

Thank you for inspiring me to make my first and own blueprint!
Never got it working without your blueprint.

Philips HUE Dial Switch - Control actions and volume of your media player - Blueprints Exchange - Home Assistant Community (home-assistant.io)