ESPHome Can't Prevent Deep Sleep

Hi,

I’ve been searching all week and can’t seem to prevent my ESP8266 D1 Mini from entering deep sleep. No matter what I’ve tried, my ESP just keeps going back into deep sleep after publishing sensor data. I’ve found a lot of guides to follow, but haven’t made much progress.

One forum post suggested changing deep_sleep.enter to deep_sleep.allow, but I just get an error saying "Unable to find action with the name 'deep_sleep.allow'."

Can I please have some help?

Home Assistant Helper:
input_boolean.esphome_disable_deep_sleep

Node Red Flow:

Node Red MQTT Publish

MQTT Explorer:
(proof that the Home Assistant helper is successfully publishing over MQTT)

ESPHome Config:
(I’ve trimmed out all the disabled sensors)


################################################################################
# Define variables
################################################################################

substitutions:
  # Device Properties
  devicename: dev-air-quality
  friendly_name: Dev-Air-Quality
  devicetopic: AirQuality
  log_tag: yaml
  
  # Sleep Properties
  sleep_time: 5s #1min #5min #10s
  run_time: 5s #1s

  # Pinout
  # Wake        D0  # GPIO16  - Wake (deep sleep) - high at boot.
  pin_i2c_scl:  D1  # GPIO5
  pin_i2c_sda:  D2  # GPIO4
  # Reserved    D3  # GPIO0   - biased high - connected to flash button 
  # Reserved    D4  # GPIO2   - biased high - connected to on-board LED
  pin_rx:       D5  # GPIO14
  pin_tx:       D6  # GPIO12
  pin_dht:      D7  # GPIO13
  #             D8  # GPIO15  - biased low
  #             RX  # GPIO3
  #             TX  # GPIO1   - debug output at boot
  #             A0  # ADC0


################################################################################
# Define Device
################################################################################

esphome:
  name: $devicename
  on_boot:
    #- lambda: 'ESP_LOGE("${log_tag}", "Booted");'
    - logger.log:
        format: "Normal Boot"
        level: ERROR
#  on_loop:
  on_shutdown:
    - logger.log:
        format: "Normal Deep Sleep"
        level: ERROR

esp8266:
  board: d1_mini

# Enable logging
logger:
  level: DEBUG
  on_message:
    level: WARN
    then:
      - mqtt.publish:
          topic: $devicetopic/logger
          payload: !lambda |-
            return "Level: " + to_string(level) + " ||| Tag: " + tag + " ||| Message: " + message;

# Enable Home Assistant API
#api:
#  password: !secret api_password

# Enable Over-The-Air flashing
ota:
  #safe_mode: True
  password: !secret ota_password
  on_end:
    - logger.log:
        format: "OTA Update"
        level: ERROR


################################################################################
# Power
################################################################################

deep_sleep:
  id: deep_sleep_1
  sleep_duration: $sleep_time
  run_duration: $run_time


################################################################################
# Wireless Access
################################################################################

wifi:
  id: wifi_client
  fast_connect: true # Skip wifi scan to save time.
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  
  # Set a static IP address.
  manual_ip:
    static_ip: redacted
    gateway: redacted
    subnet: redacted
  # If changing the name or the IP address of the device, this provides the old address so that ESPHome knows which device to overwrite.
  use_address: "192.168.86.200"


mqtt:
  id: mqtt_client
  broker: !secret mqtt_broker
  port: !secret mqtt_port
  username: !secret mqtt_user
  password: !secret mqtt_password
  discovery: true
  discovery_retain: true
  # Set empty birth and will messages to avoid showing unavailable during sleep
  birth_message:
  will_message:
  topic_prefix: $devicetopic
  on_message:
    # Disable Deep Sleep
    - topic: admin/esphome_disable_deep_sleep
      qos: 0                                          #1
      payload: 'ON'
      then:
        - logger.log:
            format: 'MQTT Admin: disable deep sleep'
            level: ERROR
        - deep_sleep.prevent: deep_sleep_1
    # Allow Deep Sleep
    - topic: admin/esphome_disable_deep_sleep
      qos: 0                                          #1
      payload: 'OFF'
      then:
        #- lambda: 'ESP_LOGE("${log_tag}", "MQTT Admin: enter deep sleep");'
        - logger.log:
            format: 'MQTT Admin: entering deep sleep'
            level: ERROR
        - deep_sleep.enter: deep_sleep_1


################################################################################
# Communication Protocols
################################################################################

i2c:
  sda: $pin_i2c_sda
  scl: $pin_i2c_scl
  id: bus_i2c
  scan: False       # Save time by skipping the I2C scan on startup, since all addresses are known. Defaults to True
  frequency: 50kHz  # Defaults to 50kHz, SCD30 can't handle more than 100kHz.

