I have an existing ESP32 device that is to be used as an operational remote through the HA Frontend. I have all of that working with 3 button toggles per button - single click, double click, hold. I am trying to set up my ESP32 device to somehow be able to be discovered by another HA/ESPHome. I have this somewhat working. My problem is updating WiFi secrets without destroying the existing YAML configurations I’ve made. Here’s my YAML:
esphome:
name: esp32
friendly_name: esp32
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "j2c7Y/RdRJL2Lew5Q7IVNI8KiEqQOrWY5s0Vf8P66o8="
ota:
- platform: esphome
password: "4f4e3cb2f1d52bea59eda10bba1838ac"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp32 Fallback Hotspot"
password: "Z2kC8tfVUFym"
captive_portal:
switch:
- platform: template
name: "Menu Single"
id: menu_single
optimistic: true
- platform: template
name: "Menu Hold"
id: menu_hold
optimistic: true
- platform: template
name: "Menu Double"
id: menu_double
optimistic: true
- platform: template
name: "Up Single"
id: up_single
optimistic: true
- platform: template
name: "Up Hold"
id: up_hold
optimistic: true
- platform: template
name: "Up Double"
id: up_double
optimistic: true
- platform: template
name: "Power Single"
id: power_single
optimistic: true
- platform: template
name: "Power Hold"
id: power_hold
optimistic: true
- platform: template
name: "Power Double"
id: power_double
optimistic: true
- platform: template
name: "Left Single"
id: left_single
optimistic: true
- platform: template
name: "Left Hold"
id: left_hold
optimistic: true
- platform: template
name: "Left Double"
id: left_double
optimistic: true
- platform: template
name: "OK Single"
id: ok_single
optimistic: true
- platform: template
name: "OK Hold"
id: ok_hold
optimistic: true
- platform: template
name: "OK Double"
id: ok_double
optimistic: true
- platform: template
name: "Right Single"
id: right_single
optimistic: true
- platform: template
name: "Right Hold"
id: right_hold
optimistic: true
- platform: template
name: "Right Double"
id: right_double
optimistic: true
- platform: template
name: "Volume Up Single"
id: vol_up_single
optimistic: true
- platform: template
name: "Volume Up Hold"
id: vol_up_hold
optimistic: true
- platform: template
name: "Volume Up Double"
id: vol_up_double
optimistic: true
- platform: template
name: "Down Single"
id: down_single
optimistic: true
- platform: template
name: "Down Hold"
id: down_hold
optimistic: true
- platform: template
name: "Down Double"
id: down_double
optimistic: true
- platform: template
name: "Channel Up Single"
id: ch_up_single
optimistic: true
- platform: template
name: "Channel Up Hold"
id: ch_up_hold
optimistic: true
- platform: template
name: "Channel Up Double"
id: ch_up_double
optimistic: true
- platform: template
name: "Volume Down Single"
id: vol_down_single
optimistic: true
- platform: template
name: "Volume Down Hold"
id: vol_down_hold
optimistic: true
- platform: template
name: "Volume Down Double"
id: vol_down_double
optimistic: true
- platform: template
name: "Mute Single"
id: mute_single
optimistic: true
- platform: template
name: "Mute Hold"
id: mute_hold
optimistic: true
- platform: template
name: "Mute Double"
id: mute_double
optimistic: true
- platform: template
name: "Channel Down Single"
id: ch_down_single
optimistic: true
- platform: template
name: "Channel Down Hold"
id: ch_down_hold
optimistic: true
- platform: template
name: "Channel Down Double"
id: ch_down_double
optimistic: true
- platform: template
name: "Skip Back Single"
id: skip_back_single
optimistic: true
- platform: template
name: "Skip Back Hold"
id: skip_back_hold
optimistic: true
- platform: template
name: "Skip Back Double"
id: skip_back_double
optimistic: true
- platform: template
name: "Stop Single"
id: stop_single
optimistic: true
- platform: template
name: "Stop Hold"
id: stop_hold
optimistic: true
- platform: template
name: "Stop Double"
id: stop_double
optimistic: true
- platform: template
name: "Skip Forward Single"
id: skip_fwd_single
optimistic: true
- platform: template
name: "Skip Forward Hold"
id: skip_fwd_hold
optimistic: true
- platform: template
name: "Skip Forward Double"
id: skip_fwd_double
optimistic: true
- platform: template
name: "Fast Back Single"
id: fast_back_single
optimistic: true
- platform: template
name: "Fast Back Hold"
id: fast_back_hold
optimistic: true
- platform: template
name: "Fast Back Double"
id: fast_back_double
optimistic: true
- platform: template
name: "Play/Pause Single"
id: play_pause_single
optimistic: true
- platform: template
name: "Play/Pause Hold"
id: play_pause_hold
optimistic: true
- platform: template
name: "Play/Pause Double"
id: play_pause_double
optimistic: true
- platform: template
name: "Fast Forward Single"
id: fast_fwd_single
optimistic: true
- platform: template
name: "Fast Forward Hold"
id: fast_fwd_hold
optimistic: true
- platform: template
name: "Fast Forward Double"
id: fast_fwd_double
optimistic: true
- platform: template
name: "A Single"
id: a_single
optimistic: true
- platform: template
name: "A Hold"
id: a_hold
optimistic: true
- platform: template
name: "A Double"
id: a_double
optimistic: true
- platform: template
name: "B Single"
id: b_single
optimistic: true
- platform: template
name: "B Hold"
id: b_hold
optimistic: true
- platform: template
name: "B Double"
id: b_double
optimistic: true
- platform: template
name: "C Single"
id: c_single
optimistic: true
- platform: template
name: "C Hold"
id: c_hold
optimistic: true
- platform: template
name: "C Double"
id: c_double
optimistic: true
- platform: template
name: "D Single"
id: d_single
optimistic: true
- platform: template
name: "D Hold"
id: d_hold
optimistic: true
- platform: template
name: "D Double"
id: d_double
optimistic: true
- platform: template
name: "E Single"
id: e_single
optimistic: true
- platform: template
name: "E Hold"
id: e_hold
optimistic: true
- platform: template
name: "E Double"
id: e_double
optimistic: true
- platform: template
name: "F Single"
id: f_single
optimistic: true
- platform: template
name: "F Hold"
id: f_hold
optimistic: true
- platform: template
name: "F Double"
id: f_double
optimistic: true
binary_sensor:
# needs its own pullup
- platform: gpio
pin:
number: GPIO36
inverted: false
mode:
input: true
#pullup: true (gpio36 doesn't have internal pullup)
id: menu
name: "Menu"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: menu_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: menu_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: menu_single
invalid_cooldown: 0.2s
# needs its own pullup
- platform: gpio
pin:
number: GPIO39
inverted: false
mode:
input: true
#pullup: true
id: up
name: "Up"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: up_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: up_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: up_single
invalid_cooldown: 0.2s
# needs its own pullup
- platform: gpio
pin:
number: GPIO2
inverted: false
mode:
input: true
#pullup: true
id: power
name: "Power"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: power_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: power_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: power_single
invalid_cooldown: 0.2s
# needs its own pullup
- platform: gpio
pin:
number: GPIO35
inverted: false
mode:
input: true
#pullup: true
id: left
name: "Left"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: left_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: left_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: left_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO33
inverted: true
mode:
input: true
pullup: true
id: ok
name: "OK"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ok_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ok_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ok_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO32
inverted: true
mode:
input: true
pullup: true
id: right
name: "Right"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: right_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: right_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: right_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO25
inverted: true
mode:
input: true
pullup: true
id: vol_up
name: "Volume Up"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_up_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_up_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_up_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO26
inverted: true
mode:
input: true
pullup: true
id: down
name: "Down"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: down_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: down_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: down_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO27
inverted: true
mode:
input: true
pullup: true
id: ch_up
name: "Channel Up"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_up_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_up_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_up_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO14
inverted: true
mode:
input: true
pullup: true
id: vol_down
name: "Volume Down"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_down_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_down_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: vol_down_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO12
inverted: true
mode:
input: true
pullup: true
id: mute
name: "Mute"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: mute_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: mute_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: mute_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO13
inverted: true
mode:
input: true
pullup: true
id: ch_down
name: "Channel Down"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_down_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_down_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: ch_down_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO15
inverted: true
mode:
input: true
pullup: true
id: skip_back
name: "Skip Back"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_back_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_back_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_back_single
invalid_cooldown: 0.2s
# need its own pullup
- platform: gpio
pin:
number: GPIO34
inverted: false
mode:
input: true
#pullup: true
id: stop
name: "Stop"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: stop_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: stop_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: stop_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO0
inverted: true
mode:
input: true
pullup: true
id: skip_fwd
name: "Skip Forward"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_fwd_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_fwd_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: skip_fwd_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO4
inverted: true
mode:
input: true
pullup: true
id: fast_back
name: "Fast Backward"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_back_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_back_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_back_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO16
inverted: true
mode:
input: true
pullup: true
id: play_pause
name: "Play/Pause"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: play_pause_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: play_pause_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: play_pause_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO17
inverted: true
mode:
input: true
pullup: true
id: fast_fwd
name: "Fast Forward"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_fwd_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_fwd_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: fast_fwd_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO5
inverted: true
mode:
input: true
pullup: true
id: a
name: "A"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: a_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: a_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: a_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO18
inverted: true
mode:
input: true
pullup: true
id: b
name: "B"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: b_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: b_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: b_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO23
inverted: true
mode:
input: true
pullup: true
id: c
name: "C"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: c_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: c_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: c_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO19
inverted: true
mode:
input: true
pullup: true
id: d
name: "D"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: d_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: d_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: d_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO21
inverted: true
mode:
input: true
pullup: true
id: e
name: "E"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: e_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: e_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: e_single
invalid_cooldown: 0.2s
- platform: gpio
pin:
number: GPIO22
inverted: true
mode:
input: true
pullup: true
id: f
name: "F"
internal: true #(this hides the plain button from HA frontend)
on_multi_click:
- timing:
- ON for at most 0.5s
- OFF for at most 0.2s
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: f_double
invalid_cooldown: 0.2s
- timing:
- ON for at least 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: f_hold
invalid_cooldown: 0.2s
- timing:
- ON for at most 0.5s
- OFF for at least 0.2s
then:
- switch.toggle: f_single
invalid_cooldown: 0.2s
In a test scenario I deleted the YAML in the ESPHome web UI and tried to establish a connection with the device. When plugged in to the HA station it was recognized, but was not recognized wirelessly. I imagine because things like the API key, OTA password, and fallback hotspot password weren’t set up. Is there a way to set this up without damaging the YAML that exists?
My end goal is to produce remotes for colleagues and have them set up their own sensitive information. If I can get that down to just updating wifi credentials that would be optimal.