A simple click and long press button

Hi!
I want to use a single push button to control 2 different devices.
Single click: lighting
Long press: ventilation
HA 2023 on RPI CM4
Configuration help

Here is my yaml code

alias: Mise marche et arret lampe salon
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.cm4_in2
    from: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 0
    to: "on"
condition: []
action:
  - if:
      - condition: state
        entity_id: switch.cm4_relais2
        state: "off"
        for:
          hours: 0
          minutes: 0
          seconds: 0
    then:
      - service: light.turn_on
        data: {}
        target:
          area_id: salon
          entity_id: light.cm4_relais2
    else:
      - service: light.turn_off
        data: {}
        target:
          area_id: salon
          entity_id: light.cm4_relais2
mode: single

`alias: Mise en marche et arret brasseur salon
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.cm4_in3
    from: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 3
    to: "on"
condition: []
action:
  - if:
      - condition: state
        entity_id: switch.cm4_relais3
        state: "on"
    then:
      - service: fan.turn_off
        data: {}
        target:
          area_id: salon
          entity_id: fan.cm4_relais3
    else:
      - service: fan.turn_on
        data: {}
        target:
          area_id: salon
          entity_id: fan.cm4_relais3
mode: single

My problem
simple click the lamp lights up
simple click again the lamp turns off
long press on the same button the fan starts
long press again the fan turns off but the lamp also turns on

I think you are better off creating a button card. Set the entity to your light and the tap action to toggle. Then set your hold action to call service and use switch.toggle service on your switch.cm4_relais3. Like this.

show_name: true
show_icon: true
type: button
tap_action:
  action: toggle
entity: light.cm4_relais2
hold_action:
  action: call-service
  service: switch.toggle
  target:
    entity_id: fan.cm4_relais3

1 Like

You can use a wait for trigger with a timeout to achieve this.

Here’s the gist. Upon the first click, the script will wait 200ms for the second click, if no subsequent click was triggered and the wait times out, it’s considered a single click.

If the second click was triggered during the timeout period, that will be considered a double-click.

You can do the same for triple and long press but the more actions you add the longer the wait has to be, which effectively slows down the response of the button.

See this documentation for more details: Script Syntax - Home Assistant

Note: It should all be in one script.

Not exactly long press, but here’s an example for single click and double click:

Example Automation
alias: Double click
description: ""
trigger:
  - platform: state
    entity_id:
      - input_button.test_button # This captures the first click.
condition: []
action:
  # This waits for the second click or subsequent events.
  - wait_for_trigger: 
      - platform: state
        entity_id:
          - input_button.test_button
    timeout:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: 250
  - if:
      - condition: template
        value_template: "{{ wait.trigger == none }}"
    then:
      - service: notify.mobile_app_minion
        data:
          message: Single click
    else:
      - service: notify.mobile_app_minion
        data:
          message: Double click

# Has to be single, otherwise automation will trigger again in another instance.
mode: single

In your case, you’ll look for specific states in your binary sensor instead of just entity_id. And you’d be able to do long press since your binary sensor knows when it’s let go, you’ll just have to listen to when it turns off for a long press.

Thanks for the example.

Few questions, you used input_button. But how can i make this if i only have a state.node_status that has to change its state.

    type: state.node_status
    entity_id: 12598fea98cf490c26701d3378
    from: asleep
    to: awake
    for:
      hours: 0
      minutes: 0
      seconds: 0

and the second, how does this “resets” the press if there has not been a second press in 10 seconds?

Your first “Then” i should be ending the automation i think.
the “else” i could fire my action.

Could you show what properties are in the entity state.node_status?

You can find the entity in Developer Tools:
Open your Home Assistant instance and show your state developer tools.

If it’s simply the state of the entity, then just change input_button.test_button to state.node_status and add a to: awake condition.

The automation trigger listens for the first click, the second click is handled by the wait_for_trigger.
In both triggers, the entity and to conditions should be the same for you.

You will just have to adjust the timeout to what’s required after setting your trigger conditions.

:warning: Do ensure you’re using an entity - what you provided does not look like an entity. Make sure you find your entity here:
Open your Home Assistant instance and show your entities.

Your right, the first is not an entity.
The entity that can be used is

sensor.temperatuur_sensor_toilet_node_status

And it has the states:

asleep, awake, dead, alive

This is what i have so far,

But i do not understand your value_template why is it set wait.trigger I can not find that back in the automation, should it not be ‘wait_for_trigger’? or is ‘wait.trigger’ a deafault?

alias: Button Test
description: Test
trigger:
  - platform: state
    entity_id:
      - sensor.temperatuur_sensor_toilet_node_status
    from: asleep
    to: awake
condition:
  - condition: device
    type: is_on
    device_id: e5896eecc53466838808e07a9f730b37
    entity_id: 6eb21747e09d725280f7a67442e6ea98
    domain: switch
    for:
      hours: 0
      minutes: 0
      seconds: 5
action:
  - wait_for_trigger:
      - platform: state
        entity_id:
          - sensor.temperatuur_sensor_toilet_node_status
        from: asleep
        to: awake
    timeout:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - if:
      - condition: template
        value_template: "{{ wait.trigger == none }}"
    then:
      - stop: Slechts Ă©Ă©n keer gedrukt binnen 10 seconden.
    else:
      - type: turn_off
        device_id: e5896eecc53466838808e07a9f730b37
        entity_id: 6eb21747e09d725280f7a67442e6ea98
        domain: switch
      - stop: Twee keer gedrukt binnen 10 seconde, actie uitgevoerd.
mode: single

This only registers the first click


The wait variable is set by the wait_for_trigger action


If it time out, wait.trigger will be empty, but if it detects your sensor going to awake during the 10 seconds, wait.trigger will have some details regarding that event.

Therefore, we check for wait.trigger == none, if it is true, then nothing has been pressed after 10 seconds.

Otherwise, there has been a press within the 10 seconds it was waiting, then we treat that as the second click.

P.S. I will recommend that you put the condition into your action, just in case the state of your device is turned off within that 10 seconds buffer, it will not cause a trigger. But what you have will also work.

You can debug more if you run the automation, and check the trace.

1 Like

Thanks! had to remove the last “stop” and it worked.

You meen the check that the device is On in the action?
Will try, but normally the device will not be turned of because i have to remove the battery for that :stuck_out_tongue:

I also have to make a second automation to turn the plug On again when it is Off.
then i normally merge those 2 automations in 1. Will post the complete automation when its ready.

Thanks for the example ! much better than my original idea to make counters and triggers haha.

No problem, glad to hear it worked for you. You can check out some YouTube on using Trigger ID, I like to use trigger ID for case when you need to manage one feature but it requires multiple actions.

Then you can merge the automations seamlessly.

1 Like

noticed one strange thing, i need to press the button 3 times instead of 2. Don’t know why.

Edit: nvm, its 2 now, maybe pressing to fast haha

Yeah wireless button response is slow and sometimes may not register quick enough. I face same issue with ZigBee when the button device can’t do double click natively.

I’m afraid it is not possible,

alias: Button Test Off
description: Test
trigger:
  - platform: state
    entity_id:
      - sensor.temperatuur_sensor_toilet_node_status
    from: asleep
    to: awake
    id: press_turn_off
condition:
  - condition: device
    type: is_on
    device_id: e5896eecc53466838808e07a9f730b37
    entity_id: 6eb21747e09d725280f7a67442e6ea98
    domain: switch
    for:
      hours: 0
      minutes: 0
      seconds: 5
action:
  - wait_for_trigger:
      - platform: state
        entity_id:
          - sensor.temperatuur_sensor_toilet_node_status
        from: asleep
        to: awake
    timeout:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - if:
      - condition: template
        value_template: "{{ wait.trigger == none }}"
    then:
      - stop: Slechts Ă©Ă©n keer gedrukt binnen 10 seconden.
    else:
      - type: turn_off
        device_id: e5896eecc53466838808e07a9f730b37
        entity_id: 6eb21747e09d725280f7a67442e6ea98
        domain: switch
mode: single

alias: Button Test On
description: Test
trigger:
  - platform: state
    entity_id:
      - sensor.temperatuur_sensor_toilet_node_status
    from: asleep
    to: awake
    id: press_turn_on
condition:
  - condition: device
    type: is_off
    device_id: e5896eecc53466838808e07a9f730b37
    entity_id: 6eb21747e09d725280f7a67442e6ea98
    domain: switch
    for:
      hours: 0
      minutes: 0
      seconds: 5
action:
  - wait_for_trigger:
      - platform: state
        entity_id:
          - sensor.temperatuur_sensor_toilet_node_status
        from: asleep
        to: awake
    timeout:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - if:
      - condition: template
        value_template: "{{ wait.trigger == none }}"
    then:
      - stop: Slechts Ă©Ă©n keer gedrukt binnen 10 seconden.
    else:
      - type: turn_on
        device_id: e5896eecc53466838808e07a9f730b37
        entity_id: 6eb21747e09d725280f7a67442e6ea98
        domain: switch
mode: single

My trigger is the same, so it can not get its own trigger_id.
Think i have to stick with 2 separate files

You should put a choose into your action to decide what actions to take based on device state.

In other words, move your condition into the actions using either if-then or choose, and based on device state, decide what has to be done after the second click. (This if-then or choose action should be nested in the current existing one)

That way, one automation can deal with both device is on, and device is off.

It will also make your automation a bit more reliable and responsive as it will not be blocked by the condition.

alias: Temperatuur Sensor Toilet - Press to Turn On/Off IR Paneel Toilet
description: >-
  Zet het IR Paneel Aan en Uit door 2x achter elkaar op de knop van de
  Temperatuur Sensor te drukken.
trigger:
  - platform: state
    entity_id:
      - sensor.temperatuur_sensor_toilet_node_status
    from: asleep
    to: awake
    id: press_button
    enabled: true
condition: []
action:
  - wait_for_trigger:
      - platform: state
        entity_id:
          - sensor.temperatuur_sensor_toilet_node_status
        from: asleep
        to: awake
    timeout:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - choose:
      - conditions:
          - condition: trigger
            id:
              - press_button
            enabled: true
          - condition: state
            entity_id: switch.smart_switch_ir_paneel_toilet
            state: "off"
            for:
              hours: 0
              minutes: 0
              seconds: 5
        sequence:
          - if:
              - condition: template
                value_template: "{{ wait.trigger == none }}"
            then:
              - stop: Slechts Ă©Ă©n keer gedrukt binnen 10 seconden.
            else:
              - type: turn_on
                device_id: e5896eecc53466838808e07a9f730b37
                entity_id: 6eb21747e09d725280f7a67442e6ea98
                domain: switch
      - conditions:
          - condition: trigger
            id:
              - press_button
          - condition: state
            entity_id: switch.smart_switch_ir_paneel_toilet
            state: "on"
            for:
              hours: 0
              minutes: 0
              seconds: 5
        sequence:
          - if:
              - condition: template
                value_template: "{{ wait.trigger == none }}"
            then:
              - stop: Slechts Ă©Ă©n keer gedrukt binnen 10 seconden.
            else:
              - type: turn_off
                device_id: e5896eecc53466838808e07a9f730b37
                entity_id: 6eb21747e09d725280f7a67442e6ea98
                domain: switch
mode: single

:smiley: :smiley:

I will flip the other way, automation check second click first then check device, but if it works, it’s all good :+1:t2:

sounds indeed better haha.

than i have to put the sequence before the condition state from the switch.
and with the “else” i need to do an other check of the switch is On and than the turn_on switch.
Right?

will try later today.