ZHA Double (and Triple) Click Experiments

Original title: “IKEA Trådfri Remote: ZHA Double (and Triple) Click”
I updated the title after sharing the results of my Xiaomi remote experiments.


I recently picked up an IKEA Trådfri Remote to try out. My computer is in the Living Room and I thought it would be nice to have a multi function remote to manage the fan and lights around me. After watching the zha_event logs I determined that I could get 9 functions out of the 5 button remote. 5 single clicks plus 4 long presses.

Unfortunately, zha_event was not capturing an event for double clicks like my Xiaomi double switches do. I kept thinking there might be a way to capture clicks say a half second apart. As it turns out part of the trick was to delay the single click action by a half second to allow a chance for a second click to be detected!

Anyway, if you are interested in learning more about how I did it, I go into a lot of detail in an article on my blog (link below).

You can find full versions of my automation and script at the links below. My full automation handles multiple remotes instead of just the one in the below example.

5 Likes

Today I sat down with a spare Xiaomi Aqara Wireless Mini Switch. It is the square one with a single button in the middle.

I attempted to recreate the multi-click success, but there seems to be a delay in the button presses being received by ZHA. The delay is long enough that I cannot consistently time the button presses to detect a double click. I even tried extending the delay from 1/2 a second to 2 seconds. Slowing my click rate down did not work. Speeding up my click rate didn’t work.

In the end the timing window for this Xiaomi button is just too narrow to make a double click on this button useful. I doubt any other Xiaomi battery powered buttons would work any differently, so I am going to end the Xiaomi button experiment here.

Let me know if you use this technique successfully any other ZHA buttons!

Tradfri 5 button remote update:

In my article I only tried capturing multi-click on the center button. I wanted to let you know that it also works on the other 4 buttons as well! This means we can use this remote for a practically unlimited number of actions.

So now we can use this remote for:

  • 5 single click actions
  • 4 long press actions
  • 5 double click actions
  • 5 triple click actions
  • etc.

For example, I setup my top and bottom buttons to:

  • 1 click = turn on/off primary lamp
  • 2 clicks = turn on/off table lamp
  • Long press up = increase primary and/or table lamp brightness by 20%
  • Long press down = decrease primary and/or table lamp brightness by 20%

I was eyeing the Ikea remote to control stuff in my living room (that’s not yet implemented but it’s in my head) and this is just perfect! Thank you.
PS: Also great to see what can actually be done with automations

1 Like

I don’t think I realized how game changing the new choose and mode features were going to be until now! I believe this could not have been accomplished sooner without custom Python code! :slight_smile:

This is exactly what I set out looking for!

I have a couple Ikea bulbs with toggle switches, and most of the time find it pretty annoying that the bulbs turn back on to their previous light level. A double-click for full brightness would be perfect.

Any suggestion for max length for input_text.zha_click?

1 Like

I felt like 0.5 seconds was a reasonable for delay between clicking a butting once to turn on a light and the light actually turning on. Much longer and you would be feeling impatient. You may have a use case for extending that delay, so give it a try and see how a single click feels.

Not the delay, the max text length of the field where the click info is stored. HA defaults it to 100, but I was guessing that’s probably too short. I changed it to 1000, but don’t really even know if I’m in the right ballpark. I’m guessing it depends on how many switches will be using it.

I had an epiphany! I was making this code more complex that I needed to. By using a counter entity, and assuming I am unlikely to be taping multiple ZHA buttons within a half second of each other, I got rid of the complex input_text field.

Here is my improved code for my three remotes!

automation:
  alias: ZHA Button Click
  id: zha_button_click
  initial_state: true
  mode: restart # Force restart to pickup double click
  max_exceeded: silent
  trigger:
    platform: event
    event_type: zha_event
  action:
    # Increment the counter then delay 0.5 second to allow for a second click to cancel the second action.
    - service: counter.increment
      entity_id: counter.zha_button_click
    - delay:
        seconds: 0.5

    # Store the click count and reset the counter.
    - variables:
        click_count: '{{ states("counter.zha_button_click") }}'
    - service: counter.reset
      entity_id: counter.zha_button_click

    # Retrieve the remaining values needed to determine which action was requested.
    - variables:
        remotes:
          # Ikea
          "ec:1b:bd:ff:fe:23:9c:ee": "remote_family_room"
      
          # Xiaomi
          "00:15:8d:00:01:2d:d7:c3": "button_printer_power"
          "00:15:8d:00:02:83:e2:b6": "remote_bedroom_double_rocker"
        manufacturers:
          "ec:1b:bd:ff": "ikea"
          "00:15:8d:00": "xiaomi"

        device_ieee: '{{ trigger.event.data.device_ieee }}'

        manufacturer: '{{ manufacturers[device_ieee[0:11]] }}'
        remote: '{{ remotes[device_ieee] }}'
        click_count: |
          {% if manufacturer == "xiaomi" %}
            {%- set count = trigger.event.data.args.value %}
            {%- if count == False or count is not number %}
              {{- 0 }}
            {%- else %}
              {{ count|int }}
            {%- endif %}
          {% else %}
            {{ click_count }}
          {%- endif %}
        # Removed '(manufacturer == "xiaomi" and click_count == 0) to make printer button work.'
        command: |
          {% set command = trigger.event.data.command %}
          {%- if (manufacturer == "hue" and command == "step")
              or (manufacturer == "ikea" and command == "checkin")
              or remote|trim == "" %}
            {%- set command = "ignore" %}
          {%- endif %}
          {{- command }}
        command_modifier: |
          {% if manufacturer == "ikea" %}
            {{ trigger.event.data.args[0] }}
          {%- endif %}

    # Only take action for commands other than "ignore".
    - choose:
        - conditions: '{{ command != "ignore" }}'
          sequence:
            # Take the requested action!
            - service: script.zha_button_actions
              data:
                click_count: '{{ click_count }}'
                command: '{{ command }}'
                command_modifier: '{{ command_modifier }}'
                manufacturer: '{{ manufacturer }}'
                remote: '{{ remote }}'

