I am in the process of making an electronic ESP32-Powered button pusher for an existing panel. Basically, the ESP reads the duty cycle of two LEDs to get power and boiler states, and has two GPIO outputs connected to the existing push buttons to control the boiler and power states from ESPHome. The physical buttons are still accessible from the panel, so the states can be changed either from the physical buttons, or ESPHome. Complicating things, this machine has different momentary hold requirements for each button state:
Turn on Power: Press and Hold Button for 3s
Turn off Power: Momentary Press
Turn on Boiler: Momentary Press
Turn off Boiler: Press and Hold Button for 3s
I use the following code to get the power and boiler states:
# Status LED Duty Cycles
sensor:
- platform: duty_cycle
id: power_led_duty_cycle
pin:
number: ${power_led_input_pin}
mode:
input: true
pulldown: true
name: Power LED Duty Cycle
update_interval: 1s
- platform: duty_cycle
id: boiler_led_duty_cycle
pin:
number: ${boiler_led_input_pin}
mode:
input: true
pulldown: true
name: Boiler LED Duty Cycle
update_interval: 1s
# Power, Steam Boiler State Inputs
binary_sensor:
- platform: template
id: power_state
name: "Power State"
device_class: power
lambda: |-
if (id(power_led_duty_cycle).state > 80) {
return true;
} else {
return false;
}
- platform: template
id: boiler_state
name: "Boiler State"
device_class: running
lambda: |-
if (id(boiler_led_duty_cycle).state > 40) {
return true;
} else {
return false;
}
And this code to switch between the states by closing the existing button contacts:
# Button Outputs
output:
- platform: gpio
id: power_btn
pin: ${power_btn_output_pin}
- platform: gpio
id: boiler_btn
pin: ${boiler_btn_output_pin}
switch:
- platform: output
name: "Power"
output: power_btn
on_turn_on:
- output.turn_on: power_btn
- delay: 3s
- output.turn_off: power_btn
on_turn_off:
- output.turn_on: power_btn
- delay: 0.5s
- output.turn_off: power_btn
- platform: output
name: "Boiler"
restore_mode: RESTORE_DEFAULT_ON
output: boiler_btn
on_turn_on:
- output.turn_on: boiler_btn
- delay: 0.5s
- output.turn_off: boiler_btn
on_turn_off:
- output.turn_on: boiler_btn
- delay: 3s
- output.turn_off: boiler_btn
Everything works as expected right now, but if the power or boiler state is physically changed at the panel, then the ESPHome switches are out of sync. (The duty cycles and binary sensors still report correct states since they’re monitoring the LEDs.) I know I could set up some custom switches in Home Assistant, but is there a good way to combine the switch and binary sensors together to have a single entity within ESPHome that will control switching and update according to the LED duty cycle? If the machine didn’t require different timings to turn off and on, I would change the switches to buttons, and monitor the state separately, but having two on buttons, two off buttons, and two “monitoring” binary sensors seems a bit cumbersome.