diff --git a/components/wifi_cfg/wifi_cfg.c b/components/wifi_cfg/wifi_cfg.c index bc0b0bb..08c5a46 100644 --- a/components/wifi_cfg/wifi_cfg.c +++ b/components/wifi_cfg/wifi_cfg.c @@ -45,7 +45,7 @@ static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){ return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key); } -static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw){ +static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw, const char* powersave){ nvs_handle_t h; if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return; if (ssid) nvs_set_str2(h, "ssid", ssid); @@ -55,16 +55,17 @@ static void save_cfg(const char* ssid, const char* pass, const char* ip, const c if (gw) nvs_set_str2(h, "gw", gw); if (band) nvs_set_str2(h, "band", band); if (bw) nvs_set_str2(h, "bw", bw); + if (powersave) nvs_set_str2(h, "powersave", powersave); nvs_set_u8(h, "dhcp", dhcp ? 1 : 0); nvs_commit(h); nvs_close(h); cfg_dhcp = dhcp; - ESP_LOGI(TAG, "Config saved to NVS: SSID=%s Band=%s BW=%s", ssid?ssid:"", band?band:"", bw?bw:""); + ESP_LOGI(TAG, "Config saved to NVS: SSID=%s Band=%s BW=%s PowerSave=%s", ssid?ssid:"", band?band:"", bw?bw:"", powersave?powersave:"NONE"); } static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz, - char* band, size_t bsz, char* bw, size_t bwsz, bool* dhcp){ + char* band, size_t bsz, char* bw, size_t bwsz, char* powersave, size_t pssz, bool* dhcp){ nvs_handle_t h; if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; size_t len; @@ -78,6 +79,7 @@ static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0; len = bsz; e = nvs_get_str(h, "band", band, &len); if (e!=ESP_OK) strcpy(band, "2.4G"); len = bwsz; e = nvs_get_str(h, "bw", bw, &len); if (e!=ESP_OK) strcpy(bw, "HT20"); + len = pssz; e = nvs_get_str(h, "powersave", powersave, &len); if (e!=ESP_OK) strcpy(powersave, "NONE"); uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0); nvs_close(h); return true; @@ -142,10 +144,10 @@ static void apply_ip_static(const char* ip, const char* mask, const char* gw){ bool wifi_cfg_apply_from_nvs(void) { char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; - char band[16]={0}, bw[16]={0}; + char band[16]={0}, bw[16]={0}, powersave[16]={0}; bool dhcp = true; if (!load_cfg(ssid,sizeof(ssid), pass,sizeof(pass), ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw), - band,sizeof(band), bw,sizeof(bw), &dhcp)){ + band,sizeof(band), bw,sizeof(bw), powersave,sizeof(powersave), &dhcp)){ ESP_LOGW(TAG, "No Wi‑Fi config in NVS"); return false; } @@ -154,10 +156,11 @@ bool wifi_cfg_apply_from_nvs(void) { ESP_LOGW(TAG, "SSID in NVS is empty; treating as no Wi-Fi config"); return false; } - ESP_LOGI(TAG, "Applying Wi-Fi config: SSID=%s DHCP=%d IP=%s Band=%s BW=%s", - ssid, dhcp, ip, band, bw); + ESP_LOGI(TAG, "Applying Wi-Fi config: SSID=%s DHCP=%d IP=%s Band=%s BW=%s PowerSave=%s", + ssid, dhcp, ip, band, bw, powersave); - ESP_LOGI(TAG, "Applying Wi‑Fi config: SSID=%s DHCP=%d IP=%s Band=%s BW=%s", ssid, dhcp, ip, band, bw); + ESP_LOGI(TAG, "Applying Wi‑Fi config: SSID=%s DHCP=%d IP=%s Band=%s BW=%s PowerSave=%s", + ssid, dhcp, ip, band, bw, powersave); static bool inited = false; if (!inited){ @@ -297,7 +300,7 @@ typedef struct { bool (*fetch_line)(char *buf, size_t sz, void *ctx); } cfg_io_t; -static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, char *band, char *bw, bool *dhcp){ +static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, char *band, char *bw, char *powersave, bool *dhcp){ if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, 63); ssid[63]=0; return; } if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, 63); pass[63]=0; return; } if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, 31); ip[31]=0; return; } @@ -305,13 +308,14 @@ static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char if (strncmp(line, "GW:",3)==0){ strncpy(gw, line+3, 31); gw[31]=0; return; } if (strncmp(line, "BAND:",5)==0){ strncpy(band, line+5, 15); band[15]=0; return; } if (strncmp(line, "BW:",3)==0){ strncpy(bw, line+3, 15); bw[15]=0; return; } + if (strncmp(line, "POWERSAVE:",10)==0){ strncpy(powersave, line+10, 15); powersave[15]=0; return; } if (strncmp(line, "DHCP:",5)==0){ *dhcp = atoi(line+5) ? true:false; return; } } static void cfg_worker(const cfg_io_t *io){ char line[160]; char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; - char band[16]={0}, bw[16]={0}; + char band[16]={0}, bw[16]={0}, powersave[16]={0}; bool dhcp = true; bool in_cfg = false; @@ -325,7 +329,7 @@ static void cfg_worker(const cfg_io_t *io){ if (strcmp(line, "CFG")==0){ in_cfg = true; ssid[0]=pass[0]=ip[0]=mask[0]=gw[0]=0; - band[0]=bw[0]=0; + band[0]=bw[0]=powersave[0]=0; dhcp = true; } continue; @@ -334,14 +338,15 @@ static void cfg_worker(const cfg_io_t *io){ // Set defaults if not specified if (!band[0]) strcpy(band, "2.4G"); if (!bw[0]) strcpy(bw, "HT20"); + if (!powersave[0]) strcpy(powersave, "NONE"); - save_cfg(ssid, pass, ip, mask, gw, dhcp, band, bw); + save_cfg(ssid, pass, ip, mask, gw, dhcp, band, bw, powersave); if (io->emit) io->emit("OK\n", io->ctx); wifi_cfg_apply_from_nvs(); in_cfg = false; continue; } - on_cfg_line(line, ssid, pass, ip, mask, gw, band, bw, &dhcp); + on_cfg_line(line, ssid, pass, ip, mask, gw, band, bw, powersave, &dhcp); } } @@ -413,3 +418,34 @@ void wifi_cfg_init(void){ xTaskCreatePinnedToCore(cfg_listener_usb_task, "cfg_usb", 6144, NULL, 5, NULL, tskNO_AFFINITY); } + +wifi_ps_type_t wifi_cfg_get_power_save_mode(void) { + char powersave[16] = {0}; + nvs_handle_t h; + + if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) { + ESP_LOGW(TAG, "Failed to open NVS for power save - defaulting to NONE"); + return WIFI_PS_NONE; + } + + size_t len = sizeof(powersave); + esp_err_t err = nvs_get_str(h, "powersave", powersave, &len); + nvs_close(h); + + if (err != ESP_OK) { + ESP_LOGI(TAG, "No power save setting in NVS - defaulting to NONE"); + return WIFI_PS_NONE; + } + + // Parse the power save string + if (strcmp(powersave, "MIN") == 0 || strcmp(powersave, "MIN_MODEM") == 0) { + ESP_LOGI(TAG, "Power save mode: MIN_MODEM"); + return WIFI_PS_MIN_MODEM; + } else if (strcmp(powersave, "MAX") == 0 || strcmp(powersave, "MAX_MODEM") == 0) { + ESP_LOGI(TAG, "Power save mode: MAX_MODEM"); + return WIFI_PS_MAX_MODEM; + } else { + ESP_LOGI(TAG, "Power save mode: NONE (no power saving)"); + return WIFI_PS_NONE; + } +} diff --git a/components/wifi_cfg/wifi_cfg.h b/components/wifi_cfg/wifi_cfg.h index 3782d72..e848850 100644 --- a/components/wifi_cfg/wifi_cfg.h +++ b/components/wifi_cfg/wifi_cfg.h @@ -1,15 +1,51 @@ +#ifndef WIFI_CFG_H +#define WIFI_CFG_H + +#include "esp_wifi.h" +#include -#pragma once #ifdef __cplusplus extern "C" { #endif -#include +/** + * @brief Initialize the WiFi configuration system + * + * Spawns listener tasks for both UART and USB-Serial/JTAG interfaces + * to receive configuration commands. + */ +void wifi_cfg_init(void); -void wifi_cfg_init(void); // starts serial listener task -bool wifi_cfg_apply_from_nvs(void); // reads saved config and connects Wi‑Fi -void wifi_cfg_force_dhcp(bool enable); // for testing +/** + * @brief Apply WiFi configuration from NVS + * + * @return true if configuration was found and applied, false otherwise + */ +bool wifi_cfg_apply_from_nvs(void); + +/** + * @brief Force DHCP mode enable/disable + * + * @param enable true to enable DHCP, false to disable + */ +void wifi_cfg_force_dhcp(bool enable); + +/** + * @brief Get the configured power save mode from NVS + * + * @return wifi_ps_type_t Power save mode (WIFI_PS_NONE, WIFI_PS_MIN_MODEM, or WIFI_PS_MAX_MODEM) + */ +wifi_ps_type_t wifi_cfg_get_power_save_mode(void); + +/** + * @brief Ensure WiFi driver is initialized (thread-safe, idempotent) + * + * @return ESP_OK on success, error code otherwise + */ +esp_err_t wifi_ensure_inited(void); #ifdef __cplusplus } #endif + +#endif // WIFI_CFG_H diff --git a/config_device.py b/config_device.py index 22f205f..17e0b5c 100755 --- a/config_device.py +++ b/config_device.py @@ -15,22 +15,23 @@ def log_verbose(message, verbose=False): def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", gateway="192.168.1.1", netmask="255.255.255.0", - band="2.4G", bandwidth="HT20", reboot=True, verbose=False): + band="2.4G", bandwidth="HT20", powersave="NONE", reboot=True, verbose=False): """Configure ESP32 device via serial""" print(f"\n{'='*70}") print(f"ESP32 WiFi Configuration") print(f"{'='*70}") - print(f"Port: {port}") - print(f"SSID: {ssid}") - print(f"Password: {'*' * len(password)}") - print(f"IP: {ip}") - print(f"Gateway: {gateway}") - print(f"Netmask: {netmask}") - print(f"Band: {band}") - print(f"Bandwidth: {bandwidth}") - print(f"Reboot: {'Yes' if reboot else 'No'}") - print(f"Verbose: {verbose}") + print(f"Port: {port}") + print(f"SSID: {ssid}") + print(f"Password: {'*' * len(password)}") + print(f"IP: {ip}") + print(f"Gateway: {gateway}") + print(f"Netmask: {netmask}") + print(f"Band: {band}") + print(f"Bandwidth: {bandwidth}") + print(f"PowerSave: {powersave}") + print(f"Reboot: {'Yes' if reboot else 'No'}") + print(f"Verbose: {verbose}") print(f"{'='*70}\n") try: @@ -59,6 +60,7 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", "DHCP:0", f"BAND:{band}", f"BW:{bandwidth}", + f"POWERSAVE:{powersave}", "END" ] @@ -232,6 +234,7 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", print(f"SSID: {ssid}") print(f"Band: {band}") print(f"Bandwidth: {bandwidth}") + print(f"PowerSave: {powersave}") print(f"{'='*70}") print("\nNext steps:") print(f" 1. Check LED color:") @@ -280,6 +283,15 @@ Examples: # 5GHz with HT40 bandwidth and auto-reboot %(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -s ClubHouse5G -b 5G -B HT40 + # Disable power save for best CSI quality (default) + %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -ps NONE + + # Enable minimum power save (useful for battery-powered devices) + %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -ps MIN + + # Enable maximum power save (lowest power consumption) + %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -ps MAX + # Configure without rebooting (manual reboot required) %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -r @@ -311,6 +323,9 @@ Examples: parser.add_argument('-B', '--bandwidth', default='HT20', choices=['HT20', 'HT40'], help='Channel bandwidth: HT20 or HT40 (default: HT20)') + parser.add_argument('-ps', '--powersave', default='NONE', + choices=['NONE', 'MIN', 'MIN_MODEM', 'MAX', 'MAX_MODEM'], + help='Power save mode: NONE (no PS, best for CSI), MIN/MIN_MODEM, MAX/MAX_MODEM (default: NONE)') parser.add_argument('-r', '--no-reboot', action='store_true', help='Do NOT reboot device after configuration (default: will reboot)') parser.add_argument('-v', '--verbose', action='store_true', @@ -327,6 +342,7 @@ Examples: netmask=args.netmask, band=args.band, bandwidth=args.bandwidth, + powersave=args.powersave, reboot=not args.no_reboot, # Invert since flag is --no-reboot verbose=args.verbose ) diff --git a/main/main.c b/main/main.c index 61536c2..f86452f 100644 --- a/main/main.c +++ b/main/main.c @@ -151,12 +151,15 @@ static void wifi_enable_csi_once(void) { ESP_LOGI("CSI", "Waiting 500ms for WiFi to stabilize..."); vTaskDelay(pdMS_TO_TICKS(500)); - // Disable power save for CSI - err = esp_wifi_set_ps(WIFI_PS_NONE); + // Get power save mode from NVS configuration + wifi_ps_type_t ps_mode = wifi_cfg_get_power_save_mode(); + err = esp_wifi_set_ps(ps_mode); if (err != ESP_OK) { - ESP_LOGW("CSI", "Failed to disable power save: %s", esp_err_to_name(err)); + ESP_LOGW("CSI", "Failed to set power save mode: %s", esp_err_to_name(err)); } else { - ESP_LOGI("CSI", "WiFi power save disabled"); + const char *ps_str = (ps_mode == WIFI_PS_NONE) ? "NONE (disabled)" : + (ps_mode == WIFI_PS_MIN_MODEM) ? "MIN_MODEM" : "MAX_MODEM"; + ESP_LOGI("CSI", "WiFi power save set to: %s", ps_str); } wifi_csi_config_t csi_cfg; diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..48ff361 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,17 @@ +# UART console @115200 on UART0 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 + +# Logging: INFO by default (quiet enough but useful) +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_LOG_DEFAULT_LEVEL=3 + +# Make backtraces visible and reboot automatically on panic +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y + +# Give the main task a bit more room (iperf + console parsing) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 + +# Slightly smaller binaries without hurting you +CONFIG_COMPILER_OPTIMIZATION_SIZE=y