[wifi, wifi_info] Add a WiFi power mode text sensor (#11480)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Kevin Ahrendt
2025-12-03 15:18:59 -05:00
committed by GitHub
parent 03aaa66f8e
commit a8518d3cea
9 changed files with 137 additions and 5 deletions

View File

@@ -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<WiFiIPStateListener *> ip_state_listeners_;
std::vector<WiFiScanResultsListener *> scan_results_listeners_;
std::vector<WiFiConnectStateListener *> connect_state_listeners_;
std::vector<WiFiPowerSaveListener *> power_save_listeners_;
#endif // USE_WIFI_LISTENERS
ESPPreferenceObject pref_;
#ifdef USE_WIFI_FAST_CONNECT

View File

@@ -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);
#ifdef USE_WIFI_LISTENERS
if (success) {
for (auto *listener : this->power_save_listeners_) {
listener->on_wifi_power_save(this->power_save_);
}
}
#endif
return success;
}
#if LWIP_VERSION_MAJOR != 1

View File

@@ -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;
#ifdef USE_WIFI_LISTENERS
if (success) {
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) {

View File

@@ -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);
#ifdef USE_WIFI_LISTENERS
if (success) {
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<ManualIP> &manual_ip) {
// enable STA
if (!this->wifi_mode_(true, {}))

View File

@@ -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;
#ifdef USE_WIFI_LISTENERS
if (success) {
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

View File

@@ -6,6 +6,7 @@ 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,
@@ -30,6 +31,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.Component
)
CONFIG_SCHEMA = cv.Schema(
{
@@ -58,6 +62,10 @@ 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): text_sensor.text_sensor_schema(
PowerSaveModeWiFiInfo,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
),
}
)
@@ -68,6 +76,7 @@ _NETWORK_INFO_KEYS = {
CONF_IP_ADDRESS,
CONF_DNS_ADDRESS,
CONF_SCAN_RESULTS,
CONF_POWER_SAVE_MODE,
}
@@ -90,6 +99,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])

View File

@@ -2,6 +2,10 @@
#ifdef USE_WIFI
#include "esphome/core/log.h"
#ifdef USE_ESP8266
#include <pgmspace.h>
#endif
namespace esphome::wifi_info {
static const char *const TAG = "wifi_info";
@@ -100,6 +104,62 @@ 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) {
#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:
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;
}
#endif
this->publish_state(mode_str);
}
#endif
/*********************

View File

@@ -63,6 +63,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 {

View File

@@ -15,4 +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"