-
-
Save ashmckenzie/a73df0a4e0564f61c6c3baf36c62cca7 to your computer and use it in GitHub Desktop.
Custom ESPHome deep sleep component that's controlled via MQTT (adjustable sleep duration, sleep enter trigger)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "esphome.h" | |
#include "driver/rtc_io.h" | |
class CustomSleepComponent : public Component, public CustomMQTTDevice { | |
public: | |
void setup() override { | |
subscribe(TOPIC_SLEEP_DURATION, &CustomSleepComponent::on_sleep_duration_message); | |
subscribe(TOPIC_SLEEP_PREVENT, &CustomSleepComponent::on_prevent_message); | |
subscribe(TOPIC_SLEEP_ENTER, &CustomSleepComponent::on_enter_message); | |
rtc_gpio_hold_dis(GPIO_NUM_4); // Opposite of rtc_gpio_hold_en() that's called before sleep | |
} | |
private: | |
static constexpr auto LOG_TAG = "custom_sleep"; | |
static constexpr auto TOPIC_SLEEP_DURATION = "mailbox_camera/sleep_duration"; | |
static constexpr auto TOPIC_SLEEP_PREVENT = "mailbox_camera/switch/ota_mode/command"; | |
static constexpr auto TOPIC_SLEEP_ENTER = "mailbox_camera/sleep"; | |
static constexpr auto DEFAULT_RUN_DURATION_S = 30; | |
unsigned long sleep_duration_s = 0; | |
bool prevent = false; | |
void on_sleep_duration_message(const std::string &payload) { | |
this->sleep_duration_s = strtoul(payload.c_str(), NULL, 10); | |
if (this->sleep_duration_s == 0) { | |
ESP_LOGE(LOG_TAG, "Failed to parse sleep duration: %s", payload.c_str()); | |
return; | |
} | |
ESP_LOGD(LOG_TAG, "Sleep duration: %lu s", this->sleep_duration_s); | |
} | |
void on_prevent_message(const std::string &payload) { | |
if (payload == "ON") { | |
this->prevent = true; | |
ESP_LOGD(LOG_TAG, "Prevent deep sleep: ON"); | |
} else if (payload == "OFF") { | |
this->prevent = false; | |
ESP_LOGD(LOG_TAG, "Prevent deep sleep: OFF"); | |
this->set_timeout(DEFAULT_RUN_DURATION_S * 1000, [this]() { this->begin_sleep(); }); | |
} | |
} | |
void on_enter_message(const std::string &payload) { | |
if (this->prevent) { | |
ESP_LOGD(LOG_TAG, "Not entering deep sleep because prevent is ON"); | |
return; | |
} | |
ESP_LOGD(LOG_TAG, "Beginning deep sleep"); | |
begin_sleep(); | |
} | |
void begin_sleep() { | |
esp_err_t result = esp_sleep_enable_timer_wakeup(sleep_duration_s * 1000 * 1000); | |
if (result != ESP_OK) { | |
ESP_LOGE(LOG_TAG, "Failed to enable timer wakeup: %d", result); | |
return; | |
} | |
delay(500); // Allow last messages to be sent over MQTT | |
App.run_safe_shutdown_hooks(); | |
rtc_gpio_hold_en(GPIO_NUM_4); // Prevents LED flash turning on in sleep | |
esp_deep_sleep_start(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment