How I Solved the OTA Update Problem for My Deep Sleep Devices
Alright, my friends, today I’m gonna tell you how I solved the OTA update issue for all my ESPHome devices that are in deep sleep 95% of the time. If you’ve ever had to wait for a device to wake up just to do an update, you know how annoying it can be. But don’t worry! I’ve created a super simple and automatic system so that my devices are ready to update whenever needed, without the hassle of trying to catch them while they’re in deep sleep mode.
1. Code on the ESPHome device
First things first, we need to use substitutions in the ESPHome code to make things more flexible and reusable. This allows you to define variables at the top of the file and then use them throughout the rest of your YAML. It’s like creating a cheat sheet so you don’t have to keep typing the same stuff over and over.
Example of code with substitutions in ESPHome:
At the top of your YAML file, you define your variables, like the device name, light pin, etc. Then you use those variables throughout the code.
substitutions:
esp_name: "Living room plants"
esp_id: "living_room_plants"
pin_led_board: GPIO2 # Pin for the status light
# Include the common OTA code
packages:
ota: !include common/ota_update.yaml
Here, we define variables like esp_name
, esp_id
, and pin_led_board
so you can reuse them everywhere in the file. It keeps the code neat, easy to read, and prevents repetitive stuff. Like your grandma’s recipes, but way more efficient!
2. Code for OTA updates (ota_update.yaml
)
Now, let’s talk about that ota_update.yaml
file you’ve got, which contains all the OTA magic . Thanks to substitutions, we don’t need to rewrite the same thing for every device. This file becomes like your go-to script for all your ESPHome devices, all ready to be reused. No need to reinvent the wheel, you feel me?
Example of ota_update.yaml
:
# Status light to show if OTA update is pending
output:
- platform: ledc
pin: ${pin_led_board}
id: ${esp_id}_led_board
light:
- platform: monochromatic
output: ${esp_id}_led_board
name: "${esp_name} Status Light"
id: ${esp_id}_light_board
effects:
- pulse:
name: "Fast Pulse"
transition_length: 0.5s
update_interval: 0.5s
min_brightness: 0%
max_brightness: 100%
switch:
# Switch to tell us if there's an OTA update pending
- platform: template
id: ${esp_id}_ota_update
name: "${esp_name} OTA - Prepare update"
icon: "mdi:bed"
lambda: |-
if (id(${esp_id}_ota_update_available).state == "on") {
return true;
} else {
return false;
}
optimistic: true
on_turn_on:
- logger.log: "Switch turned on"
on_turn_off:
- logger.log: "Switch turned off"
text_sensor:
# Text sensor to show the OTA status
- platform: template
id: ${esp_id}_ota_status
name: "${esp_name} OTA - Status"
icon: mdi:list-status
# Receive the signal from Home Assistant and handle the deep sleep state
- platform: homeassistant
name: "${esp_name} OTA Update Available"
entity_id: input_boolean.${esp_id}_ota_update_available
id: ${esp_id}_ota_update_available
on_value:
then:
- if:
condition:
text_sensor.state:
id: ${esp_id}_ota_update_available
state: 'off'
then:
- logger.log: "Switch turned off"
- light.turn_off: ${esp_id}_light_board # Turn off the light
- text_sensor.template.publish:
id: ${esp_id}_ota_status
state: "No OTA updates pending"
- script.execute: run # Run the script to go back to deep sleep
else:
- logger.log: "Switch turned on"
- light.turn_on:
id: ${esp_id}_light_board # Turn on the light
effect: "Fast Pulse"
- text_sensor.template.publish:
id: ${esp_id}_ota_status
state: "Awaiting OTA update"
Now, when there’s an OTA update pending, the status light will blink like there’s a party going on. When it’s done, or the update isn’t needed, the light goes off . It’s like a visual reminder so you don’t forget that your device is waiting for that OTA action.
3. Code to include in Home Assistant
For Home Assistant, we need to create an input_boolean
so we can tell the device whether or not an OTA update is available. This helps manage the update flow between the two systems.
In your configuration.yaml
, you add the following code:
homeassistant:
# Files where I include various settings for my ESPHome devices, automations, etc.
packages: !include_dir_merge_named arduxmon_packages
This loads the YAML files from arduxmon_packages
, including the device-specific ones. For example, in living_room_plants.yaml
, you’ll add:
input_boolean:
living_room_plants_ota_update_available:
name: "Living room plants - OTA Update Available"
initial: off
icon: mdi:nature-people
This input_boolean
is the switch that Home Assistant uses to tell the device that an OTA update is available. When it’s turned on, the ESP device stays awake, waiting for that sweet OTA update.
4. How Everything Works Together
Now let’s connect the dots so you can see how all this flows.
Interaction between Home Assistant and ESPHome device:
- Activate the
input_boolean
in Home Assistant:
- You turn on the
input_boolean
(e.g., living_room_plants_ota_update_available
) in Home Assistant when you’re ready for the OTA update.
- The ESP32 device:
- The device wakes up and checks the state of the
input_boolean
. If it’s on, it stays awake, and the status light turns on, flashing to let you know there’s an update pending.
- Turn off the
input_boolean
once the OTA is done:
- Once the update happens, or if you just wanna stop it, you turn off the
input_boolean
in Home Assistant. This sends the device back into deep sleep and turns off the light.
- Using the light as a reminder:
- If you forget to update or just want to be reminded, the flashing light will give you that visual cue that the OTA update is still pending.
The flow in a nutshell:
- You activate the
input_boolean
in Home Assistant when you want to start the OTA process.
- The ESP32 wakes up and checks the status. If there’s an update, the device stays awake and the light flashes.
- When the update is done (or you decide to cancel), you turn off the
input_boolean
, and the device goes back to deep sleep.
Recap in the Funniest Way Possible :
You’re chilling in the living room, and your plants are like “yo, update me!”. So you go into Home Assistant, flip the switch , and boom, your ESP32 lights up like a Christmas tree . It waits for that OTA update while you go back to watching Netflix . When it’s all done, the light goes off like “OK, back to sleep!” . Simple, automatic, and with a flashing light as your reminder!