Add a WiFi power mode debug text sensor

This commit is contained in:
Kevin Ahrendt
2025-12-02 14:03:38 -05:00
committed by Kevin Ahrendt
parent 638c59e162
commit 4a84221641
16 changed files with 261 additions and 2 deletions
@@ -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_);
+23 -1
View File
@@ -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 <esp_wifi.h>
#elif defined(USE_ESP8266)
extern "C" {
#include <user_interface.h>
}
#elif defined(USE_RP2040)
#include <pico/cyw43_arch.h>
#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_();
+40
View File
@@ -11,6 +11,10 @@
#include <esp_chip_info.h>
#include <esp_partition.h>
#ifdef USE_WIFI
#include <esp_wifi.h>
#endif
#ifdef USE_ARDUINO
#include <Esp.h>
#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
@@ -3,11 +3,41 @@
#include "esphome/core/log.h"
#include <Esp.h>
#ifdef USE_WIFI
extern "C" {
#include <user_interface.h>
}
#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
@@ -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
+40 -1
View File
@@ -2,11 +2,39 @@
#ifdef USE_RP2040
#include "esphome/core/log.h"
#include <Arduino.h>
#ifdef USE_WIFI
#include <pico/cyw43_arch.h>
#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
+13
View File
@@ -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))
@@ -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"
@@ -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
@@ -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:
@@ -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"
@@ -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"
@@ -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"
@@ -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"
@@ -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"
@@ -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"