diff --git a/get-started/csi_recv_router/main/app_main.c b/get-started/csi_recv_router/main/app_main.c index 17a3cda..4280a47 100644 --- a/get-started/csi_recv_router/main/app_main.c +++ b/get-started/csi_recv_router/main/app_main.c @@ -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); diff --git a/get-started/csi_recv_router/sdkconfig.defaults b/get-started/csi_recv_router/sdkconfig.defaults index 042924a..9057ab6 100644 --- a/get-started/csi_recv_router/sdkconfig.defaults +++ b/get-started/csi_recv_router/sdkconfig.defaults @@ -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