Skip to content
Get started

Deep Sleep Component

The deep_sleep component can be used to automatically enter a deep sleep mode on the ESP8266/ESP32/BK72xx/nRF52 after a certain amount of time. This is especially useful with nodes that operate on batteries and therefore need to conserve as much energy as possible.

To use deep_sleep first specify how long the node should be active, i.e. how long it should check sensor values and report them, using the run_duration option.

Next, tell the node how it should wakeup. On the ESP8266, you can only put the node into deep sleep for a duration using sleep_duration, note that on the ESP8266 GPIO16 must be connected to the RST pin so that it will wake up again. On the ESP32, you additionally have the option to wake up on any RTC pin (GPIO0, GPIO2, GPIO4, GPIO12, GPIO13, GPIO14, GPIO15, GPIO25, GPIO26, GPIO27, GPIO32, GPIO39). BK72xx can be woken-up using timer (with the maximum value of 36 hours) and/or with one or more non-strapping pins.

While in deep sleep mode, the node will not do any work and not respond to any network traffic, even Over The Air updates. If the device’s entities are appearing as Unavailable while your device is actively sleeping, this component was likely added after the device was added to Home Assistant. To prevent this behavior, you can remove and re-add the device in Home Assistant.

# Example configuration entry
deep_sleep:
run_duration: 10s
sleep_duration: 10min

NOTE

Some ESP8266s have an onboard USB chip (e.g. D1 mini) on the chips’ control line that is connected to the RST pin. This enables the flasher to reboot the ESP when required. This may interfere with deep sleep on some devices and prevent the ESP from waking when it’s powered through its USB connector. Powering the ESP from a separate 3.3V source connected to the 3.3V pin and GND will solve this issue. In these cases, using a USB to TTL adapter will allow you to log ESP activity.

  • run_duration (Optional, Time): The time duration the node should be active, i.e. run code.

    Only on ESP32, instead of time, it is possible to specify run duration according to the wakeup reason from deep-sleep:

    • default (Required, Time): default run duration for timer wakeup and any unspecified wakeup reason.
    • gpio_wakeup_reason (Optional, Time): run duration if woken up by GPIO.
    • touch_wakeup_reason (Optional, Time): run duration if woken up by touch.
  • sleep_duration (Optional, Time): The time duration to stay in deep sleep mode. On BK72xx, the maximum is 36 hours. On Zephyr, the maximum is 49 days.

  • touch_wakeup (Optional, boolean): Only on ESP32. Use a touch event to wakeup from deep sleep. To be able to wakeup from a touch event, Binary Sensor must be configured properly.

  • wakeup_pin (Optional, Pin Schema / list): Only on ESP32/BK72xx. A single pin to wake up to once in deep sleep mode. Use the inverted property to wake up to LOW signals. If you want to specify multiple wake-up pins (BK72xx only) specify them under wakeup_pin using a list of entries consisting of:

    • pin (Required, Pin Schema)
    • wakeup_pin_mode (Optional) see below
  • wakeup_pin_mode (Optional): Only on ESP32/BK72xx. Specify how to handle waking up from a wakeup_pin if the wakeup pin is already in the state with which it would wake up when attempting to enter deep sleep. See Wakeup Pin Mode. Defaults to IGNORE

  • on_wake (Optional, Automation): An automation to run when the device boots after waking from deep sleep. Only on ESP32, ESP8266 and BK72xx. See on_wake Trigger.

  • id (Optional, ID): Manually specify the ID used for code generation.

Advanced features:

  • esp32_ext1_wakeup (Optional): Use the EXT1 wakeup source of the ESP32 to wake from deep sleep to wake up on multiple pins. This cannot be used together with wakeup pin.

    • pins (Required, list): The pins to wake up on. Each entry is either a Pin Schema directly, or a mapping of:
      • pin (Required, Pin Schema): The pin to wake up on.
      • on_wake (Optional, Automation): An automation to run when this specific pin woke the device from deep sleep. See on_wake Trigger.
    • mode (Required): The mode to use for the wakeup source. Must be one of:
      • ANY_LOW: wake up when any selected pin is LOW (ESP32‑C5/C6/C61/H2/P4/S2/S3 only)
      • ALL_LOW: wake up when all selected pins are LOW (ESP32 only)
      • ANY_HIGH: wake up when any selected pin is HIGH

NOTE

Only one deep sleep component may be configured.

