Hello everyone!
I wanted to share with you a solution I found for a problem that many might be facing: how to keep devices awake during OTA updates in ESPHome.
The problem: I had devices that, for power-saving reasons, would enter deep sleep after sending data to Home Assistant. This meant they would only stay awake for a few seconds, making it impossible to update them via OTA.
The solution: After several attempts, I managed to find a solution that worked for me. I created a service in Home Assistant as an input_boolean. When this service is set to ON, it indicates that an update is desired. However, the issue was that devices couldnāt read this service upon boot as they were in deep sleep.
To address this, I included a while loop immediately after waking up. This loop persists while the service returns an empty value. Once it returns a value (which should be either OFF or ON), the device proceeds with the rest of the code. If itās OFF, it continues with its scheduled operation; if itās ON, it cancels deep sleep and remains awake to receive the update.
Why it works: This solution allows the device to be attentive to OTA updates only when needed, while still conserving power by remaining in deep sleep when an update isnāt required.
I hope this solution proves helpful to those facing the same issue. And Iād love to hear if anyone has an even more optimal solution than this!
The Home Assitant service:
input_boolean:
ota_update_available:
name: OTA Update Available
initial: off
icon: mdi:nature-people
The ESPHome code (Lolin-S2 mini):
esp32:
board: lolin_s2_mini
framework:
type: arduino
esphome:
name: read-ha-on-awake
friendly_name: read HA on awake
on_boot:
then:
# I use the onboard led to visually check at which point of the process we are.
- light.turn_on: light_esp
# This is where the 'trick' is, I make my workaround with the while loop until I verify that we have a connection to HA.
- while:
condition:
lambda: 'return id(ota_update_available).state == "";'
then:
- logger.log: "We're still not connecting to HA, retrying in 5s."
- homeassistant.service:
service: 'homeassistant.update_entity'
data:
entity_id: 'input_boolean.ota_update_available'
# I test using the onboard led.
- light.turn_off: light_esp
- delay: 50ms
- light.turn_on: light_esp
- delay: 5s
- homeassistant.service:
service: 'homeassistant.update_entity'
data:
entity_id: 'input_boolean.ota_update_available'
- delay: 5s
- if:
condition:
text_sensor.state:
id: ota_update_available
state: 'on'
then:
- logger.log: "OTA Update Available!"
# I test using the onboard led.
- light.turn_off: light_esp
- delay: 500ms
- light.turn_on: light_esp
# Prevent the ESP32 from going to sleep
- deep_sleep.prevent: deep_sleep_1
else:
- logger.log: "no OTA Update Available!"
# I test using the onboard led.
- light.turn_off: light_esp
- delay: 200ms
- light.turn_on: light_esp
- delay: 1000ms
- light.turn_off: light_esp
- delay: 200ms
- light.turn_on: light_esp
- delay: 1000ms
- light.turn_off: light_esp
- delay: 200ms
- light.turn_on: light_esp
- delay: 1000ms
- light.turn_off: light_esp
logger:
api:
encryption:
key: "xxxxxxxxxxxxxx"
ota:
password: "f41fefdee105a2e5c2d0263fe94810ca"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Read-Ha-On-Awake"
password: "xxxxxxxxx"
captive_portal:
web_server:
deep_sleep:
id: deep_sleep_1
run_duration: 60s
sleep_duration: 20s
text_sensor:
- platform: homeassistant
name: "OTA Update Available"
entity_id: "input_boolean.ota_update_available"
id: ota_update_available
light:
- platform: binary
id: light_esp
name: "ESP LIGHT"
output: light_output
output:
- id: light_output
platform: gpio
pin: GPIO15
Best regards to all!