From 4a8422164172de8c769ef5a96b90683204c99fcf Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 21 Oct 2025 16:48:50 -0400 Subject: [PATCH 01/14] Add a WiFi power mode debug text sensor --- esphome/components/debug/debug_component.cpp | 1 + esphome/components/debug/debug_component.h | 24 ++++++++++- esphome/components/debug/debug_esp32.cpp | 40 ++++++++++++++++++ esphome/components/debug/debug_esp8266.cpp | 41 +++++++++++++++++++ esphome/components/debug/debug_libretiny.cpp | 22 ++++++++++ esphome/components/debug/debug_rp2040.cpp | 41 ++++++++++++++++++- esphome/components/debug/text_sensor.py | 13 ++++++ tests/components/debug/test.bk72xx-ard.yaml | 9 ++++ tests/components/debug/test.esp32-ard.yaml | 9 ++++ tests/components/debug/test.esp32-idf.yaml | 9 ++++ tests/components/debug/test.esp32-s2-idf.yaml | 9 ++++ tests/components/debug/test.esp8266-ard.yaml | 9 ++++ tests/components/debug/test.ln882x-ard.yaml | 9 ++++ .../components/debug/test.nrf52-xiao-ble.yaml | 9 ++++ tests/components/debug/test.rp2040-ard.yaml | 9 ++++ tests/components/fan/test.esp8266-ard.yaml | 9 ++++ 16 files changed, 261 insertions(+), 2 deletions(-) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index f54bf82eae0..790635e6c7b 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -18,6 +18,7 @@ void DebugComponent::dump_config() { ESP_LOGCONFIG(TAG, "Debug component:"); #ifdef USE_TEXT_SENSOR LOG_TEXT_SENSOR(" ", "Device info", this->device_info_); + LOG_TEXT_SENSOR(" ", "WiFi Power Save Mode", this->wifi_power_save_); #endif // USE_TEXT_SENSOR #ifdef USE_SENSOR LOG_SENSOR(" ", "Free space on heap", this->free_sensor_); diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 96306f7cdfe..5b3c34a1b6e 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -10,7 +10,18 @@ #endif #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" -#endif +#ifdef USE_WIFI +#ifdef USE_ESP32 +#include +#elif defined(USE_ESP8266) +extern "C" { +#include +} +#elif defined(USE_RP2040) +#include +#endif // USE_ESP32 / USE_ESP8266 / USE_RP2040 +#endif // USE_WIFI +#endif // USE_TEXT_SENSOR namespace esphome { namespace debug { @@ -25,6 +36,7 @@ class DebugComponent : public PollingComponent { #ifdef USE_TEXT_SENSOR void set_device_info_sensor(text_sensor::TextSensor *device_info) { device_info_ = device_info; } void set_reset_reason_sensor(text_sensor::TextSensor *reset_reason) { reset_reason_ = reset_reason; } + void set_wifi_power_save_sensor(text_sensor::TextSensor *wifi_power_save) { wifi_power_save_ = wifi_power_save; } #endif // USE_TEXT_SENSOR #ifdef USE_SENSOR void set_free_sensor(sensor::Sensor *free_sensor) { free_sensor_ = free_sensor; } @@ -79,6 +91,16 @@ class DebugComponent : public PollingComponent { #ifdef USE_TEXT_SENSOR text_sensor::TextSensor *device_info_{nullptr}; text_sensor::TextSensor *reset_reason_{nullptr}; + text_sensor::TextSensor *wifi_power_save_{nullptr}; +#if defined(USE_WIFI) && defined(USE_ESP32) + wifi_ps_type_t last_wifi_ps_mode_{}; +#elif defined(USE_WIFI) && defined(USE_ESP8266) + sleep_type_t last_wifi_sleep_type_{}; +#elif defined(USE_WIFI) && defined(USE_RP2040) + uint32_t last_wifi_pm_{CYW43_PERFORMANCE_PM}; +#elif defined(USE_WIFI) && defined(USE_LIBRETINY) + bool last_wifi_sleep_{false}; +#endif #endif // USE_TEXT_SENSOR std::string get_reset_reason_(); diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 1c3dc3699b8..3d84b3a235b 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -11,6 +11,10 @@ #include #include +#ifdef USE_WIFI +#include +#endif + #ifdef USE_ARDUINO #include #endif @@ -44,6 +48,29 @@ static const char *const RESET_REASONS[] = { static const char *const REBOOT_KEY = "reboot_source"; static const size_t REBOOT_MAX_LEN = 24; +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) +/// @brief Helper function to convert ESP32 WiFi power save mode to string +/// @param ps_mode WiFi power save mode from esp_wifi_get_ps() +/// @return const char pointer to the readable power save mode +/// +/// Maps ESP32 WiFi power save modes to user-friendly strings: +/// - WIFI_PS_NONE (no power saving) -> "NONE" +/// - WIFI_PS_MIN_MODEM (minimal modem sleep) -> "LIGHT" +/// - WIFI_PS_MAX_MODEM (maximum modem sleep) -> "HIGH" +static const char *wifi_ps_mode_to_string(wifi_ps_type_t ps_mode) { + switch (ps_mode) { + case WIFI_PS_NONE: + return "NONE"; + case WIFI_PS_MIN_MODEM: + return "LIGHT"; + case WIFI_PS_MAX_MODEM: + return "HIGH"; + default: + return "UNKNOWN"; + } +} +#endif // USE_TEXT_SENSOR && USE_WIFI + // on shutdown, store the source of the reboot request void DebugComponent::on_shutdown() { auto *component = App.get_current_component(); @@ -234,6 +261,19 @@ void DebugComponent::update_platform_() { this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); } #endif + +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) + if (this->wifi_power_save_ != nullptr) { + wifi_ps_type_t power_save_mode; + if (esp_wifi_get_ps(&power_save_mode) == ESP_OK) { + // Publish if the state has changed or if this is the first read + if (this->last_wifi_ps_mode_ != power_save_mode || !this->wifi_power_save_->has_state()) { + this->wifi_power_save_->publish_state(wifi_ps_mode_to_string(power_save_mode)); + this->last_wifi_ps_mode_ = power_save_mode; + } + } + } +#endif } } // namespace debug diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 3395d9db121..c8429014107 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -3,11 +3,41 @@ #include "esphome/core/log.h" #include +#ifdef USE_WIFI +extern "C" { +#include +} +#endif + namespace esphome { namespace debug { static const char *const TAG = "debug"; +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) +/// @brief Helper function to convert ESP8266 WiFi sleep type to string +/// @param sleep_type WiFi sleep type from wifi_get_sleep_type() +/// @return const char pointer to the readable sleep type +/// +/// Maps ESP8266 WiFi sleep types to user-friendly strings: +/// - NONE_SLEEP_T (no sleep) -> "NONE" +/// - LIGHT_SLEEP_T (light sleep) -> "LIGHT" +/// - MODEM_SLEEP_T (modem sleep) -> "HIGH" +/// - RF_CAL_SLEEP_T (RF calibration sleep) -> "UNKNOWN" (special mode, rarely used) +static const char *wifi_sleep_type_to_string(sleep_type_t sleep_type) { + switch (sleep_type) { + case NONE_SLEEP_T: + return "NONE"; + case LIGHT_SLEEP_T: + return "LIGHT"; + case MODEM_SLEEP_T: + return "HIGH"; + default: + return "UNKNOWN"; + } +} +#endif // USE_TEXT_SENSOR && USE_WIFI + std::string DebugComponent::get_reset_reason_() { #if !defined(CLANG_TIDY) return ESP.getResetReason().c_str(); @@ -87,6 +117,17 @@ void DebugComponent::update_platform_() { #endif #endif + +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) + if (this->wifi_power_save_ != nullptr) { + sleep_type_t sleep_type = wifi_get_sleep_type(); + // Publish if the state has changed or if this is the first read + if (this->last_wifi_sleep_type_ != sleep_type || !this->wifi_power_save_->has_state()) { + this->wifi_power_save_->publish_state(wifi_sleep_type_to_string(sleep_type)); + this->last_wifi_sleep_type_ = sleep_type; + } + } +#endif } } // namespace debug diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index b5e2a5b3103..a09daa8ea12 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -7,6 +7,17 @@ namespace debug { static const char *const TAG = "debug"; +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) +/// @brief Helper function to convert LibreTiny WiFi sleep state to string +/// @param sleep_enabled WiFi sleep enabled state from WiFi.getSleep() +/// @return const char pointer to the readable sleep state +/// +/// LibreTiny WiFi sleep is a boolean on/off setting: +/// - true (sleep enabled) -> "ON" +/// - false (sleep disabled) -> "OFF" +static const char *wifi_sleep_to_string(bool sleep_enabled) { return sleep_enabled ? "ON" : "OFF"; } +#endif // USE_TEXT_SENSOR && USE_WIFI + std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_name(lt_get_reboot_reason()); } uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } @@ -37,6 +48,17 @@ void DebugComponent::update_platform_() { this->block_sensor_->publish_state(lt_heap_get_max_alloc()); } #endif + +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) + if (this->wifi_power_save_ != nullptr) { + bool sleep_enabled = WiFi.getSleep(); + // Publish if the state has changed or if this is the first read + if (this->last_wifi_sleep_ != sleep_enabled || !this->wifi_power_save_->has_state()) { + this->wifi_power_save_->publish_state(wifi_sleep_to_string(sleep_enabled)); + this->last_wifi_sleep_ = sleep_enabled; + } + } +#endif } } // namespace debug diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index 497547e30d7..8892d36323b 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -2,11 +2,39 @@ #ifdef USE_RP2040 #include "esphome/core/log.h" #include + +#ifdef USE_WIFI +#include +#endif + namespace esphome { namespace debug { static const char *const TAG = "debug"; +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) +/// @brief Helper function to convert RP2040 CYW43 WiFi power mode to string +/// @param pm WiFi power mode from cyw43_state.pm +/// @return const char pointer to the readable power mode +/// +/// Maps RP2040 CYW43 WiFi power modes to user-friendly strings: +/// - CYW43_PERFORMANCE_PM (no power saving) -> "NONE" +/// - CYW43_DEFAULT_PM (default power saving) -> "LIGHT" +/// - CYW43_AGGRESSIVE_PM (aggressive power saving) -> "HIGH" +static const char *wifi_pm_to_string(uint32_t pm) { + switch (pm) { + case CYW43_PERFORMANCE_PM: + return "NONE"; + case CYW43_DEFAULT_PM: + return "LIGHT"; + case CYW43_AGGRESSIVE_PM: + return "HIGH"; + default: + return "UNKNOWN"; + } +} +#endif // USE_TEXT_SENSOR && USE_WIFI + std::string DebugComponent::get_reset_reason_() { return ""; } uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); } @@ -16,7 +44,18 @@ void DebugComponent::get_device_info_(std::string &device_info) { device_info += "CPU Frequency: " + to_string(rp2040.f_cpu()); } -void DebugComponent::update_platform_() {} +void DebugComponent::update_platform_() { +#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) + if (this->wifi_power_save_ != nullptr) { + uint32_t pm = cyw43_state.pm; + // Publish if the state has changed or if this is the first read + if (this->last_wifi_pm_ != pm || !this->wifi_power_save_->has_state()) { + this->wifi_power_save_->publish_state(wifi_pm_to_string(pm)); + this->last_wifi_pm_ = pm; + } + } +#endif +} } // namespace debug } // namespace esphome diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 96ef2318501..11b0b4b7578 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -3,9 +3,11 @@ from esphome.components import text_sensor import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE, + CONF_POWER_SAVE_MODE, ENTITY_CATEGORY_DIAGNOSTIC, ICON_CHIP, ICON_RESTART, + ICON_WIFI, ) from . import CONF_DEBUG_ID, DebugComponent @@ -25,6 +27,14 @@ CONFIG_SCHEMA = cv.Schema( icon=ICON_RESTART, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), + cv.Optional(CONF_POWER_SAVE_MODE): cv.All( + text_sensor.text_sensor_schema( + icon=ICON_WIFI, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.only_on(["esp32", "esp8266", "rp2040", "bk72xx", "rtl87xx"]), + cv.requires_component("wifi"), + ), } ) @@ -38,3 +48,6 @@ async def to_code(config): if CONF_RESET_REASON in config: sens = await text_sensor.new_text_sensor(config[CONF_RESET_REASON]) cg.add(debug_component.set_reset_reason_sensor(sens)) + if CONF_POWER_SAVE_MODE in config: + sens = await text_sensor.new_text_sensor(config[CONF_POWER_SAVE_MODE]) + cg.add(debug_component.set_wifi_power_save_sensor(sens)) diff --git a/tests/components/debug/test.bk72xx-ard.yaml b/tests/components/debug/test.bk72xx-ard.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.bk72xx-ard.yaml +++ b/tests/components/debug/test.bk72xx-ard.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.esp32-ard.yaml b/tests/components/debug/test.esp32-ard.yaml index 8e19a4d6277..ff6e34a8451 100644 --- a/tests/components/debug/test.esp32-ard.yaml +++ b/tests/components/debug/test.esp32-ard.yaml @@ -1,4 +1,13 @@ <<: !include common.yaml +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" + esp32: cpu_frequency: 240MHz diff --git a/tests/components/debug/test.esp32-idf.yaml b/tests/components/debug/test.esp32-idf.yaml index f7483a54b3b..96e16113922 100644 --- a/tests/components/debug/test.esp32-idf.yaml +++ b/tests/components/debug/test.esp32-idf.yaml @@ -3,6 +3,15 @@ esp32: cpu_frequency: 240MHz +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" + sensor: - platform: debug free: diff --git a/tests/components/debug/test.esp32-s2-idf.yaml b/tests/components/debug/test.esp32-s2-idf.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.esp32-s2-idf.yaml +++ b/tests/components/debug/test.esp32-s2-idf.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.esp8266-ard.yaml b/tests/components/debug/test.esp8266-ard.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.esp8266-ard.yaml +++ b/tests/components/debug/test.esp8266-ard.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.ln882x-ard.yaml b/tests/components/debug/test.ln882x-ard.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.ln882x-ard.yaml +++ b/tests/components/debug/test.ln882x-ard.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.nrf52-xiao-ble.yaml b/tests/components/debug/test.nrf52-xiao-ble.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.nrf52-xiao-ble.yaml +++ b/tests/components/debug/test.nrf52-xiao-ble.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.rp2040-ard.yaml b/tests/components/debug/test.rp2040-ard.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/debug/test.rp2040-ard.yaml +++ b/tests/components/debug/test.rp2040-ard.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/fan/test.esp8266-ard.yaml b/tests/components/fan/test.esp8266-ard.yaml index dade44d145b..b1b6cebd7c7 100644 --- a/tests/components/fan/test.esp8266-ard.yaml +++ b/tests/components/fan/test.esp8266-ard.yaml @@ -1 +1,10 @@ <<: !include common.yaml + +wifi: + ssid: "WIFI SSID" + password: "WIFI PASSWORD" + +text_sensor: + - platform: debug + power_save_mode: + name: "WiFi Power Save Mode" From a3677daee152f3044da36c65d4bf0a969f8a0ffc Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 22 Oct 2025 11:13:28 -0400 Subject: [PATCH 02/14] ln882x doesn't support it, so remove it --- tests/components/debug/test.ln882x-ard.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/components/debug/test.ln882x-ard.yaml b/tests/components/debug/test.ln882x-ard.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.ln882x-ard.yaml +++ b/tests/components/debug/test.ln882x-ard.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" From 5115aeeb2ba69614eb48a9e4265c41ecc748026b Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 22 Oct 2025 11:46:56 -0400 Subject: [PATCH 03/14] remove untested support for rp2040 and libretiny platforms --- esphome/components/debug/debug_component.h | 8 +--- esphome/components/debug/debug_libretiny.cpp | 22 ----------- esphome/components/debug/debug_rp2040.cpp | 41 +------------------- esphome/components/debug/text_sensor.py | 2 +- tests/components/debug/test.bk72xx-ard.yaml | 9 ----- tests/components/debug/test.rp2040-ard.yaml | 9 ----- 6 files changed, 3 insertions(+), 88 deletions(-) diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 5b3c34a1b6e..3a3e41bffb2 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -17,9 +17,7 @@ extern "C" { #include } -#elif defined(USE_RP2040) -#include -#endif // USE_ESP32 / USE_ESP8266 / USE_RP2040 +#endif // USE_ESP32 / USE_ESP8266 #endif // USE_WIFI #endif // USE_TEXT_SENSOR @@ -96,10 +94,6 @@ class DebugComponent : public PollingComponent { wifi_ps_type_t last_wifi_ps_mode_{}; #elif defined(USE_WIFI) && defined(USE_ESP8266) sleep_type_t last_wifi_sleep_type_{}; -#elif defined(USE_WIFI) && defined(USE_RP2040) - uint32_t last_wifi_pm_{CYW43_PERFORMANCE_PM}; -#elif defined(USE_WIFI) && defined(USE_LIBRETINY) - bool last_wifi_sleep_{false}; #endif #endif // USE_TEXT_SENSOR diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index a09daa8ea12..b5e2a5b3103 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -7,17 +7,6 @@ namespace debug { static const char *const TAG = "debug"; -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) -/// @brief Helper function to convert LibreTiny WiFi sleep state to string -/// @param sleep_enabled WiFi sleep enabled state from WiFi.getSleep() -/// @return const char pointer to the readable sleep state -/// -/// LibreTiny WiFi sleep is a boolean on/off setting: -/// - true (sleep enabled) -> "ON" -/// - false (sleep disabled) -> "OFF" -static const char *wifi_sleep_to_string(bool sleep_enabled) { return sleep_enabled ? "ON" : "OFF"; } -#endif // USE_TEXT_SENSOR && USE_WIFI - std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_name(lt_get_reboot_reason()); } uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } @@ -48,17 +37,6 @@ void DebugComponent::update_platform_() { this->block_sensor_->publish_state(lt_heap_get_max_alloc()); } #endif - -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) - if (this->wifi_power_save_ != nullptr) { - bool sleep_enabled = WiFi.getSleep(); - // Publish if the state has changed or if this is the first read - if (this->last_wifi_sleep_ != sleep_enabled || !this->wifi_power_save_->has_state()) { - this->wifi_power_save_->publish_state(wifi_sleep_to_string(sleep_enabled)); - this->last_wifi_sleep_ = sleep_enabled; - } - } -#endif } } // namespace debug diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index 8892d36323b..497547e30d7 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -2,39 +2,11 @@ #ifdef USE_RP2040 #include "esphome/core/log.h" #include - -#ifdef USE_WIFI -#include -#endif - namespace esphome { namespace debug { static const char *const TAG = "debug"; -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) -/// @brief Helper function to convert RP2040 CYW43 WiFi power mode to string -/// @param pm WiFi power mode from cyw43_state.pm -/// @return const char pointer to the readable power mode -/// -/// Maps RP2040 CYW43 WiFi power modes to user-friendly strings: -/// - CYW43_PERFORMANCE_PM (no power saving) -> "NONE" -/// - CYW43_DEFAULT_PM (default power saving) -> "LIGHT" -/// - CYW43_AGGRESSIVE_PM (aggressive power saving) -> "HIGH" -static const char *wifi_pm_to_string(uint32_t pm) { - switch (pm) { - case CYW43_PERFORMANCE_PM: - return "NONE"; - case CYW43_DEFAULT_PM: - return "LIGHT"; - case CYW43_AGGRESSIVE_PM: - return "HIGH"; - default: - return "UNKNOWN"; - } -} -#endif // USE_TEXT_SENSOR && USE_WIFI - std::string DebugComponent::get_reset_reason_() { return ""; } uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); } @@ -44,18 +16,7 @@ void DebugComponent::get_device_info_(std::string &device_info) { device_info += "CPU Frequency: " + to_string(rp2040.f_cpu()); } -void DebugComponent::update_platform_() { -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) - if (this->wifi_power_save_ != nullptr) { - uint32_t pm = cyw43_state.pm; - // Publish if the state has changed or if this is the first read - if (this->last_wifi_pm_ != pm || !this->wifi_power_save_->has_state()) { - this->wifi_power_save_->publish_state(wifi_pm_to_string(pm)); - this->last_wifi_pm_ = pm; - } - } -#endif -} +void DebugComponent::update_platform_() {} } // namespace debug } // namespace esphome diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 11b0b4b7578..196fd98bd06 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -32,7 +32,7 @@ CONFIG_SCHEMA = cv.Schema( icon=ICON_WIFI, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), - cv.only_on(["esp32", "esp8266", "rp2040", "bk72xx", "rtl87xx"]), + cv.only_on(["esp32", "esp8266"]), cv.requires_component("wifi"), ), } diff --git a/tests/components/debug/test.bk72xx-ard.yaml b/tests/components/debug/test.bk72xx-ard.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.bk72xx-ard.yaml +++ b/tests/components/debug/test.bk72xx-ard.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" diff --git a/tests/components/debug/test.rp2040-ard.yaml b/tests/components/debug/test.rp2040-ard.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.rp2040-ard.yaml +++ b/tests/components/debug/test.rp2040-ard.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" From 8c6917fe8b16f81d28262573a48c76a10e3ee315 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 22 Oct 2025 12:24:44 -0400 Subject: [PATCH 04/14] only implement for esp32 --- esphome/components/debug/debug_component.h | 12 +----- esphome/components/debug/debug_esp8266.cpp | 41 -------------------- esphome/components/debug/text_sensor.py | 2 +- tests/components/debug/test.esp8266-ard.yaml | 9 ----- 4 files changed, 3 insertions(+), 61 deletions(-) diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 3a3e41bffb2..86217e9ae47 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -10,15 +10,9 @@ #endif #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" -#ifdef USE_WIFI -#ifdef USE_ESP32 +#if defined(USE_WIFI) && defined(USE_ESP32) #include -#elif defined(USE_ESP8266) -extern "C" { -#include -} -#endif // USE_ESP32 / USE_ESP8266 -#endif // USE_WIFI +#endif #endif // USE_TEXT_SENSOR namespace esphome { @@ -92,8 +86,6 @@ class DebugComponent : public PollingComponent { text_sensor::TextSensor *wifi_power_save_{nullptr}; #if defined(USE_WIFI) && defined(USE_ESP32) wifi_ps_type_t last_wifi_ps_mode_{}; -#elif defined(USE_WIFI) && defined(USE_ESP8266) - sleep_type_t last_wifi_sleep_type_{}; #endif #endif // USE_TEXT_SENSOR diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index c8429014107..3395d9db121 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -3,41 +3,11 @@ #include "esphome/core/log.h" #include -#ifdef USE_WIFI -extern "C" { -#include -} -#endif - namespace esphome { namespace debug { static const char *const TAG = "debug"; -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) -/// @brief Helper function to convert ESP8266 WiFi sleep type to string -/// @param sleep_type WiFi sleep type from wifi_get_sleep_type() -/// @return const char pointer to the readable sleep type -/// -/// Maps ESP8266 WiFi sleep types to user-friendly strings: -/// - NONE_SLEEP_T (no sleep) -> "NONE" -/// - LIGHT_SLEEP_T (light sleep) -> "LIGHT" -/// - MODEM_SLEEP_T (modem sleep) -> "HIGH" -/// - RF_CAL_SLEEP_T (RF calibration sleep) -> "UNKNOWN" (special mode, rarely used) -static const char *wifi_sleep_type_to_string(sleep_type_t sleep_type) { - switch (sleep_type) { - case NONE_SLEEP_T: - return "NONE"; - case LIGHT_SLEEP_T: - return "LIGHT"; - case MODEM_SLEEP_T: - return "HIGH"; - default: - return "UNKNOWN"; - } -} -#endif // USE_TEXT_SENSOR && USE_WIFI - std::string DebugComponent::get_reset_reason_() { #if !defined(CLANG_TIDY) return ESP.getResetReason().c_str(); @@ -117,17 +87,6 @@ void DebugComponent::update_platform_() { #endif #endif - -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) - if (this->wifi_power_save_ != nullptr) { - sleep_type_t sleep_type = wifi_get_sleep_type(); - // Publish if the state has changed or if this is the first read - if (this->last_wifi_sleep_type_ != sleep_type || !this->wifi_power_save_->has_state()) { - this->wifi_power_save_->publish_state(wifi_sleep_type_to_string(sleep_type)); - this->last_wifi_sleep_type_ = sleep_type; - } - } -#endif } } // namespace debug diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 196fd98bd06..74027a694df 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -32,7 +32,7 @@ CONFIG_SCHEMA = cv.Schema( icon=ICON_WIFI, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), - cv.only_on(["esp32", "esp8266"]), + cv.only_on(["esp32"]), cv.requires_component("wifi"), ), } diff --git a/tests/components/debug/test.esp8266-ard.yaml b/tests/components/debug/test.esp8266-ard.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.esp8266-ard.yaml +++ b/tests/components/debug/test.esp8266-ard.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" From 3934c1563c060e19363c9cb0d611d0ee453dca9f Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 19 Nov 2025 07:51:18 -0500 Subject: [PATCH 05/14] Fix bad rebase --- tests/components/debug/test.nrf52-xiao-ble.yaml | 9 --------- tests/components/fan/test.esp8266-ard.yaml | 9 --------- 2 files changed, 18 deletions(-) diff --git a/tests/components/debug/test.nrf52-xiao-ble.yaml b/tests/components/debug/test.nrf52-xiao-ble.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.nrf52-xiao-ble.yaml +++ b/tests/components/debug/test.nrf52-xiao-ble.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" diff --git a/tests/components/fan/test.esp8266-ard.yaml b/tests/components/fan/test.esp8266-ard.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/fan/test.esp8266-ard.yaml +++ b/tests/components/fan/test.esp8266-ard.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" From 8ffdfc2aad73468ede4a0b95a7b35ab50ba16f9f Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 14:01:01 -0500 Subject: [PATCH 06/14] move sensor to wifi_info --- esphome/components/debug/debug_component.cpp | 1 - esphome/components/debug/debug_component.h | 8 ---- esphome/components/debug/debug_esp32.cpp | 40 ------------------- esphome/components/debug/text_sensor.py | 13 ------ esphome/components/wifi_info/text_sensor.py | 14 +++++++ .../wifi_info/wifi_info_text_sensor.cpp | 38 ++++++++++++++++++ .../wifi_info/wifi_info_text_sensor.h | 15 +++++++ tests/components/debug/test.esp32-ard.yaml | 9 ----- tests/components/debug/test.esp32-idf.yaml | 9 ----- tests/components/debug/test.esp32-s2-idf.yaml | 9 ----- .../components/wifi_info/test.esp32-ard.yaml | 9 +++++ .../components/wifi_info/test.esp32-idf.yaml | 5 +++ 12 files changed, 81 insertions(+), 89 deletions(-) create mode 100644 tests/components/wifi_info/test.esp32-ard.yaml diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index 790635e6c7b..f54bf82eae0 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -18,7 +18,6 @@ void DebugComponent::dump_config() { ESP_LOGCONFIG(TAG, "Debug component:"); #ifdef USE_TEXT_SENSOR LOG_TEXT_SENSOR(" ", "Device info", this->device_info_); - LOG_TEXT_SENSOR(" ", "WiFi Power Save Mode", this->wifi_power_save_); #endif // USE_TEXT_SENSOR #ifdef USE_SENSOR LOG_SENSOR(" ", "Free space on heap", this->free_sensor_); diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 86217e9ae47..c997ad7bd78 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -10,9 +10,6 @@ #endif #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" -#if defined(USE_WIFI) && defined(USE_ESP32) -#include -#endif #endif // USE_TEXT_SENSOR namespace esphome { @@ -28,7 +25,6 @@ class DebugComponent : public PollingComponent { #ifdef USE_TEXT_SENSOR void set_device_info_sensor(text_sensor::TextSensor *device_info) { device_info_ = device_info; } void set_reset_reason_sensor(text_sensor::TextSensor *reset_reason) { reset_reason_ = reset_reason; } - void set_wifi_power_save_sensor(text_sensor::TextSensor *wifi_power_save) { wifi_power_save_ = wifi_power_save; } #endif // USE_TEXT_SENSOR #ifdef USE_SENSOR void set_free_sensor(sensor::Sensor *free_sensor) { free_sensor_ = free_sensor; } @@ -83,10 +79,6 @@ class DebugComponent : public PollingComponent { #ifdef USE_TEXT_SENSOR text_sensor::TextSensor *device_info_{nullptr}; text_sensor::TextSensor *reset_reason_{nullptr}; - text_sensor::TextSensor *wifi_power_save_{nullptr}; -#if defined(USE_WIFI) && defined(USE_ESP32) - wifi_ps_type_t last_wifi_ps_mode_{}; -#endif #endif // USE_TEXT_SENSOR std::string get_reset_reason_(); diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 3d84b3a235b..1c3dc3699b8 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -11,10 +11,6 @@ #include #include -#ifdef USE_WIFI -#include -#endif - #ifdef USE_ARDUINO #include #endif @@ -48,29 +44,6 @@ static const char *const RESET_REASONS[] = { static const char *const REBOOT_KEY = "reboot_source"; static const size_t REBOOT_MAX_LEN = 24; -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) -/// @brief Helper function to convert ESP32 WiFi power save mode to string -/// @param ps_mode WiFi power save mode from esp_wifi_get_ps() -/// @return const char pointer to the readable power save mode -/// -/// Maps ESP32 WiFi power save modes to user-friendly strings: -/// - WIFI_PS_NONE (no power saving) -> "NONE" -/// - WIFI_PS_MIN_MODEM (minimal modem sleep) -> "LIGHT" -/// - WIFI_PS_MAX_MODEM (maximum modem sleep) -> "HIGH" -static const char *wifi_ps_mode_to_string(wifi_ps_type_t ps_mode) { - switch (ps_mode) { - case WIFI_PS_NONE: - return "NONE"; - case WIFI_PS_MIN_MODEM: - return "LIGHT"; - case WIFI_PS_MAX_MODEM: - return "HIGH"; - default: - return "UNKNOWN"; - } -} -#endif // USE_TEXT_SENSOR && USE_WIFI - // on shutdown, store the source of the reboot request void DebugComponent::on_shutdown() { auto *component = App.get_current_component(); @@ -261,19 +234,6 @@ void DebugComponent::update_platform_() { this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); } #endif - -#if defined(USE_TEXT_SENSOR) && defined(USE_WIFI) - if (this->wifi_power_save_ != nullptr) { - wifi_ps_type_t power_save_mode; - if (esp_wifi_get_ps(&power_save_mode) == ESP_OK) { - // Publish if the state has changed or if this is the first read - if (this->last_wifi_ps_mode_ != power_save_mode || !this->wifi_power_save_->has_state()) { - this->wifi_power_save_->publish_state(wifi_ps_mode_to_string(power_save_mode)); - this->last_wifi_ps_mode_ = power_save_mode; - } - } - } -#endif } } // namespace debug diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 74027a694df..96ef2318501 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -3,11 +3,9 @@ from esphome.components import text_sensor import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE, - CONF_POWER_SAVE_MODE, ENTITY_CATEGORY_DIAGNOSTIC, ICON_CHIP, ICON_RESTART, - ICON_WIFI, ) from . import CONF_DEBUG_ID, DebugComponent @@ -27,14 +25,6 @@ CONFIG_SCHEMA = cv.Schema( icon=ICON_RESTART, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), - cv.Optional(CONF_POWER_SAVE_MODE): cv.All( - text_sensor.text_sensor_schema( - icon=ICON_WIFI, - entity_category=ENTITY_CATEGORY_DIAGNOSTIC, - ), - cv.only_on(["esp32"]), - cv.requires_component("wifi"), - ), } ) @@ -48,6 +38,3 @@ async def to_code(config): if CONF_RESET_REASON in config: sens = await text_sensor.new_text_sensor(config[CONF_RESET_REASON]) cg.add(debug_component.set_reset_reason_sensor(sens)) - if CONF_POWER_SAVE_MODE in config: - sens = await text_sensor.new_text_sensor(config[CONF_POWER_SAVE_MODE]) - cg.add(debug_component.set_wifi_power_save_sensor(sens)) diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index bc0c038f804..8cc0c4e66fe 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -6,9 +6,11 @@ from esphome.const import ( CONF_DNS_ADDRESS, CONF_IP_ADDRESS, CONF_MAC_ADDRESS, + CONF_POWER_SAVE_MODE, CONF_SCAN_RESULTS, CONF_SSID, ENTITY_CATEGORY_DIAGNOSTIC, + ICON_WIFI, ) DEPENDENCIES = ["wifi"] @@ -30,6 +32,9 @@ MacAddressWifiInfo = wifi_info_ns.class_( DNSAddressWifiInfo = wifi_info_ns.class_( "DNSAddressWifiInfo", text_sensor.TextSensor, cg.Component ) +PowerSaveModeWiFiInfo = wifi_info_ns.class_( + "PowerSaveModeWiFiInfo", text_sensor.TextSensor, cg.PollingComponent +) CONFIG_SCHEMA = cv.Schema( { @@ -57,6 +62,14 @@ CONFIG_SCHEMA = cv.Schema( ), cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( DNSAddressWifiInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC + ).extend(cv.polling_component_schema("1s")), + cv.Optional(CONF_POWER_SAVE_MODE): cv.All( + text_sensor.text_sensor_schema( + PowerSaveModeWiFiInfo, + icon=ICON_WIFI, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ).extend(cv.polling_component_schema("1s")), + cv.only_on(["esp32"]), ), } ) @@ -90,6 +103,7 @@ async def to_code(config): await setup_conf(config, CONF_SCAN_RESULTS) wifi.request_wifi_scan_results() await setup_conf(config, CONF_DNS_ADDRESS) + await setup_conf(config, CONF_POWER_SAVE_MODE) if conf := config.get(CONF_IP_ADDRESS): wifi_info = await text_sensor.new_text_sensor(config[CONF_IP_ADDRESS]) await cg.register_component(wifi_info, config[CONF_IP_ADDRESS]) diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index 6c9d0c00e57..360cd979ea4 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -6,6 +6,29 @@ namespace esphome::wifi_info { static const char *const TAG = "wifi_info"; +#ifdef USE_ESP32 +/// @brief Helper function to convert ESP32 WiFi power save mode to string +/// @param ps_mode WiFi power save mode from esp_wifi_get_ps() +/// @return const char pointer to the readable power save mode +/// +/// Maps ESP32 WiFi power save modes to user-friendly strings: +/// - WIFI_PS_NONE (no power saving) -> "NONE" +/// - WIFI_PS_MIN_MODEM (minimal modem sleep) -> "LIGHT" +/// - WIFI_PS_MAX_MODEM (maximum modem sleep) -> "HIGH" +static const char *wifi_ps_mode_to_string(wifi_ps_type_t ps_mode) { + switch (ps_mode) { + case WIFI_PS_NONE: + return "NONE"; + case WIFI_PS_MIN_MODEM: + return "LIGHT"; + case WIFI_PS_MAX_MODEM: + return "HIGH"; + default: + return "UNKNOWN"; + } +} +#endif // USE_ESP32 + #ifdef USE_WIFI_LISTENERS static constexpr size_t MAX_STATE_LENGTH = 255; @@ -108,5 +131,20 @@ void BSSIDWiFiInfo::on_wifi_connect_state(const std::string &ssid, const wifi::b void MacAddressWifiInfo::dump_config() { LOG_TEXT_SENSOR("", "MAC Address", this); } +#ifdef USE_ESP32 +void PowerSaveModeWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "WiFi Power Save Mode", this); } + +void PowerSaveModeWiFiInfo::update() { + wifi_ps_type_t power_save_mode; + if (esp_wifi_get_ps(&power_save_mode) == ESP_OK) { + // Publish if the state has changed or if this is the first read + if (this->last_power_save_mode_ != power_save_mode || !this->has_state()) { + this->publish_state(wifi_ps_mode_to_string(power_save_mode)); + this->last_power_save_mode_ = power_save_mode; + } + } +} +#endif // USE_ESP32 + } // namespace esphome::wifi_info #endif diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index f1f85c114fa..78afcad43fb 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -6,6 +6,9 @@ #include "esphome/components/wifi/wifi_component.h" #ifdef USE_WIFI #include +#ifdef USE_ESP32 +#include +#endif // USE_ESP32 namespace esphome::wifi_info { @@ -74,5 +77,17 @@ class MacAddressWifiInfo final : public Component, public text_sensor::TextSenso void dump_config() override; }; +#ifdef USE_ESP32 +class PowerSaveModeWiFiInfo : public PollingComponent, public text_sensor::TextSensor { + public: + void update() override; + float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + void dump_config() override; + + protected: + wifi_ps_type_t last_power_save_mode_{}; +}; +#endif // USE_ESP32 + } // namespace esphome::wifi_info #endif diff --git a/tests/components/debug/test.esp32-ard.yaml b/tests/components/debug/test.esp32-ard.yaml index ff6e34a8451..8e19a4d6277 100644 --- a/tests/components/debug/test.esp32-ard.yaml +++ b/tests/components/debug/test.esp32-ard.yaml @@ -1,13 +1,4 @@ <<: !include common.yaml -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" - esp32: cpu_frequency: 240MHz diff --git a/tests/components/debug/test.esp32-idf.yaml b/tests/components/debug/test.esp32-idf.yaml index 96e16113922..f7483a54b3b 100644 --- a/tests/components/debug/test.esp32-idf.yaml +++ b/tests/components/debug/test.esp32-idf.yaml @@ -3,15 +3,6 @@ esp32: cpu_frequency: 240MHz -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" - sensor: - platform: debug free: diff --git a/tests/components/debug/test.esp32-s2-idf.yaml b/tests/components/debug/test.esp32-s2-idf.yaml index b1b6cebd7c7..dade44d145b 100644 --- a/tests/components/debug/test.esp32-s2-idf.yaml +++ b/tests/components/debug/test.esp32-s2-idf.yaml @@ -1,10 +1 @@ <<: !include common.yaml - -wifi: - ssid: "WIFI SSID" - password: "WIFI PASSWORD" - -text_sensor: - - platform: debug - power_save_mode: - name: "WiFi Power Save Mode" diff --git a/tests/components/wifi_info/test.esp32-ard.yaml b/tests/components/wifi_info/test.esp32-ard.yaml new file mode 100644 index 00000000000..3393e33898f --- /dev/null +++ b/tests/components/wifi_info/test.esp32-ard.yaml @@ -0,0 +1,9 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml + +<<: !include common.yaml + +text_sensor: + - platform: wifi_info + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/wifi_info/test.esp32-idf.yaml b/tests/components/wifi_info/test.esp32-idf.yaml index b47e39c3898..648bdf47c98 100644 --- a/tests/components/wifi_info/test.esp32-idf.yaml +++ b/tests/components/wifi_info/test.esp32-idf.yaml @@ -2,3 +2,8 @@ packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml <<: !include common.yaml + +text_sensor: + - platform: wifi_info + power_save_mode: + name: "WiFi Power Save Mode" From 7dfd20fb4f335a47a763661755b6502392e00d1b Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 14:10:43 -0500 Subject: [PATCH 07/14] remove arduino test --- esphome/components/debug/debug_component.h | 2 +- tests/components/wifi_info/test.esp32-ard.yaml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 tests/components/wifi_info/test.esp32-ard.yaml diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index c997ad7bd78..96306f7cdfe 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -10,7 +10,7 @@ #endif #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" -#endif // USE_TEXT_SENSOR +#endif namespace esphome { namespace debug { diff --git a/tests/components/wifi_info/test.esp32-ard.yaml b/tests/components/wifi_info/test.esp32-ard.yaml deleted file mode 100644 index 3393e33898f..00000000000 --- a/tests/components/wifi_info/test.esp32-ard.yaml +++ /dev/null @@ -1,9 +0,0 @@ -packages: - i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml - -<<: !include common.yaml - -text_sensor: - - platform: wifi_info - power_save_mode: - name: "WiFi Power Save Mode" From 70fa4dc3b21f88244c86771972c4cf1193e8f034 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 14:26:24 -0500 Subject: [PATCH 08/14] fix codegen and increase update interval --- esphome/components/wifi_info/text_sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 8cc0c4e66fe..0af4ebaf623 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -62,13 +62,13 @@ CONFIG_SCHEMA = cv.Schema( ), cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( DNSAddressWifiInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC - ).extend(cv.polling_component_schema("1s")), + ), cv.Optional(CONF_POWER_SAVE_MODE): cv.All( text_sensor.text_sensor_schema( PowerSaveModeWiFiInfo, icon=ICON_WIFI, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, - ).extend(cv.polling_component_schema("1s")), + ).extend(cv.polling_component_schema("60s")), cv.only_on(["esp32"]), ), } From 85d8a26d51e551c3232e9999c2d9dfc5bf3d3589 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 14:27:20 -0500 Subject: [PATCH 09/14] remove icon --- esphome/components/wifi_info/text_sensor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 0af4ebaf623..16eff4cabaa 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_SCAN_RESULTS, CONF_SSID, ENTITY_CATEGORY_DIAGNOSTIC, - ICON_WIFI, ) DEPENDENCIES = ["wifi"] @@ -66,7 +65,6 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_POWER_SAVE_MODE): cv.All( text_sensor.text_sensor_schema( PowerSaveModeWiFiInfo, - icon=ICON_WIFI, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ).extend(cv.polling_component_schema("60s")), cv.only_on(["esp32"]), From 2a27a3a95a93445f6c3398738af8e9170a92503c Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 15:01:39 -0500 Subject: [PATCH 10/14] add a power save mode listener and use it for the text sensor --- esphome/components/wifi/wifi_component.h | 15 +++++ .../wifi/wifi_component_esp8266.cpp | 10 ++- .../wifi/wifi_component_esp_idf.cpp | 10 ++- .../wifi/wifi_component_libretiny.cpp | 12 +++- .../components/wifi/wifi_component_pico_w.cpp | 10 ++- esphome/components/wifi_info/text_sensor.py | 12 ++-- .../wifi_info/wifi_info_text_sensor.cpp | 64 ++++++++----------- .../wifi_info/wifi_info_text_sensor.h | 23 ++++--- tests/components/wifi_info/common.yaml | 2 + .../components/wifi_info/test.esp32-idf.yaml | 5 -- 10 files changed, 97 insertions(+), 66 deletions(-) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 2148f2d4c71..be94e9462b1 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -273,6 +273,16 @@ class WiFiConnectStateListener { virtual void on_wifi_connect_state(const std::string &ssid, const bssid_t &bssid) = 0; }; +/** Listener interface for WiFi power save mode changes. + * + * Components can implement this interface to receive power save mode updates + * without the overhead of std::function callbacks. + */ +class WiFiPowerSaveListener { + public: + virtual void on_wifi_power_save(WiFiPowerSaveMode mode) = 0; +}; + /// This component is responsible for managing the ESP WiFi interface. class WiFiComponent : public Component { public: @@ -419,6 +429,10 @@ class WiFiComponent : public Component { void add_connect_state_listener(WiFiConnectStateListener *listener) { this->connect_state_listeners_.push_back(listener); } + /** Add a listener for WiFi power save mode changes. + * Listener receives: WiFiPowerSaveMode + */ + void add_power_save_listener(WiFiPowerSaveListener *listener) { this->power_save_listeners_.push_back(listener); } #endif // USE_WIFI_LISTENERS #ifdef USE_WIFI_RUNTIME_POWER_SAVE @@ -581,6 +595,7 @@ class WiFiComponent : public Component { std::vector ip_state_listeners_; std::vector scan_results_listeners_; std::vector connect_state_listeners_; + std::vector power_save_listeners_; #endif // USE_WIFI_LISTENERS ESPPreferenceObject pref_; #ifdef USE_WIFI_FAST_CONNECT diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index c1c0dd470f2..9fdae278c73 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -104,7 +104,15 @@ bool WiFiComponent::wifi_apply_power_save_() { break; } wifi_fpm_auto_sleep_set_in_null_mode(1); - return wifi_set_sleep_type(power_save); + bool success = wifi_set_sleep_type(power_save); + if (success) { +#ifdef USE_WIFI_LISTENERS + for (auto *listener : this->power_save_listeners_) { + listener->on_wifi_power_save(this->power_save_); + } +#endif + } + return success; } #if LWIP_VERSION_MAJOR != 1 diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index e1f8108892a..54fa40a173b 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -280,7 +280,15 @@ bool WiFiComponent::wifi_apply_power_save_() { power_save = WIFI_PS_NONE; break; } - return esp_wifi_set_ps(power_save) == ESP_OK; + bool success = esp_wifi_set_ps(power_save) == ESP_OK; + if (success) { +#ifdef USE_WIFI_LISTENERS + for (auto *listener : this->power_save_listeners_) { + listener->on_wifi_power_save(this->power_save_); + } +#endif + } + return success; } bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 0de70038994..a3a3c852b5c 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -69,7 +69,17 @@ bool WiFiComponent::wifi_sta_pre_setup_() { delay(10); return true; } -bool WiFiComponent::wifi_apply_power_save_() { return WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); } +bool WiFiComponent::wifi_apply_power_save_() { + bool success = WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); + if (success) { +#ifdef USE_WIFI_LISTENERS + for (auto *listener : this->power_save_listeners_) { + listener->on_wifi_power_save(this->power_save_); + } +#endif + } + return success; +} bool WiFiComponent::wifi_sta_ip_config_(const optional &manual_ip) { // enable STA if (!this->wifi_mode_(true, {})) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index c7dc4120ddb..5f4e6ffc696 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -54,7 +54,15 @@ bool WiFiComponent::wifi_apply_power_save_() { break; } int ret = cyw43_wifi_pm(&cyw43_state, pm); - return ret == 0; + bool success = ret == 0; + if (success) { +#ifdef USE_WIFI_LISTENERS + for (auto *listener : this->power_save_listeners_) { + listener->on_wifi_power_save(this->power_save_); + } +#endif + } + return success; } // TODO: The driver doesn't seem to have an API for this diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 16eff4cabaa..8a7f1923678 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -32,7 +32,7 @@ DNSAddressWifiInfo = wifi_info_ns.class_( "DNSAddressWifiInfo", text_sensor.TextSensor, cg.Component ) PowerSaveModeWiFiInfo = wifi_info_ns.class_( - "PowerSaveModeWiFiInfo", text_sensor.TextSensor, cg.PollingComponent + "PowerSaveModeWiFiInfo", text_sensor.TextSensor, cg.Component ) CONFIG_SCHEMA = cv.Schema( @@ -62,12 +62,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_DNS_ADDRESS): text_sensor.text_sensor_schema( DNSAddressWifiInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC ), - cv.Optional(CONF_POWER_SAVE_MODE): cv.All( - text_sensor.text_sensor_schema( - PowerSaveModeWiFiInfo, - entity_category=ENTITY_CATEGORY_DIAGNOSTIC, - ).extend(cv.polling_component_schema("60s")), - cv.only_on(["esp32"]), + cv.Optional(CONF_POWER_SAVE_MODE): text_sensor.text_sensor_schema( + PowerSaveModeWiFiInfo, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), } ) @@ -79,6 +76,7 @@ _NETWORK_INFO_KEYS = { CONF_IP_ADDRESS, CONF_DNS_ADDRESS, CONF_SCAN_RESULTS, + CONF_POWER_SAVE_MODE, } diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index 360cd979ea4..a2d4c2c45dd 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -6,29 +6,6 @@ namespace esphome::wifi_info { static const char *const TAG = "wifi_info"; -#ifdef USE_ESP32 -/// @brief Helper function to convert ESP32 WiFi power save mode to string -/// @param ps_mode WiFi power save mode from esp_wifi_get_ps() -/// @return const char pointer to the readable power save mode -/// -/// Maps ESP32 WiFi power save modes to user-friendly strings: -/// - WIFI_PS_NONE (no power saving) -> "NONE" -/// - WIFI_PS_MIN_MODEM (minimal modem sleep) -> "LIGHT" -/// - WIFI_PS_MAX_MODEM (maximum modem sleep) -> "HIGH" -static const char *wifi_ps_mode_to_string(wifi_ps_type_t ps_mode) { - switch (ps_mode) { - case WIFI_PS_NONE: - return "NONE"; - case WIFI_PS_MIN_MODEM: - return "LIGHT"; - case WIFI_PS_MAX_MODEM: - return "HIGH"; - default: - return "UNKNOWN"; - } -} -#endif // USE_ESP32 - #ifdef USE_WIFI_LISTENERS static constexpr size_t MAX_STATE_LENGTH = 255; @@ -123,6 +100,32 @@ void BSSIDWiFiInfo::on_wifi_connect_state(const std::string &ssid, const wifi::b this->publish_state(buf); } +/************************ + * PowerSaveModeWiFiInfo + ***********************/ + +void PowerSaveModeWiFiInfo::setup() { wifi::global_wifi_component->add_power_save_listener(this); } + +void PowerSaveModeWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "WiFi Power Save Mode", this); } + +void PowerSaveModeWiFiInfo::on_wifi_power_save(wifi::WiFiPowerSaveMode mode) { + const char *mode_str; + switch (mode) { + case wifi::WIFI_POWER_SAVE_NONE: + mode_str = "NONE"; + break; + case wifi::WIFI_POWER_SAVE_LIGHT: + mode_str = "LIGHT"; + break; + case wifi::WIFI_POWER_SAVE_HIGH: + mode_str = "HIGH"; + break; + default: + mode_str = "UNKNOWN"; + break; + } + this->publish_state(mode_str); +} #endif /********************* @@ -131,20 +134,5 @@ void BSSIDWiFiInfo::on_wifi_connect_state(const std::string &ssid, const wifi::b void MacAddressWifiInfo::dump_config() { LOG_TEXT_SENSOR("", "MAC Address", this); } -#ifdef USE_ESP32 -void PowerSaveModeWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "WiFi Power Save Mode", this); } - -void PowerSaveModeWiFiInfo::update() { - wifi_ps_type_t power_save_mode; - if (esp_wifi_get_ps(&power_save_mode) == ESP_OK) { - // Publish if the state has changed or if this is the first read - if (this->last_power_save_mode_ != power_save_mode || !this->has_state()) { - this->publish_state(wifi_ps_mode_to_string(power_save_mode)); - this->last_power_save_mode_ = power_save_mode; - } - } -} -#endif // USE_ESP32 - } // namespace esphome::wifi_info #endif diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 78afcad43fb..5aad0424913 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -66,6 +66,17 @@ class BSSIDWiFiInfo final : public Component, public text_sensor::TextSensor, pu // WiFiConnectStateListener interface void on_wifi_connect_state(const std::string &ssid, const wifi::bssid_t &bssid) override; }; + +class PowerSaveModeWiFiInfo final : public Component, + public text_sensor::TextSensor, + public wifi::WiFiPowerSaveListener { + public: + void setup() override; + void dump_config() override; + + // WiFiPowerSaveListener interface + void on_wifi_power_save(wifi::WiFiPowerSaveMode mode) override; +}; #endif class MacAddressWifiInfo final : public Component, public text_sensor::TextSensor { @@ -77,17 +88,5 @@ class MacAddressWifiInfo final : public Component, public text_sensor::TextSenso void dump_config() override; }; -#ifdef USE_ESP32 -class PowerSaveModeWiFiInfo : public PollingComponent, public text_sensor::TextSensor { - public: - void update() override; - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } - void dump_config() override; - - protected: - wifi_ps_type_t last_power_save_mode_{}; -}; -#endif // USE_ESP32 - } // namespace esphome::wifi_info #endif diff --git a/tests/components/wifi_info/common.yaml b/tests/components/wifi_info/common.yaml index f87d381d0cf..340eaca2a7b 100644 --- a/tests/components/wifi_info/common.yaml +++ b/tests/components/wifi_info/common.yaml @@ -16,3 +16,5 @@ text_sensor: name: MAC Address dns_address: name: DNS ADdress + power_save_mode: + name: "WiFi Power Save Mode" diff --git a/tests/components/wifi_info/test.esp32-idf.yaml b/tests/components/wifi_info/test.esp32-idf.yaml index 648bdf47c98..b47e39c3898 100644 --- a/tests/components/wifi_info/test.esp32-idf.yaml +++ b/tests/components/wifi_info/test.esp32-idf.yaml @@ -2,8 +2,3 @@ packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml <<: !include common.yaml - -text_sensor: - - platform: wifi_info - power_save_mode: - name: "WiFi Power Save Mode" From 2821f3041cd72b5fe5412ac7fa1f33c420029745 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 15:08:43 -0500 Subject: [PATCH 11/14] move ifdef guard to outside if statement --- esphome/components/wifi/wifi_component_esp8266.cpp | 4 ++-- esphome/components/wifi/wifi_component_esp_idf.cpp | 4 ++-- esphome/components/wifi/wifi_component_libretiny.cpp | 4 ++-- esphome/components/wifi/wifi_component_pico_w.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 9fdae278c73..3b1a442bdbd 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -105,13 +105,13 @@ bool WiFiComponent::wifi_apply_power_save_() { } wifi_fpm_auto_sleep_set_in_null_mode(1); bool success = wifi_set_sleep_type(power_save); - if (success) { #ifdef USE_WIFI_LISTENERS + if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); } -#endif } +#endif return success; } diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 54fa40a173b..1f4eb1e42c1 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -281,13 +281,13 @@ bool WiFiComponent::wifi_apply_power_save_() { break; } bool success = esp_wifi_set_ps(power_save) == ESP_OK; - if (success) { #ifdef USE_WIFI_LISTENERS + if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); } -#endif } +#endif return success; } diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index a3a3c852b5c..1a6f037a874 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -71,13 +71,13 @@ bool WiFiComponent::wifi_sta_pre_setup_() { } bool WiFiComponent::wifi_apply_power_save_() { bool success = WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); - if (success) { #ifdef USE_WIFI_LISTENERS + if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); } -#endif } +#endif return success; } bool WiFiComponent::wifi_sta_ip_config_(const optional &manual_ip) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 5f4e6ffc696..02287554324 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -55,13 +55,13 @@ bool WiFiComponent::wifi_apply_power_save_() { } int ret = cyw43_wifi_pm(&cyw43_state, pm); bool success = ret == 0; - if (success) { #ifdef USE_WIFI_LISTENERS + if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); } -#endif } +#endif return success; } From 7c532ba812ecd713b4c4b7f21c91c641c9da74be Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 15:12:40 -0500 Subject: [PATCH 12/14] remove unusued include --- esphome/components/wifi_info/wifi_info_text_sensor.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 5aad0424913..b2242372daa 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -6,9 +6,6 @@ #include "esphome/components/wifi/wifi_component.h" #ifdef USE_WIFI #include -#ifdef USE_ESP32 -#include -#endif // USE_ESP32 namespace esphome::wifi_info { From 224866dfbba473ad29074e4e1034a41b1cbad9ad Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 17:47:25 -0500 Subject: [PATCH 13/14] fix typo in test --- tests/components/wifi_info/common.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/wifi_info/common.yaml b/tests/components/wifi_info/common.yaml index 340eaca2a7b..91dea6c66ee 100644 --- a/tests/components/wifi_info/common.yaml +++ b/tests/components/wifi_info/common.yaml @@ -15,6 +15,6 @@ text_sensor: mac_address: name: MAC Address dns_address: - name: DNS ADdress + name: DNS Address power_save_mode: name: "WiFi Power Save Mode" From d85d8745f604a716df3e2da504b47adc56724edc Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 2 Dec 2025 17:48:05 -0500 Subject: [PATCH 14/14] use progmem to store strings on ESP8266s --- .../wifi_info/wifi_info_text_sensor.cpp | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index a2d4c2c45dd..56cf49028c5 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -2,6 +2,10 @@ #ifdef USE_WIFI #include "esphome/core/log.h" +#ifdef USE_ESP8266 +#include +#endif + namespace esphome::wifi_info { static const char *const TAG = "wifi_info"; @@ -109,6 +113,34 @@ void PowerSaveModeWiFiInfo::setup() { wifi::global_wifi_component->add_power_sav void PowerSaveModeWiFiInfo::dump_config() { LOG_TEXT_SENSOR("", "WiFi Power Save Mode", this); } void PowerSaveModeWiFiInfo::on_wifi_power_save(wifi::WiFiPowerSaveMode mode) { +#ifdef USE_ESP8266 +#define MODE_STR(s) static const char MODE_##s[] PROGMEM = #s + MODE_STR(NONE); + MODE_STR(LIGHT); + MODE_STR(HIGH); + MODE_STR(UNKNOWN); + + const char *mode_str_p; + switch (mode) { + case wifi::WIFI_POWER_SAVE_NONE: + mode_str_p = MODE_NONE; + break; + case wifi::WIFI_POWER_SAVE_LIGHT: + mode_str_p = MODE_LIGHT; + break; + case wifi::WIFI_POWER_SAVE_HIGH: + mode_str_p = MODE_HIGH; + break; + default: + mode_str_p = MODE_UNKNOWN; + break; + } + + char mode_str[8]; + strncpy_P(mode_str, mode_str_p, sizeof(mode_str)); + mode_str[sizeof(mode_str) - 1] = '\0'; +#undef MODE_STR +#else const char *mode_str; switch (mode) { case wifi::WIFI_POWER_SAVE_NONE: @@ -124,8 +156,10 @@ void PowerSaveModeWiFiInfo::on_wifi_power_save(wifi::WiFiPowerSaveMode mode) { mode_str = "UNKNOWN"; break; } +#endif this->publish_state(mode_str); } + #endif /*********************