On the ESP32 (and BK72xx), you have the option of waking up on any RTC pin. However, there’s one scenario that you need to tell ESPHome how to handle: What if the wakeup pin is already in the state with which it would wake up when the deep sleep should start? There are three ways of handling this using the wakeup_pin_mode option:

  • IGNORE (Default): Ignore the fact that we will immediately exit the deep sleep mode because the wakeup pin is already active.

  • KEEP_AWAKE : Keep the ESP32 awake while the wakeup pin is still active. Or in other words: defer the activation of the deep sleep until the wakeup pin is no longer active.

  • INVERT_WAKEUP : When deep sleep was set up to wake up on a HIGH signal, but the wakeup pin is already HIGH, then re-configure deep sleep to wake up on a LOW signal and vice versa. Useful in situations when you want to use observe the state changes of a pin using deep sleep and the ON/OFF values last longer.

# Example configuration with single pin wakeup on BK72xx
deep_sleep:
wakeup_pin: P8 # will wakeup when P8 is high
wakeup_pin_mode: IGNORE # state of P8 at the moment of going to sleep does not influence the wakeup scenario
# Example configuration with multi-pin wakeup on BK72xx
deep_sleep:
wakeup_pin:
- pin:
number: P8
inverted: True # will wake up when P8 is low
wakeup_pin_mode: KEEP_AWAKE # will prevent sleep as long as P8 is low
- pin: P24 # will wake up when P24 goes high
wakeup_pin_mode: INVERT_WAKEUP # flips the trigger level after each wake

This automation runs once at boot when the device wakes from deep sleep. It does not run after a cold boot, a reset or a restart (for example after an OTA update). It is available on ESP32, ESP8266 and BK72xx.

The variable cause of type deep_sleep::WakeupCause tells you what woke the device:

  • deep_sleep::WAKEUP_CAUSE_TIMER: The sleep timer.
  • deep_sleep::WAKEUP_CAUSE_GPIO: A pin (wakeup_pin or esp32_ext1_wakeup).
  • deep_sleep::WAKEUP_CAUSE_TOUCH: A touch pad.
  • deep_sleep::WAKEUP_CAUSE_UNKNOWN: The device woke from deep sleep, but the source could not be identified.

On the ESP8266, the cause is always deep_sleep::WAKEUP_CAUSE_TIMER, as it can only wake up through the RTC timer.

deep_sleep:
# ...
on_wake:
- if:
condition:
lambda: 'return cause == deep_sleep::WAKEUP_CAUSE_TIMER;'
then:
- logger.log: Woken by the timer

When waking up on multiple pins with esp32_ext1_wakeup, an on_wake automation can also be attached to each pin. It only runs when that pin caused the wakeup. This is useful for devices with multiple buttons that should each do something different when they wake the device:

globals:
- id: page_index
type: int
restore_value: true
initial_value: '0'
deep_sleep:
run_duration: 30s
sleep_duration: 12h
esp32_ext1_wakeup:
mode: ANY_LOW # ESP32‑C5/C6/C61/H2/P4/S2/S3 only
pins:
- pin: GPIO3
on_wake: # left button: previous page
- lambda: 'id(page_index) -= 1;'
- pin: GPIO4
on_wake: # right button: next page
- lambda: 'id(page_index) += 1;'
- pin: GPIO5
on_wake: # green button: cycle view
- script.execute: cycle_view

on_wake automations run after restored global variables have been loaded and before on_boot automations with a priority below 700 (which includes the default priority of 600). This means an on_wake automation can update a global variable that an on_boot automation then uses.

NOTE

With the ALL_LOW mode, all configured pins must be LOW to wake the device, so every pin’s on_wake automation will run.

On the ESP32, the esp_sleep_get_wakeup_cause() function can be used to check which wakeup source has triggered wakeup from sleep mode.

sensor:
- platform: template
name: "Wakeup Cause"
accuracy_decimals: 0
lambda: return esp_sleep_get_wakeup_cause();

The following integers are the wakeup causes:

  • 0 - ESP_SLEEP_WAKEUP_UNDEFINED : In case of deep sleep, reset was not caused by exit from deep sleep
  • 1 - ESP_SLEEP_WAKEUP_ALL : Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source
  • 2 - ESP_SLEEP_WAKEUP_EXT0 : Wakeup caused by external signal using RTC_IO
  • 3 - ESP_SLEEP_WAKEUP_EXT1 : Wakeup caused by external signal using RTC_CNTL
  • 4 - ESP_SLEEP_WAKEUP_TIMER : Wakeup caused by timer
  • 5 - ESP_SLEEP_WAKEUP_TOUCHPAD : Wakeup caused by touchpad
  • 6 - ESP_SLEEP_WAKEUP_ULP : Wakeup caused by ULP program
  • 7 - ESP_SLEEP_WAKEUP_GPIO : Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)
  • 8 - ESP_SLEEP_WAKEUP_UART : Wakeup caused by UART (light sleep only)
  • 9 - ESP_SLEEP_WAKEUP_WIFI : Wakeup caused by WIFI (light sleep only)
  • 10 - ESP_SLEEP_WAKEUP_COCPU : Wakeup caused by COCPU int
  • 11 - ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG : Wakeup caused by COCPU crash
  • 12 - ESP_SLEEP_WAKEUP_BT : Wakeup caused by BT (light sleep only)

