Skip to content

Instantly share code, notes, and snippets.

@ofalvai
Last active October 8, 2022 20:21
Show Gist options
  • Save ofalvai/4d5b6fd4a7fd31f2495f2846464d4500 to your computer and use it in GitHub Desktop.
Save ofalvai/4d5b6fd4a7fd31f2495f2846464d4500 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)
#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