script:
  zha_button_actions:
    sequence:
      - choose:
          # Printer Power Button
          #   * Xiaomi Mijia Wireless Switch (round)
          - conditions: '{{ remote == "button_printer_power" }}'
            sequence:
              - service: switch.toggle
                entity_id: switch.printers

          # Family Room 5 button remote
          #   * IKEA Tradfri Remote Control
          - conditions: '{{ remote == "remote_family_room" }}'
            sequence:
              - choose:
                  # Button: Power (middle)
                  - conditions:
                      - condition: template
                        value_template: '{{ command == "toggle" }}'
                    sequence:
                      - choose:
                          # Single Click
                          - conditions: '{{ click_count == 1 }}'
                            sequence:
                              # Toggle the fan.
                              - service: fan.toggle
                                entity_id: fan.family_room
                          # Double click
                          - conditions: '{{ click_count == 2 }}'
                            sequence:
                              - service: switch.toggle
                                entity_id: switch.tv_family_room
                          # Triple click
                          - conditions: '{{ click_count == 3 }}'
                            sequence:                        
                              - choose:
                                  # The door is locked
                                  - conditions: '{{ states("lock.front_door")|lower|trim == "locked" }}'
                                    sequence:
                                      - service: lock.unlock
                                        entity_id: lock.front_door
                                      
                                      - service: input_boolean.turn_on
                                        entity_id: input_boolean.leave_unlocked
                                # The door is unlocked
                                default:
                                  - service: input_boolean.turn_off
                                    entity_id: input_boolean.leave_unlocked
                                  
                                  - service: lock.lock
                                    entity_id: lock.front_door
                          # Quadruple Click
                          - conditions: '{{ click_count == 4 }}'
                            sequence:
                              - service: input_boolean.toggle
                                entity_id: input_boolean.guest_mode

                  # Brightness Up (top)
                  - conditions: '{{ command == "step_with_on_off" }}'
                    sequence:
                      - choose:
                          # Single Click
                          - conditions: '{{ click_count == 1 }}'
                            sequence:
                              - service: light.turn_on
                                data:
                                  entity_id: light.family_room
                                  brightness_pct: 100
                          # Double click
                          - conditions: '{{ click_count == 2 }}'
                            sequence:
                              - service: light.turn_on
                                data:
                                  entity_id: light.table_lamp
                                  brightness_pct: 100

                  # Brightness down (bottom)
                  - conditions: '{{ command == "step" }}'
                    sequence:
                      - choose:
                          # Single Click
                          - conditions: '{{ click_count == 1 }}'
                            sequence:
                              - service: light.turn_off
                                entity_id:
                                  - light.family_room
                                  - light.table_lamp
                          # Double click
                          - conditions: '{{ click_count == 2}}'
                            sequence:
                              - service: light.turn_off
                                entity_id: light.table_lamp

                  ###############################
                  # SINGLE CLICK / HOLD BUTTONS #
                  ###############################

                  # Single Click: Arrow left (right)
                  - conditions: '{{ command == "press" and command_modifier == 256 }}'
                    sequence:
                      - service: light.turn_on
                        data:
                          entity_id: light.family_room_floor_lamp
                          brightness_pct: 100
                  # Single Click: Arrow right (left)
                  - conditions: '{{ command == "press" and command_modifier == 257 }}'
                    sequence:
                      - service: light.turn_off
                        entity_id: light.family_room_floor_lamp

                  # Hold: Brightness Up (top)
                  - conditions: '{{ command == "move" }}'
                    sequence:
                      - service: light.turn_on
                        data:
                          entity_id:
                            - light.family_room
                            - light.table_lamp
                          brightness_step_pct: "-20"
                  # Hold: Brightness down (bottom)
                  - conditions: '{{ command == "move_with_on_off" }}'
                    sequence:
                      - service: light.turn_on
                        data:
                          entity_id:
                            - light.family_room
                            - light.table_lamp
                          brightness_step_pct: "20"
                  # Hold: Arrow left (left)
                  - conditions: '{{ command == "hold" and command_modifier == 3329 }}'
                    sequence:
                      - service: light.turn_on
                        data:
                          entity_id: light.family_room_floor_lamp
                          brightness_step_pct: "-20"
                  # Hold: Arrow right (right)
                  - conditions: '{{ command == "hold" and command_modifier == 3328 }}'
                    sequence:
                      - service: light.turn_on
                        data:
                          entity_id: light.family_room_floor_lamp
                          brightness_step_pct: "20"

          # Bedroom Double Switch
          #   * Xiaomi Double Rockers, Battery Powered
          - conditions: '{{ remote == "remote_bedroom_double_rocker" }}'
            sequence:
              - choose:
                  # Single Click: Left
                  - conditions: '{{ command == "left_single" }}'
                    sequence:
                      - service: light.toggle
                        entity_id: light.bedroom
                  # Single Click: Right
                  - conditions: '{{ command == "right_single" }}'
                    sequence:
                      - service: light.toggle
                        entity_id: light.brian
                  # Single Click: Both
                  - conditions: '{{ command == "both_single" }}'
                    sequence:
                      - service: light.toggle
                        entity_id: light.glowforge
                  # Double Click: Left
                  - conditions: '{{ command == "left_double" }}'
                    sequence:
                      - service: switch.toggle
                        entity_id: switch.sound_machine
                  # Double Click: Right
                  - conditions: '{{ command == "right_double" }}'
                    sequence:
                      - service: switch.toggle
                        entity_id: switch.bedroom_fan
                  # Double Click: Both
                  - conditions: '{{ command == "both_double" }}'
                    sequence:
                      - service: switch.toggle
                        entity_id:
                          - switch.sound_machine
                          - switch.bedroom_fan

Just to be clear:
ZHA integration so no additional hub or gateway is required for this integration, is it correct?
I’m currently using Conbee II for all my zigbee integrations, it would be great to use it for this remote, too.
Thanks!
-f

I am also using a Conbee II with the ZHA integration. I think that answers your question.

1 Like