feat: Add POWERSAVE command with DFS + light sleep (v1.6)
Enable ESP-IDF power management framework (DFS 240/80 MHz + light sleep) and add POWERSAVE command to toggle WiFi modem sleep. NVS-persisted, default off. Automatically disabled during POWERTEST.
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "esp_now.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_https_ota.h"
|
||||
@@ -164,6 +165,7 @@ static int s_deauth_ring_count = 0;
|
||||
|
||||
/* Power test */
|
||||
static volatile bool s_powertest_running = false;
|
||||
static bool s_powersave = false;
|
||||
|
||||
/* Probe dedup rate (moved before config_load_nvs for NVS access) */
|
||||
#define PROBE_DEDUP_DEFAULT_US 10000000LL
|
||||
@@ -236,10 +238,14 @@ static void config_load_nvs(void)
|
||||
if (nvs_get_i32(h, "probe_rate", &probe_r) == ESP_OK && probe_r >= 1 && probe_r <= 300) {
|
||||
s_probe_dedup_us = (int64_t)probe_r * 1000000LL;
|
||||
}
|
||||
int8_t powersave;
|
||||
if (nvs_get_i8(h, "powersave", &powersave) == ESP_OK) {
|
||||
s_powersave = (powersave != 0);
|
||||
}
|
||||
nvs_close(h);
|
||||
ESP_LOGI(TAG, "NVS loaded: hostname=%s rate=%d tx_power=%d adaptive=%d threshold=%.6f ble=%d target=%s:%d csi_mode=%d hybrid_n=%d",
|
||||
ESP_LOGI(TAG, "NVS loaded: hostname=%s rate=%d tx_power=%d adaptive=%d threshold=%.6f ble=%d target=%s:%d csi_mode=%d hybrid_n=%d powersave=%d",
|
||||
s_hostname, s_send_frequency, s_tx_power_dbm, s_adaptive, s_motion_threshold, s_ble_enabled,
|
||||
s_target_ip, s_target_port, (int)s_csi_mode, s_hybrid_interval);
|
||||
s_target_ip, s_target_port, (int)s_csi_mode, s_hybrid_interval, s_powersave);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "NVS: no saved config, using defaults");
|
||||
}
|
||||
@@ -1108,11 +1114,18 @@ static void powertest_task(void *arg)
|
||||
bool saved_ble = s_ble_enabled;
|
||||
int8_t saved_tx_power = s_tx_power_dbm;
|
||||
led_mode_t saved_led = s_led_mode;
|
||||
bool saved_powersave = s_powersave;
|
||||
|
||||
/* Disable adaptive during test */
|
||||
s_adaptive = false;
|
||||
s_motion_detected = false;
|
||||
|
||||
/* Disable powersave during test */
|
||||
if (s_powersave) {
|
||||
s_powersave = false;
|
||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int rate; /* 0 = stop ping */
|
||||
@@ -1188,6 +1201,9 @@ static void powertest_task(void *arg)
|
||||
}
|
||||
wifi_ping_router_start();
|
||||
|
||||
s_powersave = saved_powersave;
|
||||
esp_wifi_set_ps(s_powersave ? WIFI_PS_MIN_MODEM : WIFI_PS_NONE);
|
||||
|
||||
int total_s = dwell_s * n_phases;
|
||||
send_powertest_event("done", total_s);
|
||||
ESP_LOGI(TAG, "POWERTEST: done total=%ds", total_s);
|
||||
@@ -1256,7 +1272,7 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
"OK STATUS uptime=%s uptime_s=%lld heap=%lu rssi=%d channel=%d tx_power=%d rate=%d csi_rate=%d"
|
||||
" hostname=%s version=%s adaptive=%s motion=%d ble=%s target=%s:%d"
|
||||
" temp=%.1f csi_count=%lu boots=%lu rssi_min=%d rssi_max=%d"
|
||||
" csi_mode=%s hybrid_n=%d auth=%s flood_thresh=%d/%d",
|
||||
" csi_mode=%s hybrid_n=%d auth=%s flood_thresh=%d/%d powersave=%s",
|
||||
uptime_str, (long long)up, (unsigned long)heap, rssi, channel, (int)s_tx_power_dbm,
|
||||
s_send_frequency, actual_rate,
|
||||
s_hostname, app_desc->version,
|
||||
@@ -1266,7 +1282,8 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
(int)s_rssi_min, (int)s_rssi_max,
|
||||
csi_mode_str, s_hybrid_interval,
|
||||
s_auth_secret[0] ? "on" : "off",
|
||||
s_flood_thresh, s_flood_window_s);
|
||||
s_flood_thresh, s_flood_window_s,
|
||||
s_powersave ? "on" : "off");
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
@@ -1616,6 +1633,29 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* POWERSAVE [ON|OFF] */
|
||||
if (strcmp(cmd, "POWERSAVE") == 0) {
|
||||
snprintf(reply, reply_size, "OK POWERSAVE %s", s_powersave ? "on" : "off");
|
||||
return strlen(reply);
|
||||
}
|
||||
if (strncmp(cmd, "POWERSAVE ", 10) == 0) {
|
||||
const char *arg = cmd + 10;
|
||||
if (strncmp(arg, "ON", 2) == 0) {
|
||||
s_powersave = true;
|
||||
esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||||
config_save_i8("powersave", 1);
|
||||
snprintf(reply, reply_size, "OK POWERSAVE on (modem sleep)");
|
||||
} else if (strncmp(arg, "OFF", 3) == 0) {
|
||||
s_powersave = false;
|
||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
config_save_i8("powersave", 0);
|
||||
snprintf(reply, reply_size, "OK POWERSAVE off");
|
||||
} else {
|
||||
snprintf(reply, reply_size, "ERR POWERSAVE ON or OFF");
|
||||
}
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
snprintf(reply, reply_size, "ERR UNKNOWN");
|
||||
return strlen(reply);
|
||||
}
|
||||
@@ -1743,6 +1783,27 @@ void app_main()
|
||||
esp_wifi_set_max_tx_power(s_tx_power_dbm * 4);
|
||||
ESP_LOGI(TAG, "TX power set to %d dBm", (int)s_tx_power_dbm);
|
||||
|
||||
/* Power management: DFS (240→80 MHz) + light sleep */
|
||||
esp_pm_config_t pm_config = {
|
||||
.max_freq_mhz = 240,
|
||||
.min_freq_mhz = 80,
|
||||
.light_sleep_enable = true,
|
||||
};
|
||||
esp_err_t pm_err = esp_pm_configure(&pm_config);
|
||||
if (pm_err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "PM: DFS 240/80 MHz, light sleep enabled");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "PM configure failed: %s", esp_err_to_name(pm_err));
|
||||
}
|
||||
|
||||
/* Apply saved WiFi power save mode */
|
||||
if (s_powersave) {
|
||||
esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||||
ESP_LOGI(TAG, "WiFi modem sleep enabled");
|
||||
} else {
|
||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
}
|
||||
|
||||
/* Chip temperature sensor (ESP32-S2/S3/C3/C6 only) */
|
||||
#if SOC_TEMP_SENSOR_SUPPORTED
|
||||
temperature_sensor_config_t temp_cfg = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
|
||||
|
||||
@@ -76,3 +76,9 @@ CONFIG_BTDM_CTRL_MODE_BTDM=n
|
||||
CONFIG_BT_BLUEDROID_ENABLED=n
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
CONFIG_ESP_WIFI_IRAM_OPT=n
|
||||
|
||||
#
|
||||
# Power Management
|
||||
#
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
|
||||
Reference in New Issue
Block a user