I was able to achieve this exact use case using the node-red plugin. I am doing something similar for a winch setup. here is what i did.
My setup required me to do this with two switches - meaning i have an individual flow for “up” and another for “down” because this is how my physical switches work. I assume the same is true for you.
things you will need:
- custom:button-card
- node-red integration with HA
thats about it… node-red can be a bit difficult to get up and integrated, but there are a lot of youtube tutorials to get you going.
let’s get started. The general idea is this
- set up
input_numbers
that will be used as placeholder values which will inform node-red the button is depressed
- Use the
repeat
functionality of the custom:button-card
to continuously increment the input_number
every ~100 milliseconds
- Start a flow in node-red that will fire an event when the number has changed
- Run the flow through a trigger node which will go
high
when a value as come through, then go low after ~200 milliseconds. Note this is double the time of the
repeat` setting above. Setting it higher will ensure that if for some reason the one of the state change events is missed, it still has time to register the next state change. this ALSO becomes how long the switch will remain on AFTER you release the button, so play with these 2 values. I should probably use 250 or drop my 100ms to 80ms, but i haven’t had issues yet.
- you can then use a switch control to route to the call_service node for turning the switch on or off based on the trigger state (high or low).
- Be sure to reset the input_number back to 0 after the “off” call is made
- Be sure you do nothing when the “value” of the input_number == 0.
Here are some of my configs.
configuration.yaml
in HA
input_number:
winch_rhode_button_down_pressing:
name: Winch Button "Down" Is Depressed
initial: 0
min: 0
max: 2500
step: .5
winch_rhode_button_up_pressing:
name: Winch Button "Up" Is Depressed
initial: 0
min: 0
max: 2500
step: .5
my HA dashboard using the custom:button-card card. Note i utilize the tap_action
as well as the hold_action
in this. The only difference is the hold_action
uses the repeat
to keep the value changing continuously
- entity: holder
type: custom:button-card
template: container
color: '#EDE7B0'
custom_fields:
buttons:
card:
type: horizontal-stack
cards:
- entity: switch.sonoff_1001423223_2
name: Down
icon: mdi:arrow-down-bold
type: custom:button-card
tap_action:
action: call-service
service: input_number.increment
service_data:
entity_id: input_number.winch_rhode_button_down_pressing
hold_action:
action: call-service
service: input_number.increment
repeat: 100
service_data:
entity_id: input_number.winch_rhode_button_down_pressing
- entity: switch.sonoff_1001423223_1
name: Up
icon: mdi:arrow-up-bold
type: custom:button-card
tap_action:
action: call-service
service: input_number.increment
service_data:
entity_id: input_number.winch_rhode_button_up_pressing
hold_action:
action: call-service
service: input_number.increment
repeat: 100
service_data:
entity_id: input_number.winch_rhode_button_up_pressing
This is everything on the HA side.
On to node-red. I’m too new to upload a bunch of photos or this would be easier… i’ll try to explain…
Here is my flow for the “Up” button - you will repeat this for “Down” as well
Starting with the left side is my config for the state changed - i am monitoring the input_number only. Also, i ignore the value “0” so that when i reset it to 0 after turning the switch off i do not fire another event. This is done by setting the “State type” to “number” and adding a condition of “is not”: 0. Finally the custom output needs to be added where the custom payload is {"reset": true}
. This is important to keep the trigger from going low while you are holding the button down
Next is the trigger node. Because of the {"reset": true}
above, this will keep reseting itself every time the input_number changes, then it will not go “low” again until 200ms after the last number changes. I have it Send
1
then wait for
200 milliseconds
and the checkbox extend delay if new message arrives
checked. Thats all.
the switch node is quite basic, trigger one output on a 1 and the other on a 0 by adding an ==
1
and ==
0
. Simple.
Call the service for either turning your switch on or off. I have a switch.turn_off
and a switch.turn_on
for each the up and down directions.
And finally, if it is turning off, i reset the input_number value by calling the input_number.set_value
with a payload of {"value": 0}
Hope this helps!