From f431c7402f0cdcc8fa032302a5ebe77d8020648a Mon Sep 17 00:00:00 2001 From: jsuanet <75206491+jsuanet@users.noreply.github.com> Date: Mon, 20 Dec 2021 22:25:36 +0100 Subject: [PATCH] Add shutdown and safe_mode button (#2918) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Jos Suanet --- CODEOWNERS | 4 +-- esphome/components/safe_mode/__init__.py | 2 +- .../components/safe_mode/button/__init__.py | 36 +++++++++++++++++++ .../safe_mode/button/safe_mode_button.cpp | 25 +++++++++++++ .../safe_mode/button/safe_mode_button.h | 21 +++++++++++ esphome/components/shutdown/__init__.py | 2 +- .../components/shutdown/button/__init__.py | 23 ++++++++++++ .../shutdown/button/shutdown_button.cpp | 33 +++++++++++++++++ .../shutdown/button/shutdown_button.h | 18 ++++++++++ .../{switch.py => switch/__init__.py} | 0 .../shutdown/{ => switch}/shutdown_switch.cpp | 0 .../shutdown/{ => switch}/shutdown_switch.h | 0 tests/test4.yaml | 4 +++ 13 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 esphome/components/safe_mode/button/__init__.py create mode 100644 esphome/components/safe_mode/button/safe_mode_button.cpp create mode 100644 esphome/components/safe_mode/button/safe_mode_button.h create mode 100644 esphome/components/shutdown/button/__init__.py create mode 100644 esphome/components/shutdown/button/shutdown_button.cpp create mode 100644 esphome/components/shutdown/button/shutdown_button.h rename esphome/components/shutdown/{switch.py => switch/__init__.py} (100%) rename esphome/components/shutdown/{ => switch}/shutdown_switch.cpp (100%) rename esphome/components/shutdown/{ => switch}/shutdown_switch.h (100%) diff --git a/CODEOWNERS b/CODEOWNERS index fed6815a66..452c560938 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -133,7 +133,7 @@ esphome/components/restart/* @esphome/core esphome/components/rf_bridge/* @jesserockz esphome/components/rgbct/* @jesserockz esphome/components/rtttl/* @glmnet -esphome/components/safe_mode/* @paulmonigatti +esphome/components/safe_mode/* @jsuanet @paulmonigatti esphome/components/scd4x/* @sjtrny esphome/components/script/* @esphome/core esphome/components/sdm_meter/* @jesserockz @polyfaces @@ -143,7 +143,7 @@ esphome/components/select/* @esphome/core esphome/components/sensor/* @esphome/core esphome/components/sgp40/* @SenexCrenshaw esphome/components/sht4x/* @sjtrny -esphome/components/shutdown/* @esphome/core +esphome/components/shutdown/* @esphome/core @jsuanet esphome/components/sim800l/* @glmnet esphome/components/sm2135/* @BoukeHaarsma23 esphome/components/socket/* @esphome/core diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index f150d6e086..ab884bfee4 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -1,5 +1,5 @@ import esphome.codegen as cg -CODEOWNERS = ["@paulmonigatti"] +CODEOWNERS = ["@paulmonigatti", "@jsuanet"] safe_mode_ns = cg.esphome_ns.namespace("safe_mode") diff --git a/esphome/components/safe_mode/button/__init__.py b/esphome/components/safe_mode/button/__init__.py new file mode 100644 index 0000000000..2cd8892afb --- /dev/null +++ b/esphome/components/safe_mode/button/__init__.py @@ -0,0 +1,36 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import button +from esphome.components.ota import OTAComponent +from esphome.const import ( + CONF_ID, + CONF_OTA, + DEVICE_CLASS_RESTART, + ENTITY_CATEGORY_CONFIG, + ICON_RESTART_ALERT, +) + +DEPENDENCIES = ["ota"] + +safe_mode_ns = cg.esphome_ns.namespace("safe_mode") +SafeModeButton = safe_mode_ns.class_("SafeModeButton", button.Button, cg.Component) + +CONFIG_SCHEMA = ( + button.button_schema( + device_class=DEVICE_CLASS_RESTART, + entity_category=ENTITY_CATEGORY_CONFIG, + icon=ICON_RESTART_ALERT, + ) + .extend({cv.GenerateID(): cv.declare_id(SafeModeButton)}) + .extend({cv.GenerateID(CONF_OTA): cv.use_id(OTAComponent)}) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await button.register_button(var, config) + + ota = await cg.get_variable(config[CONF_OTA]) + cg.add(var.set_ota(ota)) diff --git a/esphome/components/safe_mode/button/safe_mode_button.cpp b/esphome/components/safe_mode/button/safe_mode_button.cpp new file mode 100644 index 0000000000..2b8654de46 --- /dev/null +++ b/esphome/components/safe_mode/button/safe_mode_button.cpp @@ -0,0 +1,25 @@ +#include "safe_mode_button.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" + +namespace esphome { +namespace safe_mode { + +static const char *const TAG = "safe_mode.button"; + +void SafeModeButton::set_ota(ota::OTAComponent *ota) { this->ota_ = ota; } + +void SafeModeButton::press_action() { + ESP_LOGI(TAG, "Restarting device in safe mode..."); + this->ota_->set_safe_mode_pending(true); + + // Let MQTT settle a bit + delay(100); // NOLINT + App.safe_reboot(); +} + +void SafeModeButton::dump_config() { LOG_BUTTON("", "Safe Mode Button", this); } + +} // namespace safe_mode +} // namespace esphome diff --git a/esphome/components/safe_mode/button/safe_mode_button.h b/esphome/components/safe_mode/button/safe_mode_button.h new file mode 100644 index 0000000000..63e0d1755e --- /dev/null +++ b/esphome/components/safe_mode/button/safe_mode_button.h @@ -0,0 +1,21 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/ota/ota_component.h" +#include "esphome/components/button/button.h" + +namespace esphome { +namespace safe_mode { + +class SafeModeButton : public button::Button, public Component { + public: + void dump_config() override; + void set_ota(ota::OTAComponent *ota); + + protected: + ota::OTAComponent *ota_; + void press_action() override; +}; + +} // namespace safe_mode +} // namespace esphome diff --git a/esphome/components/shutdown/__init__.py b/esphome/components/shutdown/__init__.py index f70ffa9520..480a6f3e31 100644 --- a/esphome/components/shutdown/__init__.py +++ b/esphome/components/shutdown/__init__.py @@ -1 +1 @@ -CODEOWNERS = ["@esphome/core"] +CODEOWNERS = ["@esphome/core", "@jsuanet"] diff --git a/esphome/components/shutdown/button/__init__.py b/esphome/components/shutdown/button/__init__.py new file mode 100644 index 0000000000..51cd6d6da2 --- /dev/null +++ b/esphome/components/shutdown/button/__init__.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import button +from esphome.const import ( + CONF_ID, + ENTITY_CATEGORY_CONFIG, + ICON_POWER, +) + +shutdown_ns = cg.esphome_ns.namespace("shutdown") +ShutdownButton = shutdown_ns.class_("ShutdownButton", button.Button, cg.Component) + +CONFIG_SCHEMA = ( + button.button_schema(entity_category=ENTITY_CATEGORY_CONFIG, icon=ICON_POWER) + .extend({cv.GenerateID(): cv.declare_id(ShutdownButton)}) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await button.register_button(var, config) diff --git a/esphome/components/shutdown/button/shutdown_button.cpp b/esphome/components/shutdown/button/shutdown_button.cpp new file mode 100644 index 0000000000..be88a10d49 --- /dev/null +++ b/esphome/components/shutdown/button/shutdown_button.cpp @@ -0,0 +1,33 @@ +#include "shutdown_button.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/application.h" + +#ifdef USE_ESP32 +#include +#endif +#ifdef USE_ESP8266 +#include +#endif + +namespace esphome { +namespace shutdown { + +static const char *const TAG = "shutdown.button"; + +void ShutdownButton::dump_config() { LOG_BUTTON("", "Shutdown Button", this); } +void ShutdownButton::press_action() { + ESP_LOGI(TAG, "Shutting down..."); + // Let MQTT settle a bit + delay(100); // NOLINT + App.run_safe_shutdown_hooks(); +#ifdef USE_ESP8266 + ESP.deepSleep(0); // NOLINT(readability-static-accessed-through-instance) +#endif +#ifdef USE_ESP32 + esp_deep_sleep_start(); +#endif +} + +} // namespace shutdown +} // namespace esphome diff --git a/esphome/components/shutdown/button/shutdown_button.h b/esphome/components/shutdown/button/shutdown_button.h new file mode 100644 index 0000000000..d0094c899d --- /dev/null +++ b/esphome/components/shutdown/button/shutdown_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/button/button.h" + +namespace esphome { +namespace shutdown { + +class ShutdownButton : public button::Button, public Component { + public: + void dump_config() override; + + protected: + void press_action() override; +}; + +} // namespace shutdown +} // namespace esphome diff --git a/esphome/components/shutdown/switch.py b/esphome/components/shutdown/switch/__init__.py similarity index 100% rename from esphome/components/shutdown/switch.py rename to esphome/components/shutdown/switch/__init__.py diff --git a/esphome/components/shutdown/shutdown_switch.cpp b/esphome/components/shutdown/switch/shutdown_switch.cpp similarity index 100% rename from esphome/components/shutdown/shutdown_switch.cpp rename to esphome/components/shutdown/switch/shutdown_switch.cpp diff --git a/esphome/components/shutdown/shutdown_switch.h b/esphome/components/shutdown/switch/shutdown_switch.h similarity index 100% rename from esphome/components/shutdown/shutdown_switch.h rename to esphome/components/shutdown/switch/shutdown_switch.h diff --git a/tests/test4.yaml b/tests/test4.yaml index 545806ba87..7c1ddee6d8 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -531,3 +531,7 @@ xpt2046: button: - platform: restart name: Restart Button + - platform: safe_mode + name: Safe Mode Button + - platform: shutdown + name: Shutdown Button