Proper way to handle multi-press buttons/switches?

What is the correct way to build button/switch automations for devices with multi-press capabilities?

I have a handful of automations setup for buttons and switch paddles for Pressed Once, Pressed Twice, etc., which seem to have broken with one of the recent updates.
I’m guessing this is due to the state automations now actually enforcing the State Change part so they aren’t triggering when the previous button event was the same as the current one.

Since these are multi function buttons, I can’t just use the any status change option, I need to actually define single press, double press, etc., and have them always trigger when that event is sent, not when it’s sent after a different event.

I tried modifying my one button automation in yaml to explicitly include pressed_once as an option for the From state to see if From pressed_once To pressed_once would get around the check, but that didn’t work.

Thanks!

both AI and web search can show you there are many examples. each device will have slightly different system events. You can see on e in my blueprint… 📛 Shelly i4 Button Controller by LTek ... with Single Button Dim & Multi-Press Functions

if you are not a coder, find a blueprint for your device

With button entities or event entities, the way to set up an automation is using a state trigger on the entity which will fire on any state change. Then you add a condition (either a template condition or an entity state condition) that will check whether the attributes of the entity match whatever you are looking for.

You need to be aware of edge cases such as after a restart when the entity might change state from unavailable to an older state, and so that needs to be accounted for as well.

One common method is to avoid all triggers that are transitions from or to unavailable/unknown states:

triggers:
  - trigger: state
    entity_id:
      - event.light_scene_001
    not_from:
      - unavailable
      - unknown
    not_to:
      - unavailable
      - unknown
conditions:
  - alias: Event was KeyPressed2x
    condition: template
    value_template: "{{ trigger.to_state.attributes.event_type == 'KeyPressed2x' }}"
actions:
  - <actions go here>

Another option is just checking that the state of the button or event (which will be a timestamp of when that event happened) is within a few seconds of right now:

triggers:
  - trigger: state
    entity_id:
      - event.light_scene_001
conditions:
  - alias: State change was within last 5 seconds
    condition: template
    value_template: >-
      {{ trigger.to_state.state | as_datetime(0|as_datetime) > now() -
      timedelta(seconds=5) }}
  - alias: Event was KeyPressed2x
    condition: template
    value_template: "{{ trigger.to_state.attributes.event_type == 'KeyPressed2x' }}"
actions:
  - <actions go here>

If you are a coder, it’s best just to process the raw events:

ZHA

You can use a single trigger for all buttons on all switches and all press types:

triggers:
  - trigger: event
    event_type: zha_event
    event_data:
      cluster_id: 6

Zigbee2MQTT

You need one trigger for each action topic:

triggers:
  - trigger: mqtt
    options:
      topic: zigbee2mqtt/Living Entry Scene/action
  - trigger: mqtt
    options:
      topic: zigbee2mqtt/Kitchen Entry Scene/action

Note: It might be possible to simplify that using wildcards, I haven’t bothered messing with that.


This is based on the idea that button presses are an event (may not work for buttons which have a release event). Hence you don’t have to mess with states you can just say, when a button press (event) happens - do something.

There is a bunch of extra code needed to figure out how to process each event, but that is going to be specific to your needs.

Here are some more details:

Thanks for the input!
I found a blueprint for my switches (I thought I’d looked before…but apparently not)), so those are good now.
I haven’t found a blueprint for my button, but it’s currently only used for one thing so the catch all change rule is ok for that for now…but maybe when I’ve got some spare time I’ll look at the various linked examples and see if I can figure out how to build one myself.