ESPHome device update manager for Home Assistant.
A custom Home Assistant integration that provides a dedicated panel and lovelace card for managing ESPHome firmware updates across all your ESPHome devices.
- Features
- Requirements
- Recommendations
- Installation
- Configuration
- Dashboard Card
- Usage
- Deep sleep devices
- Error handling
- Troubleshooting
- Uninstallation
- License
- Centralized dashboard — View all ESPHome devices, their firmware versions, and status in one place
- External dashboard support — Connect to an ESPHome dashboard running on another machine (e.g., a separate build server)
- Dashboard authentication — Support for username/password authentication on external dashboards
- Mixed setup support — Use both local ESPHome add-on and external dashboard simultaneously
- Batch updates — Select multiple devices and update them sequentially with a single click
- Individual updates — Update a single device directly from the panel
- Force Install — Recompile and upload via the ESPHome dashboard, even when no update is available. Also used for project version updates
- Pending Force Install for offline devices — Queue offline (e.g. deep sleep) devices for force install; they are automatically installed as soon as they come online
- Auto-install — automatically start updates when new firmware or a new project version becomes available
- Manual refresh — refresh button and service to re-check project versions, dashboards, and pending devices on demand or from automations
- Enable firmware entities — Disabled firmware update entities can be enabled directly from the panel
- Exclude devices from auto-install — Mark devices to be skipped by auto-install while still allowing manual force install
- Skipped update detection — Devices with updates skipped via Home Assistant are clearly marked
- Smart error handling — Compile errors, OTA failures, and offline devices are detected and reported immediately
- Failure notifications — Persistent notifications alert you when updates fail, with a link to the update log
- Update log — Detailed log of all update results, viewable directly in the panel
- Log history — Access previous update logs via the 3-dots menu (configurable backup count)
- VS Code Server add-on management — Optionally stop the VS Code Server add-on during updates to free memory, and automatically restart it when updates are complete
- Real-time status — Live progress tracking with online/offline indicators for each device
- Resilient queue — If a device fails, the queue continues with the next device
- Cancel anytime — Cancel running updates at any time; remaining devices are marked as cancelled
- Granular build services — Trigger individual
clean_build_files,compile, oruploadoperations via service calls for use in scripts and automations
- Home Assistant 2024.1 or newer
- ESPHome integration configured with your devices
- ESPHome Device Builder (Dashboard) app (add-on) installed and populated with your devices, or an external ESPHome dashboard accessible via HTTP. (ESPHome 2021.8.0 or newer)
-
Although not required, adding the following to the device's YAML gives fast and reliable online status detection:
binary_sensor: - platform: status name: "Status"
This sensor reports the device's online state instantly to Home Assistant.
Note on online status detection:
The integration uses a fallback chain to determine each device's online status:
statusbinary_sensor (recommended) — instant and reliable detection of online/offline transitions.- ESPHome integration fallback — if no status sensor is configured, the integration falls back to the ESPHome native API connection state, but is significantly slower and less reliable: it can take up to several minutes before a disconnected device is detected as offline, due to the keepalive timeout of the ESPHome API.
- Unknown 🟡 — shown when neither source can determine the status.
For best results, always add the
statusbinary_sensor to your devices.
-
Via HACS: Search for ESPHome Update Manager, download and restart Home Assistant
Or manual: Copy the
custom_components/esphome_update_managerfolder to your Home Assistantconfig/custom_components/directory and restart Home Assistant -
Add integration: Home Assistant → Settings → Devices & Services → Add Integration → search ESPHome Update Manager → submit
-
Optionally configure an external ESPHome dashboard URL (see Configuration) and log backup count
-
A new ESPHome Updates panel appears in the sidebar
The integration can be configured via Settings → Devices & Services → ESPHome Update Manager → Configure:
| Option | Default | Description |
|---|---|---|
| External Dashboard URL | (empty) | URL of an external ESPHome dashboard (e.g., http://192.168.1.100:6052). Leave empty to use only the local ESPHome add-on. |
| Username | (empty) | Username for dashboard authentication (optional) |
| Password | (empty) | Password for dashboard authentication (optional) |
| Number of log backups to keep | 5 | Number of previous update logs to retain (0 = disable backups) |
If you run ESPHome on a separate machine (e.g., a dedicated build server), you can configure the integration to use that dashboard for compiling and uploading firmware:
- Go to Settings → Devices & Services → ESPHome Update Manager → Configure
- Enter the URL of your external ESPHome dashboard (e.g.,
http://192.168.1.100:6052) - If your dashboard requires authentication, enter the username and password
- Click Submit
The integration will automatically reload and connect to the external dashboard.
Requirements for external dashboard:
- The dashboard must be accessible from Home Assistant via HTTP
- The devices must also exist in Home Assistant's ESPHome integration
Authentication:
- If your external dashboard is protected with basic authentication, enter the username and password in the configuration
- The credentials are used for both HTTP requests and WebSocket connections (compile/upload)
- When updating credentials in the options flow, leave the password field empty to keep the current password
To disconnect from an external dashboard:
- Clear the URL field or set it to
http:// - This will remove the external dashboard configuration and credentials
Mixed setup:
When using an external dashboard, you can have devices managed by both the local ESPHome add-on and the external dashboard. In mixed setups, external devices are marked with (ext) after their name in the panel.
Dashboard offline handling:
- If the external dashboard becomes unreachable, affected devices show "Unavailable" status
- The panel automatically updates within ~1 minute when the dashboard comes back online
- Auto-update triggers automatically when the dashboard comes online with pending updates
ESPHome Update Manager can also be used as a Lovelace dashboard card:
type: custom:esphome-update-cardAll options are optional — the card works out of the box without any configuration.
| Option | Type | Default | Description |
|---|---|---|---|
title |
string | none | Display a custom title at the top of the card |
show_header |
boolean | false |
Show the full panel header with logo inside the card |
compact |
boolean | false |
Use smaller fonts and padding for a more compact layout |
hide_addon_option |
boolean | false |
Hide the add-on stop/start option |
hide_auto_update |
boolean | false |
Hide the automatic update toggle |
hide_results |
boolean | false |
Hide the update results section |
max_width |
string | none | Maximum width of the card (e.g. 900px) |
max_height |
string | none | Maximum height of the card — content will scroll (e.g. 600px) |
align |
string | left |
Card alignment: left, center, or right |
type: custom:esphome-update-card
title: "ESP Updates"
show_header: false
compact: true
hide_addon_option: true
hide_auto_update: true
hide_results: true
max_width: 900px
max_height: 600px
align: centerNote: The card shares all functionality with the panel — updates, force install, cancel, and log viewing all work the same way. The log menu (⋮) is accessible via the toolbar inside the card when the header is hidden.
The toolbar above the device list contains four mode buttons and a log shortcut:
| Button | Color | Description |
|---|---|---|
| UPD | Blue | Enter Firmware Update mode — select devices to update |
| FRC | Green | Enter Force Install mode — select devices to recompile and reinstall |
| EXC | Purple | Enter Exclude mode — select devices to exclude from auto-update |
| LOG | Teal | Open the latest update log |
Once a mode is active, the toolbar switches to a confirm/cancel view:
| Button | State | Description |
|---|---|---|
| ▶ Firmware Update (n) (blue) | Update mode | Starts the update queue for the selected devices. Click with 0 selected to exit the mode. |
| ▶ Force Install (n) (green) | Force Install mode | Starts force install for the selected devices, or saves the pending list when only offline devices are selected. Click with 0 selected to exit the mode. |
| ▶ Save Excluded (n) (purple) | Exclude mode | Saves the current selection as excluded devices. Saving with 0 selected clears the exclude list. |
| ✕ | Any mode active | Exits the current mode without applying changes |
| ⏹ Cancel (red) | Updates running | Cancels the running update queue |
Only one mode can be active at a time. The UPD button is disabled when no updates are available.
The panel shows all ESPHome devices with:
| Column | Description |
|---|---|
| ☑️ Checkbox | Select devices for batch update |
| 🟢🔴🟡 Status | Online, offline, or unknown |
| Name | Device name (with (ext) suffix in mixed setups for external devices) |
| Version | Current version → available version or Current version only if up-to-date |
| Button | Action button (see below) |
| Button | Meaning |
|---|---|
| Update (blue) | Firmware update ready to install — click to start |
| Install (blue) | Project version bump ready to install — click to start |
| Up to date (green) | Device is on the latest firmware |
| Excluded (purple) | Device is excluded from auto-update and has an update available — manage via the EXC button |
| Skipped (purple) | Update was skipped via Home Assistant — clear skip in HA to update |
| Enable (orange) | Firmware entity is disabled — click to enable |
| Enabling… (orange + spinner) | Entity is being enabled, waiting for HA to pick it up |
| Updating… (blue + spinner) | Update is in progress |
| Installing… (blue + spinner) | Force install is in progress |
| Compiling… (blue + spinner) | Compiling only is in progress |
| Uploading… (blue + spinner) | Uploading only is in progress |
| Pending (grey) | Device is queued for force install — will start automatically when device comes online |
| Offline (grey) | Device is not reachable |
| Unavailable (light blue) | Firmware entity is unavailable (or external dashboard offline) |
- Select devices using the checkboxes (or click Select all)
- Click ▶ Update selected (n)
- Devices are updated sequentially
- Progress and results are shown in real-time
- Click ⏹ Cancel to stop the queue at any time
Force Install recompiles the firmware via the ESPHome dashboard and uploads it via OTA, regardless of whether an update is available. This is useful when:
- You want to push a configuration change that does not change the firmware version
- A device's project version in the YAML is higher than what is installed on the device
- You want to force a clean reinstall of the current firmware
- You want to update multiple devices in one batch — Force Install compiles and uploads all selected devices sequentially, without needing a firmware version bump.
- You want to install a modified yaml to an offline device when it comes online
- Click Force Install in the toolbar — the panel switches to Force Install mode and all devices become selectable, including offline and unavailable ones
- Select one or more devices using the checkboxes (or click the Select all checkbox in the toolbar)
- Click ▶ Force Install (n) to start
- Online devices are recompiled and uploaded immediately, sequentially
- Offline devices are added to the pending list and will be force installed automatically as soon as they come online (see Pending force install for offline devices)
- Progress and results are shown in real-time, just like a regular update
- Click ✕ to exit Force Install mode without starting
Note: While in Force Install mode, the Firmware Update button is disabled (and vice versa) — you can only be in one mode at a time.
Force Install always recompiles the firmware, even if nothing has changed.
Devices that are offline (e.g., deep sleep devices) when you trigger a Force Install are not skipped — they are added to a persistent pending list. The integration watches for these devices to come online and automatically starts the force install at that moment.
How it works:
- Select one or more offline devices in Force Install mode (or pass them to the
esphome_update_manager.force_installservice) and confirm (Click ▶ Force Install (n)) - Each offline device is shown with the Pending label in the panel. To remove a device from the pending list, enter FRC mode again — pending devices appear pre-selected — uncheck them and click ▶ Force Install to confirm.
- When a pending device comes online (status sensor goes
onor ESPHome native API reconnects), the integration waits a short debounce window of ~15 seconds so multiple devices waking up at the same time can be batched - Once ready, the force install starts automatically for all online pending devices in a single batch
- After the force install completes, the device is removed from the pending list — regardless of success or failure
Properties:
- The pending list is persisted across Home Assistant restarts
- A pending device that is removed from Home Assistant is automatically cleaned up
- If a normal update queue is already running when a pending device comes online, the integration retries every 60 seconds until the queue is free
- Pending state is independent from auto-update — pending devices are always force installed, even when auto-update is disabled
Tip: Combine pending force install with the Deep sleep devices automation to fully automate firmware updates for battery-powered devices.
Force Install can also be triggered via a Home Assistant service call, useful for automations:
Service: esphome_update_manager.force_install
| Parameter | Required | Description |
|---|---|---|
device_id |
Yes | One or more Home Assistant device IDs to force install. Can be a single string or a list. |
Behavior:
- Online devices are force installed immediately
- Offline devices are added to the pending list and will be installed automatically when they come online
- If the queue is already running, all selected devices are added to the pending list and will be installed when the queue is free
Note: The force_install service respects the "Stop VS Code Server" setting — if enabled, the VS Code Server add-on will be stopped before the update and restarted afterwards.
Example automation — force install a specific device:
actions:
- action: esphome_update_manager.force_install
data:
device_id: "abc123def456"Example automation — force install multiple devices (mix of online + offline allowed):
actions:
- action: esphome_update_manager.force_install
data:
device_id:
- "abc123def456"
- "789xyz000111"Note: The
device_idis the Home Assistant device ID, not the entity ID. You can find the device ID in Settings → Devices & Services → ESPHome → [your device] → ⋮ → Device info → ID.
The integration automatically checks whether the project version defined in the YAML matches the version installed on the device. When a higher project version is found in the YAML, the device is shown in the panel with the new version and — depending on your settings — automatically force installed.
User control via scope dropdown:
In the Auto install bar you can choose what the integration should install automatically:
| Scope | Behavior |
|---|---|
| Firmware only | Only ESPHome firmware updates are installed automatically. Project bumps are still detected and shown in the panel, but require a manual click on Install. |
| Project only | Only project version bumps from the YAML are installed automatically. Firmware updates are still detected and shown, but require a manual click on Update. |
| Firmware + Project | Both firmware updates and project bumps are installed automatically. |
Note: Detection of project bumps always runs, regardless of the scope. The scope only controls whether the integration acts on it automatically. Devices excluded via EXC are never installed automatically, but their pending bump is still visible.
This check runs in the following situations:
| Trigger | Description |
|---|---|
| Device comes online | When a device transitions from offline to online, its project version is checked after a short delay |
| HA restarts | A short while after Home Assistant has fully started, all currently online devices are checked |
| External dashboard comes online | When the external dashboard reconnects, all online devices are re-checked |
| Auto install settings change | When you toggle auto install or change the scope, a full re-check runs |
| Refresh button | Click the ↻ refresh button next to the scope dropdown to re-check now |
| Refresh service | Call esphome_update_manager.refresh_project_versions from an automation |
How it works:
- The integration reads the
sw_versionfrom the HA device registry (e.g.,1.0.2 (ESPHome 2026.3.1)) - It fetches the YAML config from the ESPHome dashboard and reads the
project.versionfield - If the YAML version is higher than the installed version, the bump is cached and shown in the panel
- If auto install is enabled with a scope that includes project bumps, a Force Install is queued automatically
- Multiple devices detected at the same time are grouped and started as a single batch (~15 second debounce)
- If the update queue is already running, the Force Install is retried until the queue is free
Online vs offline devices:
- Online devices with a project bump are installed automatically (if scope allows it) or can be installed manually via the Install button
- Offline devices with a project bump are shown in the panel with their new version visible — they are not auto-installed until they come back online
Requirements for project version check:
-
The device YAML must contain a
projectblock with aversionfield:esphome: project: name: "mycompany.mydevice" version: "1.0.3"
-
The ESPHome dashboard (local or external) must be accessible
Sometimes you want certain devices to not be installed automatically — for example a critical device that you only want to update manually after testing, or a device with an unstable firmware/project version where you want to wait.
How it works:
- Click EXC in the toolbar — the panel switches to Exclude mode and every device becomes selectable
- Devices that are already excluded appear pre-selected
- Check the devices you want to exclude (or uncheck devices you no longer want to exclude)
- Click ▶ Save Excluded (n) to apply
Effects of excluding a device:
- The device is shown with a purple Excluded button instead of the usual Update or Install button when something is available
- The device is not selectable in Firmware Update mode (UPD)
- Auto install skips the device for both firmware updates and project version bumps, even when the scope includes them
- The pending project bump is still detected and visible in the panel (with the new version shown), so you can decide to install it manually
- Force Install (FRC) still works — exclude only applies to automatic installs, not to manual or service-triggered force installs
Up-to-date excluded devices show the regular Up to date button — the Excluded indication is only visible when an update or project bump is available, since that is when the exclusion actually has an effect.
When you remove devices from the exclude list and confirm with ▶ Save Excluded, the integration immediately re-evaluates auto install for the newly un-excluded devices — both firmware updates and project bumps are queued if applicable (and the scope allows it).
The Auto install bar contains:
☑️ Auto install trigger: [Firmware only ▾] ↻ ● Enabled / ● Disabled
- Checkbox — enables or disables automatic installation
- Scope dropdown — controls what is installed automatically:
Firmware only,Project only, orFirmware + Project(see Project version auto-install) - Refresh button (↻) — immediately re-checks project versions, dashboards, and pending force installs without waiting for the next poll cycle
When enabled, the integration monitors all ESPHome device update entities and project version bumps according to the selected scope. Installs start automatically on:
- A device that comes online with a pending update or project bump
- ESPHome being updated (new firmware available)
- Home Assistant restarting with pending updates
- An external dashboard coming online with pending updates
- Settings changes (enabling auto install or changing scope re-evaluates all devices)
The "Stop VS Code Server" setting is respected for every auto install.
Note: Excluded devices (see Exclude devices from auto-install) are always skipped by auto install, even when they have an update available.
The integration provides a service that can be used in automations:
Service: esphome_update_manager.start_updates
| Parameter | Required | Description |
|---|---|---|
entity_ids |
No | List of specific entity IDs to update. If not provided, all devices with available updates will be updated. |
stop_addon |
No | Whether to stop VS Code Server during updates. If not provided, uses the saved panel setting. |
Update all devices at 3 AM:
alias: ESPHome start devices update
description: time to start updating esphome devices
triggers:
- trigger: time
at: "03:00:00"
conditions: []
actions:
- action: esphome_update_manager.start_updates
data: {}
mode: singleManually re-checks all ESPHome devices for project version bumps and refreshes the dashboard state. Useful for periodic automations.
Service: esphome_update_manager.refresh_project_versions
No parameters.
Behavior:
- Refreshes local and external dashboard data
- Re-checks all ESPHome devices for project version bumps
- Re-evaluates the pending force install list
- Kicks off auto install for any newly detected updates (if auto install is enabled)
Example automation — re-check project versions every hour:
alias: ESPHome refresh project versions
triggers:
- trigger: time_pattern
hours: "/1"
actions:
- action: esphome_update_manager.refresh_project_versions
mode: singleIn addition to start_updates and force_install, the integration provides three services that expose individual steps of the ESPHome build pipeline. Useful for scripts, automations, and advanced workflows.
Services:
| Service | Description |
|---|---|
esphome_update_manager.clean_build_files |
Clean build files (equivalent to "Clean Build Files" in the ESPHome dashboard) |
esphome_update_manager.compile |
Compile firmware without uploading (equivalent to "Install → Manual download → Cancel" in the ESPHome dashboard) |
esphome_update_manager.upload |
OTA upload pre-compiled firmware, without compiling first |
Parameters (all three):
| Parameter | Required | Description |
|---|---|---|
device_id |
No | One or more Home Assistant device IDs. Single string or list. Leave empty to target all ESPHome devices. |
Behavior:
- All three work with both local and external dashboards (the integration auto-selects per device, just like Force Install)
- Operations run sequentially via the same update queue used for firmware updates
- Progress is visible in the panel and update log (with operation-specific labels)
- For
compileandupload, the "Stop VS Code Server" setting is respected - For
clean, the add-on is not stopped (cleaning is fast)
Typical use cases:
| Use case | Workflow |
|---|---|
| Pre-compile before a sleep window | compile ahead of time, then upload the moment the device wakes |
| Recover from a corrupted build | clean_build_files followed by compile |
| Batch OTA during a maintenance window | compile all devices overnight, then upload later |
Example automation — pre-compile before a sleeping sensor wakes up:
alias: Pre-compile sleeping sensor
triggers:
- trigger: time
at: "06:55:00"
actions:
- action: esphome_update_manager.compile
data:
device_id: "abc123def456"
# Device wakes around 07:00 — OTA upload is now instantExample automation — clean all devices weekly:
alias: Weekly clean of all ESPHome build files
triggers:
- trigger: time
at: "04:00:00"
conditions:
- condition: time
weekday:
- sun
actions:
- action: esphome_update_manager.clean_build_files
# No device_id → cleans all ESPHome devicesExample script — clean + compile + upload chain for one device:
sequence:
- action: esphome_update_manager.clean_build_files
data:
device_id: "abc123def456"
- wait_for_trigger:
- trigger: event
event_type: esphome_update_manager_finished
event_data:
operation: clean
timeout: "00:05:00"
- action: esphome_update_manager.compile
data:
device_id: "abc123def456"
- wait_for_trigger:
- trigger: event
event_type: esphome_update_manager_finished
event_data:
operation: compile
timeout: "00:30:00"
- action: esphome_update_manager.upload
data:
device_id: "abc123def456"
- wait_for_trigger:
- trigger: event
event_type: esphome_update_manager_finished
event_data:
operation: upload
timeout: "00:10:00"Note: Only one operation can run at a time — if the update queue is already busy when you call one of these services, the call fails with an error. Wait for the current operation to finish, or chain them sequentially as shown above.
If the VS Code Server (Studio Code Server) add-on is installed, a checkbox appears:
☑️ Stop Studio Code Server during jobs — ● Running / ● Stopped
- When checked, the add-on is automatically stopped before updates/force installs begin and restarted after all updates/force installs complete
- The add-on is always restarted, even if updates are cancelled or fail
- The current status (Running/Stopped) is polled every 30 seconds
This is useful for systems with limited memory where the VS Code Server add-on can cause ESPHome compilations to fail due to insufficient RAM.
After updates complete, a results section shows the outcome for each device:
| Icon | Status | Description |
|---|---|---|
| ✅ | Success | Update completed successfully |
| ❌ | Failed | Update failed (with error details) |
| ⏭️ | Skipped | Device was unavailable — skipped |
| ⛔ | Cancelled | Update was cancelled by user |
| ⏳ | Queued | Waiting in queue |
| 🔄 | Running | Currently updating |
Click ✕ Clear to dismiss the results.
Access update logs via the ⋮ menu in the top-right corner of the panel:
- Latest Log — View the most recent update log
- Previous Logs — Browse previous update logs (configurable, default: 5)
Each log includes:
- Timestamp of the job run and integration version used
- Job type (Firmware Update, Force Install, Clean Build Files, Compile Only, or OTA Upload Only)
- Summary with success/failed/skipped/cancelled counts
- Details per device including status, version (from → to), start time, finish time, and any error messages
Logs are stored at:
- Current log:
config/esphome-update-manager/update_log.txt - Backups:
config/esphome-update-manager/log-backups/
A new backup is created automatically after each update batch completes. The number of backups kept can be configured in the integration settings (set to 0 to disable backups).
When one or more updates fail, a persistent notification is created in Home Assistant:
ESPHome Update Failed
Update for X ESPHome device(s) has failed.
View update log (clickable link)
Clicking the link opens the panel and automatically displays the latest update log.
By combining the integration with a small Home Assistant automation, firmware updates and force installs can be fully automated for these devices: the next time they wake up they will be flashed and put back to sleep automatically, respecting the awake window configured in the automation.
Each deep sleep device must expose:
-
A status binary sensor (used by the automation to detect when the device is online):
binary_sensor: - platform: status name: "Status"
-
A deep sleep button the automation can press. The entity_id must contain
deep_sleep,deepsleep, or havesleepin its friendly name. The deep sleep block must not define arun_duration, so the device stays awake until the button is pressed by the automation (the awake window must be configured in the automation instead):deep_sleep: id: deep_sleep_control sleep_duration: 60min button: - platform: template name: "Enter Deep Sleep" icon: mdi:sleep on_press: - deep_sleep.enter: id: deep_sleep_control
Note: Without a status binary sensor, the automation cannot reliably detect when the device is back online after the OTA reboot, and the deep sleep button will not be pressed.
This single automation handles all deep sleep devices simultaneously.
alias: Deep sleep after wake-up or update
description: >
Handles ALL deep sleep devices. On every wake-up (normal wake AND the
reboot after an install), the device gets its full awake_window_seconds
before being put back to sleep — unless an update is pending/running,
in which case it stays awake until that update finishes (then still
gets its awake_window_seconds before sleeping).
mode: parallel
max: 10 # bump this if more than 10 deep sleep devices could wake up at once
max_exceeded: silent
variables:
awake_window_seconds: 120 # <- your normal "awake to do tasks" window,
# applied both on a normal wake-up and after
# an install + reboot
triggers:
- id: wake
trigger: state
entity_id:
- binary_sensor.device1_status # change to your device status sensor
- binary_sensor.device2_status # change to your device status sensor
# add one line per deep sleep device's status sensor here
to: "on"
- id: finished
trigger: event
event_type: esphome_update_manager_finished
actions:
- choose:
# ── Branch 1: device just woke up ──────────────────────────────
- conditions:
- condition: trigger
id: wake
sequence:
- variables:
wake_last_changed: "{{ trigger.to_state.last_changed }}"
- delay: "{{ awake_window_seconds }}"
- condition: template
value_template: >
{{ states(trigger.entity_id) is not none
and state_attr(trigger.entity_id, 'friendly_name') is not none
and (states[trigger.entity_id].last_changed | string) == (wake_last_changed | string) }}
# ^ if this is false, the sensor flipped again during our wait
# (a reboot happened) — a newer run or the finished-tak is
# already handling this device, so we stop here silently
- action: esphome_update_manager.get_device_status
data:
device_id: "{{ device_id(trigger.entity_id) }}"
response_variable: dev_status
- if:
- condition: template
value_template: >
{{ not dev_status.devices.get(device_id(trigger.entity_id), {}).get('active', false) }}
then:
- variables:
deep_sleep_btn: >
{% set ns = namespace(found=none) %}
{% for e in states.button
if device_id(e.entity_id) == device_id(trigger.entity_id)
and ('deep_sleep' in e.entity_id
or 'deepsleep' in e.entity_id
or 'sleep' in (e.attributes.friendly_name | lower)) %}
{% set ns.found = e.entity_id %}
{% endfor %}
{{ ns.found }}
- if:
- condition: template
value_template: "{{ deep_sleep_btn != none }}"
then:
- target:
entity_id: "{{ deep_sleep_btn }}"
action: button.press
# ── Branch 2: an update batch just finished (force install OR
# regular auto-update / manual update) ───────────────────────
- conditions:
- condition: trigger
id: finished
sequence:
- variables:
finished_devices: |
{{ trigger.event.data.results
| selectattr('device_id', 'defined')
| list }}
- if:
- condition: template
value_template: "{{ finished_devices | length > 0 }}"
then:
- repeat:
for_each: "{{ finished_devices }}"
sequence:
# Wait for the device to come back online after reboot
- wait_template: >
{% set ns = namespace(online=false) %}
{% for e in states.binary_sensor
if e.entity_id.endswith('_status')
and device_id(e.entity_id) == repeat.item.device_id %}
{% if e.state == 'on' %}{% set ns.online = true %}{% endif %}
{% endfor %}
{{ ns.online }}
timeout: "00:03:00"
continue_on_timeout: true
# Give it its normal awake window (device does its
# tasks now, on this reboot's wake cycle)
- delay: "{{ awake_window_seconds }}"
# Final safety check before sleeping — in case
# something new got queued for it in the meantime
- action: esphome_update_manager.get_device_status
data:
device_id: "{{ repeat.item.device_id }}"
response_variable: dev_status2
- if:
- condition: template
value_template: >
{{ not dev_status2.devices.get(repeat.item.device_id, {}).get('active', false) }}
then:
- variables:
deep_sleep_btn: >
{% set ns = namespace(found=none) %}
{% for e in states.button
if device_id(e.entity_id) == repeat.item.device_id
and ('deep_sleep' in e.entity_id
or 'deepsleep' in e.entity_id
or 'sleep' in (e.attributes.friendly_name | lower)) %}
{% set ns.found = e.entity_id %}
{% endfor %}
{{ ns.found }}
- if:
- condition: template
value_template: "{{ deep_sleep_btn != none }}"
then:
- target:
entity_id: "{{ deep_sleep_btn }}"
action: button.pressOperation of deep sleep devices in combination with the automation:
- If the device wakes and there is no update or force-install pending → enter deep sleep after the time configured in the automation.
- If the device wakes and there is a firmware update, but the device is excluded → enter deep sleep after the time configured in the automation.
- If the device wakes and there is a firmware update and the device is not excluded → the update is performed; after reboot, return to deep sleep after the time configured in the automation.
- If the device wakes and a force-install is pending → the install is performed; after reboot, return to deep sleep after the time configured in the automation.
- When the update or install fails -> return to deep sleep after the time configured in the automation.
The integration handles various failure scenarios gracefully:
| Scenario | Detection | Action |
|---|---|---|
| YAML compile error | Immediate | Marked as failed, queue continues |
| OTA upload failure | Immediate | Marked as failed, queue continues |
| Insufficient memory | Immediate | Marked as failed, queue continues |
| Device offline before update | Immediate | Marked as skipped, queue continues |
| Device goes offline during update | ~2 minutes | Marked as failed, queue continues |
| Device does not recover after OTA | ~2 minutes | Marked as failed, queue continues |
| Update timeout | ~5 minutes | Marked as failed, queue continues |
| External dashboard unreachable | Immediate | Marked as failed, queue continues |
| Authentication failed | Immediate | Marked as failed, queue continues |
A failed device never blocks the rest of the queue. Only an explicit cancel stops all remaining updates.
- The device failed during a previous auto-update
- Auto-update will skip this device until you manually update it successfully
- Click the Update button to manually update the device or select multiple failed devices to update in sequence
- After a successful update, the red indication is removed and auto-update resumes for this device
Behavior:
| Scenario | Result |
|---|---|
| No external URL configured | Always local |
| External URL configured | External has priority |
| YAML on both dashboards + URL configured | External wins |
| No YAML anywhere | Unavailable |
How to switch:
- Add or remove the YAML from the desired dashboard
- Remove and re-add the device entry in the ESPHome integration (No restart of Home Assistant is required)
Note: After adding a YAML to the local dashboard, it may take a moment before HA creates the update entity.
Tip: If the above steps do not give the expected result, try reloading the ESPHome integration or restarting HA.
- Make sure the integration is added via Settings → Devices & Services
- Restart Home Assistant and clear your browser cache
- The add-on must be installed (it does not need to be running)
- Check Home Assistant logs for Supervisor API errors
- Enable the "Stop VS Code Server during updates" option
- Consider stopping other memory-heavy add-ons manually
- Ensure the "Auto install trigger" checkbox is enabled
- Auto-install only triggers on state transitions (e.g., device coming online), not when already in "update available" state
- Check Home Assistant logs for
esphome_update_managerentries
- Ensure the device YAML contains a
projectblock with aversionfield - Check that the auto install scope includes project bumps (
Project onlyorFirmware + Project) - Check that the device is not excluded (see Exclude devices from auto-install)
- Check that the ESPHome dashboard is accessible
- Try clicking the ↻ refresh button next to the scope dropdown
- Check Home Assistant logs for
esphome_update_managerentries
- Verify the ESPHome dashboard is accessible and the device YAML exists
- Check the ESPHome dashboard logs for compile or upload errors
- Ensure the device is online and reachable via OTA
- Check Home Assistant logs for
esphome_update_managerentries
- Verify the device is still in the pending list (visible as Pending in the panel)
- If the regular update queue is running, pending installs are retried every 60 seconds until the queue is free
- Check Home Assistant logs for
esphome_update_managerentries
- Verify the device has a button entity whose entity_id contains
deep_sleep,deepsleep, or whose friendly name containssleep - Verify the device's deep sleep block in YAML does not set
run_duration(otherwise the device sleeps before the button is pressed) - Check the automation traces (Settings → Automations → Deep sleep after force install → Traces) to see which path was taken
- Confirm the
esphome_update_manager_finishedevent contains entries withis_force_install: true(Developer Tools → Events → listen)
- Verify the URL is correct and accessible from Home Assistant (e.g.,
http://192.168.1.100:6052) - Check that the dashboard is running
- If authentication is enabled on the dashboard, ensure you have entered the correct username and password
- Check Home Assistant logs for connection errors
- The dashboard status updates every ~1 minute
- Verify your username and password are correct
- Check that basic authentication is enabled on your external dashboard
- The integration uses HTTP Basic Authentication — other authentication methods are not supported
- Check Home Assistant logs for
401errors
- The external dashboard may be offline — check the dashboard status
- Authentication may have failed — verify your credentials
- Devices will automatically become available when the dashboard reconnects
- Local dashboard devices depend on the firmware entity created by HA (update.<your_device>_firmware)
- A yaml per device must exist in the ESPHome builder app
- This yaml must contain the OTA component
- The device must be added to the ESPHome integration
- When there still is no update entity, backup your yaml and delete it from the builder dashboard, delete the device from the esphome integration, restart HA and add yaml and device again.
- Clear your browser cache and reload the panel
- Ensure the panel is accessible at
/esphome-update-manager
- To clear the skipped update go to Settings → System → Updates → ⋮ menu
To completely remove the integration, follow these steps in order:
- Go to Settings → Devices & Services → ESPHome Update Manager → Delete
- Go to HACS → ESPHome Update Manager → Remove
- Restart Home Assistant
MIT License — see LICENSE for details.
