So I have a D1 Mini working as a button with ESPHome.
I’d love to enable a Button Held sensor, and Double Click sensor or something like that.
I see this page in the docs, but how can I make virtual switches for held and double press that turn on when the actions in this page are triggered?
Off the top of my head I would think you need to create a template switch in the ESPhome code with a lambda relating to the held / double click. Not something I have ever tried so I can’t be of any more help unfortunately… but I’m keen to know the answer
I 'm assuming one end of your button is connected to D2 and the other end is connected to ground and your button is a normally open momentary. You need to amend your binary_sensor like so:
You need to specify input_pullup because otherwise when your button isn’t activated the input to the 8266 will float causing spurious signals. With the pullup the input will be at a solid high level. Likewise you need the filter delayed_on to allow the button to settle after it is pushed because the switch contact will bounce for a while and cause spurious signals. Good luck.
Hi, I have created a cover and I would like to add a double press to the push-button so that when I press the push-button twice it automatically closes the relay for the time set in the cover.
I discovered however that on press is not compatible with dual click. There will however be a lambda way of creating this with Lambda actions…
…delays in on_press/on_release and checks before action…
If it’s any help here’s the code I ended up with.
This it toggling input_booleans in HA. It works.
binary_sensor:
- platform: gpio
pin:
number: D4
mode: INPUT_PULLUP
inverted: True
name: "Jackson D4 Button"
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- homeassistant.service:
service: input_boolean.turn_on
data:
entity_id: input_boolean.jackbuttondouble
- timing:
- ON for 1s to 3s
- OFF for at least 0.5s
then:
- homeassistant.service:
service: input_boolean.turn_on
data:
entity_id: input_boolean.jackbuttonheld
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- homeassistant.service:
service: input_boolean.turn_on
data:
entity_id: input_boolean.jackbuttonsingle
Thanks for sharing this, this is a great solution but it’s still quite cumbersome because you have to manually define each state and you end up with multiple input booleans. Is there a way to let EspHome pass the raw data (the ons and offs) and then have HA interpret them like it would for a “physical device”? On a physical device HA seems to recognize the patterns and offer from scratch the hold, single click and double click…
Keith I tried your code and it works fine, with one caveat : you don’t seem to turn the input boolean off in your code here. Are you doing it in HA after calling an automation or something?
This is what I did/ currently busy with. Also ESPHome powered wallswitch;
globals:
- id: counter
type: int
restore_value: no
initial_value: '0'
binary_sensor:
- platform: gpio
id: btn
name: "button test"
pin:
number: D1
mode: INPUT
inverted: false
filters:
- delayed_on: 10ms
- delayed_off: 10ms
internal: true
discovery: false
on_multi_click:
#Double Click
- timing:
- ON for at most 0.5s
- OFF for at most 0.3s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- lambda: |-
id(${text_sensor_id}).publish_state("double");
- delay: 0.5s
- lambda: |-
id(${text_sensor_id}).publish_state("");
#Single Click
- timing:
- ON for at most 0.5s
- OFF for at least 0.5s
then:
- lambda: |-
id(${text_sensor_id}).publish_state("single");
- delay: 0.5s
- lambda: |-
id(${text_sensor_id}).publish_state("");
#Hold
- timing:
- ON for at least 0.75s
then:
- while:
condition:
binary_sensor.is_on: btn
then:
- lambda: |-
id(counter) += 1;
id(${text_sensor_id}).publish_state("hold");
- delay: 0.5s
#Release
- timing:
- ON for at least 1.5s
- OFF for at least 0.5s
then:
- lambda: |-
id(counter) = 0;
id(${text_sensor_id}).publish_state("release");
- delay: 0.5s
- lambda: |-
id(${text_sensor_id}).publish_state("");
#Button
# Notice;
# Home Assistant will handle JSON-payload as a String. Not pretty but it helps with handling incrementation of the count-key while holding button
# For automation I rely on Node-RED, not Home assistant. In Node-RED I've add a JSON-node to convert string into JSON. That works pretty well.
text_sensor:
- platform: template
name: ${text_sensor_name}
icon: "mdi:toggle-switch"
id: ${text_sensor_id}
update_interval: 60s
discovery: true
internal: true #helps with hijacking publishing through mqtt.publish_json. Still sensor is discovered by HA
on_value:
then:
#Hold
- if:
condition:
# Test if state ends with 'hold'
lambda: |-
std::string mainStr = id(${text_sensor_id}).state;
std::string toMatch = "hold";
if(mainStr.size() >= toMatch.size() && mainStr.compare(mainStr.size() - toMatch.size(), toMatch.size(), toMatch) == 0) {
return true;
} else {
return false;
}
then:
- mqtt.publish_json:
topic: ${mqtt_topic}/sensor/${text_sensor_name}/state
payload: |-
root["action"] = id(${text_sensor_id}).state;
root["count"] = id(counter);
else:
#Release
- if:
condition:
# Test if state ends with 'release'
lambda: |-
std::string mainStr = id(${text_sensor_id}).state;
std::string toMatch = "release";
if(mainStr.size() >= toMatch.size() && mainStr.compare(mainStr.size() - toMatch.size(), toMatch.size(), toMatch) == 0) {
return true;
} else {
return false;
}
then:
- mqtt.publish_json:
topic: ${mqtt_topic}/sensor/${text_sensor_name}/state
payload: |-
root["action"] = id(${text_sensor_id}).state;
root["count"] = "";
else:
#Other states
- mqtt.publish_json:
topic: ${mqtt_topic}/sensor/${text_sensor_name}/state
payload: |-
root["action"] = id(${text_sensor_id}).state;
Thanks to your example I made something similar, but slightly simpler. I want HA to cycle through scenes when I hold the button, so it should be sufficient to send out the same MQTT message each time to trigger the same automation. Therefore, I don’t need the text_sensor:
binary_sensor:
- platform: gpio
pin:
number: GPIO5
#mode: INPUT_PULLUP
#inverted: True
name: "Switch Shelly 1"
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 0.5s
- ON for at most 1s
- OFF for at least 0.1s
then:
- logger.log: "Double Clicked"
- mqtt.publish:
topic: shelly1_2/switch/shelly_1_switch/state
payload: "double_click"
- timing:
- ON for at most 1s
- OFF for at most 0.5s
- ON for at most 1s
- OFF for at most 0.5s
- ON for at most 1s
- OFF for at least 0.1s
then:
- logger.log: "Triple Clicked"
- mqtt.publish:
topic: shelly1_2/switch/shelly_1_switch/state
payload: "triple_click"
- timing:
- ON for at least 1s
then:
- while:
condition:
binary_sensor.is_on: switchid
then:
- logger.log: "Single Long Clicked"
- mqtt.publish:
topic: shelly1_2/switch/shelly_1_switch/state
payload: "single_long_click"
- delay: 1s
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- logger.log: "Single Short Clicked"
- mqtt.publish:
topic: shelly1_2/switch/shelly_1_switch/state
payload: "single_click"
- light.toggle: lightid
internal: true
id: switchid
I have taken @keithcroshaw approach and added turning off the input boolean.
“S20-5” is the name of the device, a Sonoff S20 and the 5th in my house now.
I removed the simple on press with the info from this thread.
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: "S20-5 Button"
# on_press:
# - light.toggle: Sonoff_S20_light #or - switch.toggle: s20_relay
on_multi_click:
# double click
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- homeassistant.service:
service: input_boolean.turn_on
data:
entity_id: input_boolean.s20_5_button_double
- delay: 0.2s
- homeassistant.service:
service: input_boolean.turn_off
data:
entity_id: input_boolean.s20_5_button_double
# hold button
- timing:
- ON for 1s to 5s
- OFF for at least 0.5s
then:
- homeassistant.service:
service: input_boolean.turn_on
data:
entity_id: input_boolean.s20_5_button_hold
- delay: 0.2s
- homeassistant.service:
service: input_boolean.turn_off
data:
entity_id: input_boolean.s20_5_button_hold
# single click
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- light.toggle: Sonoff_S20_light
I have added the following to my configuration.yaml
Home Assistant added the Button helper (aka input_button), which simplifies handling of double-clicks compared to the input_boolean solution shown above.
So instead of adding input_boolean entities in configuration.yaml as shown above, I’ve used the UI to add two helper Buttons to handle a click and a double-click: my_button_click and my_button_double_click
Note that to handle double-clicks on a remote_receiver button, like in the example below, you need to add a delayed_off filter.
binary_sensor:
- platform: remote_receiver
name: "My Button"
icon: "mdi:button-pointer"
rc_switch_raw:
protocol: 6
code: "111111111101101001001011"
filters:
- delayed_off: 200ms
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: Double Clicked.
- homeassistant.service:
service: input_button.press
data:
entity_id: input_button.my_button_double_click
- timing:
- ON for 1s to 2s
- OFF for at least 0.5s
then:
- logger.log: Very long click
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- logger.log: Clicked.
- homeassistant.service:
service: input_button.press
data:
entity_id: input_button.my_button_click