uart:
  baud_rate: 9600
  rx_pin: $pin_rx
  #tx_pin: $pin_tx  # Not needed for SCD30 or SGP30


################################################################################
# Functionality
################################################################################

# Air Quality, Temperature and Humidity.
sensor:
  # DHT11 Temperature and Humidity Sensor
  - platform: dht
    model: DHT11
    pin: $pin_dht
    temperature:
      name: "$friendly_name Temperature"
      id: temperature
    humidity:
      name: "$friendly_name Humidity"
      id: humidity
    update_interval: $sleep_time

I think (and I’m sure that someone will correct me if I’m wrong) that ‘ON’ doesn’t equal ‘on’.

MQTT topics are case sensitive and I think values are too.

2 Likes

Any particular reasons why you don’t want to go with the native api but with mqtt instead?

The docs probably not updated yet but the native api got an recent improvement that ha now connects immediatly to the esphome node once it announces it’s availability. In best case there shouldn’t be much of a difference now to mqtt. For deep_sleep.prevent you can than just use the input_boolean.esphome_disable_deep_sleep from ha directly (native api goodness :tada:

1 Like

Thanks. That worked :slight_smile:
I changed ON and OFF to on and off

It was because I read about the API not connecting fast enough or because data was frequently missed. But everything I had read was probably outdated anyway.
If API is now just as fast and reliable as MQTT, I would absolutely prefer to use that.

1 Like

I have the same error "Unable to find action with the name ‘deep sleep allow’. I also understand that this thread discusses the possible better solution of using the native interface. I have used the following code in the esphome device:

deep_sleep:
run_duration: 10min
sleep_duration: 5min
id: deep_sleep_control

binary_sensor:

  • platform: homeassistant
    id: deep_sleep_devices
    entity_id: input_boolean.deep_sleep_devices
    on_release:
    then:
    - logger.log: “Prevent deep sleep”
    - deep_sleep.prevent: deep_sleep_control
    on_press:
    then:
    - logger.log: “Allow deep sleep”
    - deep_sleep.allow: deep_sleep_control

I get the error on the last line. It seems that deep_sleep.prevent works, but not deep_sleep.allow. Can someone describe how to use the ‘native interface’ to prevent or allow deep sleep based on a homeassistant sensor value?

I’d be grateful for help and a native api solution overview.

Please have a read - especially regarding formatting. Also you are posting in a solved topic, you may have better luck starting a new one.

Hey Maurelius,

I also couldn’t get deep_sleep.allow to work. I honestly gave up and went back to code that made use of deep_sleep.enter.

With regards to using the Home Assistant API instead of MQTT, I did actually try that after posting this but I couldn’t make it work efficiently. I was definitely losing data, and I had to keep the ESP alive for around 10s through a delay (since run_duration was replaced) as opposed to 1s with MQTT.
I hope that API can replace MQTT, but I couldn’t make it work in the time I spent on it.

Thank you zoogara. I have read the “good questions” guide. I will improve my questions in future and follow the posting guide (and particularly posting code, not text).

Thank you mortalitas. I have the same experience as you. I can’t get deep_sleep.allow to work. The moment I change the code (not format) from deep_sleep.prevent to deep_sleep.allow, it immediately provides an error that it doesn’t recognise the deep_sleep.allow action . I won’t waste further time on deep_sleep.allow and will find and implement a deep_sleep.enter solution. If deep_sleep.allow was recognised, it would be simple code for a quick outcome.

1 Like

This is the working code I’m currently using. Although, as you can see, it’s not finished or cleaned up.
If you use this, you will still need to follow the Node Red and HA Helper steps in my original post.
This is MQTT code, but you’ll see my API code commented out.

A note for anybody reading this: I’m a hardware engineer with very limited real world software experience. I’m very open to feedback, but just know that my code isn’t going to be great.

# Hardware
# Tie D0 (GPIO16/Wake) to RST to allow the ESP8266 to wake from deep sleep. Remove when flashing over USB.
# Use D1 and D2 for I2C, SCL and SDA respectively.
# Avoid using the following pins, which are needed for various boot purposes.
#   • GPIO0  - D3 - biased high - connected to flash button 
#   • GPIO2  - D4 - biased high - conencted to on-board LED
#   • GPIO15 - D8 - biased low


################################################################################
# Define variables
################################################################################

substitutions:
  # Device Properties
  devicename: dev-air-quality
  friendly_name: Dev-Air-Quality
  device_topic: AirQuality
  device_sleephelper: input_boolean.esphome_disable_deep_sleep
  device_sleephelper_topic: admin/esphome_disable_deep_sleep
  
  # Logger Properties
  # This is used for the ESP_LOGx syntax, but not logger.log.
  log_tag: yaml
  
  # Sleep Properties
  sleep_time: 54s #2min #10s #2min #1min #5min #10s
  # For API mode, run time needs to be roughly 10s. 5s failed because there wasn't enough time to read the binary sensor and prevent deeps sleep. The minimum run time is probably betwen 5s and 10s.
  run_time: 2s #1s
  # The sensor will report data on boot, and then again for each sensor on their independent update_interval parameters until put to sleep again.
  # Set update interval to a longer time than run_time to ensure only 1 data update per wake.
  # I suspect that the update interval still has to be shorter than sleep time though. Otherwise, the device seems to wake up and not publish.
  global_update_interval: $sleep_time
  
  # Sensor Properties
  #temperature_offset: -3.0

  # Pinout
  # Wake        D0  # GPIO16  - Wake (deep sleep) - high at boot.
  pin_i2c_scl:  D1  # GPIO5
  pin_i2c_sda:  D2  # GPIO4
  # Reserved    D3  # GPIO0   - biased high - connected to flash button 
  # Reserved    D4  # GPIO2   - biased high - connected to on-board LED
  pin_rx:       D5  # GPIO14
  pin_tx:       D6  # GPIO12
  pin_dht:      D7  # GPIO13
  #             D8  # GPIO15  - biased low
  #             RX  # GPIO3
  #             TX  # GPIO1   - debug output at boot
  #             A0  # ADC0

globals:
  - id: shutdown_reason
    type: std::string
    restore_value: no
    initial_value: '"normal deep sleep"'


################################################################################
# Define Device
################################################################################

esphome:
  name: $devicename
  
  on_boot:
    then:
      - logger.log:
          format: "Booted"
          level: INFO
        # Enable this for API mode. Disable for MQTT.
#      - script.execute: consider_deep_sleep

  on_loop:
    #- lambda: |-           # functions to measure connection time, errors and stuff.

  on_shutdown:
    #- lambda: 'ESP_LOGE("${log_tag}", "Normal Deep Sleep");'
    - logger.log:
        format: "Normal Deep Sleep"
        level: INFO

esp8266:
  board: d1_mini

# Enable logging
logger:
  level: DEBUG #WARN
  # Publish logs to MQTT
  on_message:
    level: WARN
    then:
      - mqtt.publish:
          topic: $device_topic/logger
          payload: !lambda |-
            return "Level: " + to_string(level) + " ||| Tag: " + tag + " ||| Message: " + message;
  

# Enable Over-The-Air flashing
ota:
  #safe_mode: True
  password: !secret ota_password
  on_end:
    - logger.log:
        format: "OTA Update"
        level: INFO
    #- lambda: 'ESP_LOGE("${log_tag}", "OTA Update");'

################################################################################
# Power
################################################################################

deep_sleep:
  id: deep_sleep_control
  sleep_duration: $sleep_time
  # Disable run_duration if using API and helpder instead of MQTT.
  run_duration: $run_time


################################################################################
# Wireless Access
################################################################################

wifi:
  id: wifi_client
  fast_connect: true # Skip wifi scan to save time.
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  
  # Set a static IP address.
  manual_ip:
    static_ip: 192.168.86.200
    gateway: 192.168.86.1
    subnet: 255.255.255.0
  # If changing the name or the IP address of the device, this provides the old address so that ESPHome knows which device to overwrite.
  use_address: "192.168.86.200"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  #ap:
  #  ssid: "$devicename Fallback Hotspot"
  #  password: !secret wifi_recoveryhotspot_password
# Part of fallback hotspot in case wifi connection fails.
#captive_portal:


################################################################################
# Home Assistant Connection
################################################################################
# Choose API or MQTT, but not both.

# Enable Home Assistant API
  # Enable script execution in on_boot command.
  # Disable run_duration from the deep sleep config. This is replaced by an on_boot script.
  # Disable MQTT portion of logger config.
#api:
#  password: !secret api_password

#binary_sensor:
#  - platform: homeassistant
#    id: prevent_deep_sleep
#    name: Prevent Deep Sleep
#    entity_id: $device_sleephelper
    
# Script used in API mide to consider deep sleep. This replaces the run_duration parameter in the deep sleep configuration.
#script:
#  - id: consider_deep_sleep
#    mode: queued
#    then:
#      - delay: $run_time
#      - if:
#          condition:
#            binary_sensor.is_on: prevent_deep_sleep
#          then:
#            - logger.log:
#                format: 'MQTT Admin: disable deep sleep'
#                level: INFO
#          else:
#            - logger.log:
#                format: 'MQTT Admin: entering deep sleep'
#                level: INFO
#            - deep_sleep.enter:
#      - script.execute: consider_deep_sleep


# Enable MQTT
  # Enable run_duration from the deep sleep config.
  # This requires Node Red to publish on $device_sleephelper_topic whenever the Home Assistant helper changes state.
  # Disable script from on_boot command.
  # Enable MQTT portion of logger config.
mqtt:
  id: mqtt_client
  broker: !secret mqtt_broker
  port: !secret mqtt_port
  username: !secret mqtt_user
  password: !secret mqtt_password
  discovery: true
  discovery_retain: true
  # Set empty birth and will messages to avoid showing unavailable during sleep
  birth_message:
  will_message:
  topic_prefix: $device_topic
  on_message:
    - topic: $device_sleephelper_topic
      qos: 0                                          #1
      payload: 'on'
      then:
        - logger.log:
            format: 'MQTT Admin: disable deep sleep'
            level: INFO
        - deep_sleep.prevent: deep_sleep_control
        #- lambda: 'ESP_LOGE("${log_tag}", "MQTT Admin: disable deep sleep");'
    - topic: $device_sleephelper_topic
      qos: 0                                          #1
      payload: 'off'
      then:
        #- lambda: 'ESP_LOGE("${log_tag}", "MQTT Admin: enter deep sleep");'
        - logger.log:
            format: 'MQTT Admin: entering deep sleep'
            level: INFO
        - deep_sleep.enter: deep_sleep_control

################################################################################
# Communication Protocols
################################################################################

i2c:
  sda: $pin_i2c_sda
  scl: $pin_i2c_scl
  id: bus_i2c
  scan: False       # Save time by skipping the I2C scan on startup since all addresses are known. Defaults to True
  frequency: 50kHz  # Defaults to 50kHz, SCD30 can't handle more than 100kHz.

uart:
  baud_rate: 9600
  rx_pin: $pin_rx
  #tx_pin: $pin_tx  # Not needed for SCD30 or SGP30


################################################################################
# Functionality
################################################################################

# Air Quality, Temperature and Humidity.
sensor:
  # Sensor uptime             # Doesn't do what I thought it would. Disabling for now.
  #- platform: uptime
  #  name: "$friendly_name Uptime"
  #  id: device_uptime
    
  # DHT11 Temperature and Humidity Sensor
  - platform: dht
    model: DHT11
    pin: $pin_dht
    temperature:
      name: "$friendly_name Temperature"
      id: temperature
      #filters: # Only needed because the DHT temperature sensor in the bedroom is too close to the ESP8266. Deep sleep mostly solves this anyway. This is an old solution that didn't work.
      #  - offset: $temperature_offset
    humidity:
      name: "$friendly_name Humidity"
      id: humidity
    update_interval: $global_update_interval
    
  # CO2, Temperature and Humidity
  - platform: scd30
    i2c_id: bus_i2c
    address: 0x61
    automatic_self_calibration: true
    update_interval: $global_update_interval
    co2:
      name: "$friendly_name CO2"
      id: co2
      accuracy_decimals: 1
    temperature:
      name: "$friendly_name Temperature SCD"
      id: temperature_scd
      accuracy_decimals: 2
      filters:
        - offset: 0
    humidity:
      name: "$friendly_name Humidity SCD"
      id: humidity_scd
      accuracy_decimals: 1
    #temperature_offset: 1.5 °C
    
  # TVOC, Estimated CO2
  - platform: sgp30
    i2c_id: bus_i2c
    address: 0x58
    store_baseline: yes
    update_interval: $global_update_interval
    eco2:
      name: "$friendly_name eCO2"
      id: eco2
      accuracy_decimals: 1
    tvoc:
      name: "$friendly_name TVOC"
      id: tvoc
      accuracy_decimals: 1
      
  # Particulate Matter Concentration
#  - platform: pmsx003
#    type: PMSX003
#    pm_1_0:
#      name: "$friendly_name PM <1.0µm"
#    pm_2_5:
#      name: "$friendly_name PM <2.5µm"
#    pm_10_0:
#      name: "$friendly_name PM <10.0µm"


# Add Restart Switch
# I never got this working. I'll look at it again when I need it.
#switch:
#  - platform: restart
#    id: reboot_esp
#    name: "$devicename Restart Switch"

Hi, not sure if you found the solution to this elsewhere, but I’ve just had success with this. My main fix was adding a ‘wait until’ the HASS API was available on boot, and then adding a small delay, seems to work well now.
e.g.

on_boot:
  - wait_until:
    - api.connected
  - delay: 5s

I then add my entity checking 'If" condition to either prevent or allow deep sleep on boot.

Hope that helps?
Andy…