When sleep_duration is configured or Zigbee is used, the nRF52 resumes normal operation after waking up. Otherwise, the nRF52 performs a full reset instead of continuing execution.

This action makes the given deep sleep component enter deep sleep immediately.

on_...:
then:
- deep_sleep.enter:
id: deep_sleep_1
sleep_duration: 20min
# Sleep duration is also templatable
on_...:
then:
- deep_sleep.enter:
id: deep_sleep_1
sleep_duration: !lambda "return 20 * 60 * 1000;"
# ESP32 can sleep until a specific time of day.
on_...:
then:
- deep_sleep.enter:
id: deep_sleep_1
until: "16:00:00"
time_id: sntp_id

Configuration options:

  • sleep_duration (Optional, templatable, Time): The time duration to stay in deep sleep mode. If a template is used, it should return a value in milliseconds.
  • until (Optional, string): The time of day to wake up. Only on ESP32.
  • time_id (Optional, ID): The ID of the time component to use for the until option. Only on ESP32.

This action prevents the given deep sleep component from entering deep sleep. Useful for keeping the ESP active during data transfer or OTA updating (See note below for more information).

on_...:
then:
- deep_sleep.prevent: deep_sleep_1

NOTE

For example, if you want to upload a binary via OTA with deep sleep mode it can be difficult to catch the ESP being active.

You can use this automation to automatically prevent deep sleep when a MQTT message on the topic livingroom/ota_mode is received. Then, to do the OTA update, just use a MQTT client to publish a retained MQTT message described below. When the node wakes up again it will no longer enter deep sleep mode and you can upload your OTA update.

Remember to turn “OTA mode” off again after the OTA update by sending a MQTT message with the payload OFF. To enter the deep sleep again after the OTA update send a message on the topic livingroom/sleep_mode with payload ON. Deep sleep will start immediately. Don’t forget to delete the payload before the node wakes up again.

deep_sleep:
# ...
id: deep_sleep_1
mqtt:
# ...
on_message:
- topic: livingroom/ota_mode
payload: 'ON'
then:
- deep_sleep.prevent: deep_sleep_1
- topic: livingroom/sleep_mode
payload: 'ON'
then:
- deep_sleep.enter: deep_sleep_1

This action allows the given deep sleep component to enter deep sleep, after previously being prevented.

on_...:
then:
- deep_sleep.allow: deep_sleep_1

On platforms with bootloader OTA rollback support enabled — the default on ESP32 with the esp-idf framework and on nRF52, see enable_ota_rollback for ESP32 and nRF52 — firmware installed by an OTA update must be confirmed as working, otherwise the bootloader reverts to the previous version on the next reset. The safe_mode component confirms the new firmware once it considers the boot successful.

Since ESPHome 2026.8.0, entering deep sleep counts as a successful boot: the firmware is confirmed automatically just before the device goes to sleep. No configuration is needed, and a device that crashes before the firmware is confirmed still rolls back, as intended.

If you want stricter rollback semantics, set boot_is_good_on_shutdown: false in the safe_mode configuration. Then only boot_is_good_after elapsing or the safe_mode.mark_successful action confirms the firmware — an update that goes back to sleep before proving itself healthy is rolled back on the next wake. For example, new firmware with a bug that enters deep sleep before Wi-Fi or OTA ever comes up would be confirmed by that first sleep with the default behavior; with the option disabled and safe_mode.mark_successful placed after the device’s real work (e.g. after a successful sensor publish), the bootloader reverts it instead.

WARNING

On versions before 2026.8.0, a device that enters deep sleep before boot_is_good_after (default 1 minute) elapses never confirms the new firmware, so the bootloader rolls back every OTA update on the next wake — the update silently uninstalls itself. On these versions, use one of the following workarounds:

  • Set boot_is_good_after in the safe_mode configuration to a value shorter than the device’s awake time, e.g. boot_is_good_after: 10s.
  • Run the safe_mode.mark_successful action (available since ESPHome 2026.3.0) before entering deep sleep, for example in on_boot.
  • Disable rollback entirely with enable_ota_rollback: false under esp32: framework: advanced: (or nrf52: framework: advanced:).