#include #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_log.h" #include "nvs_flash.h" #include "nvs.h" #include "esp_netif.h" #include "esp_wifi.h" #include "esp_event.h" #include "driver/usb_serial_jtag.h" #include "esp_vfs_dev.h" #include "wifi_cfg.h" static const char *TAG = "wifi_cfg"; static void trim(char *s){ int n = strlen(s); while(n>0 && (s[n-1]=='\r' || s[n-1]=='\n' || isspace((unsigned char)s[n-1]))) s[--n]=0; while(*s && isspace((unsigned char)*s)){ memmove(s, s+1, strlen(s)); } } 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 bool cfg_dhcp = true; static esp_netif_t *sta_netif = NULL; static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp){ nvs_handle_t h; if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return; if (ssid) nvs_set_str2(h, "ssid", ssid); if (pass) nvs_set_str2(h, "pass", pass); if (ip) nvs_set_str2(h, "ip", ip); if (mask) nvs_set_str2(h, "mask", mask); if (gw) nvs_set_str2(h, "gw", gw); nvs_set_u8(h, "dhcp", dhcp ? 1 : 0); nvs_commit(h); nvs_close(h); cfg_dhcp = dhcp; } 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, bool* dhcp){ nvs_handle_t h; if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; size_t len; esp_err_t e; if ((e = nvs_get_str(h, "ssid", NULL, &len)) != ESP_OK){ nvs_close(h); return false; } if (len >= ssz){ nvs_close(h); return false; } nvs_get_str(h, "ssid", ssid, &len); len = psz; e = nvs_get_str(h, "pass", pass, &len); if (e!=ESP_OK) pass[0]=0; len = isz; e = nvs_get_str(h, "ip", ip, &len); if (e!=ESP_OK) ip[0]=0; len = msz; e = nvs_get_str(h, "mask", mask, &len); if (e!=ESP_OK) mask[0]=0; len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0; uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0); nvs_close(h); return true; } void wifi_cfg_force_dhcp(bool enable){ cfg_dhcp = enable; } static void apply_ip_static(const char* ip, const char* mask, const char* gw){ if (!sta_netif) return; esp_netif_ip_info_t info = {0}; esp_netif_dhcpc_stop(sta_netif); info.ip.addr = esp_ip4addr_aton(ip); info.netmask.addr = esp_ip4addr_aton(mask); info.gw.addr = esp_ip4addr_aton(gw); ESP_ERROR_CHECK( esp_netif_set_ip_info(sta_netif, &info) ); } bool wifi_cfg_apply_from_nvs(void){ char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; bool dhcp = true; if (!load_cfg(ssid,sizeof(ssid), pass,sizeof(pass), ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw), &dhcp)){ ESP_LOGW(TAG, "No Wi-Fi config in NVS"); return false; } ESP_LOGI(TAG, "Applying Wi-Fi config: SSID=%s DHCP=%d IP=%s", ssid, dhcp, ip); static bool inited = false; if (!inited){ ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); sta_netif = esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); inited = true; } wifi_config_t wcfg = {0}; strncpy((char*)wcfg.sta.ssid, ssid, sizeof(wcfg.sta.ssid)-1); strncpy((char*)wcfg.sta.password, pass, sizeof(wcfg.sta.password)-1); wcfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; wcfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wcfg) ); if (!dhcp && ip[0] && mask[0] && gw[0]){ apply_ip_static(ip, mask, gw); }else{ if (sta_netif) esp_netif_dhcpc_start(sta_netif); } ESP_ERROR_CHECK( esp_wifi_start() ); ESP_ERROR_CHECK( esp_wifi_connect() ); return true; } static void cfg_listener_task(void *arg){ usb_serial_jtag_driver_config_t dcfg = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); ESP_ERROR_CHECK(usb_serial_jtag_driver_install(&dcfg)); // Deprecated but functional - causes only a warning esp_vfs_usb_serial_jtag_use_driver(); setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); char line[160]; char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; bool dhcp = true; bool in_cfg = false; while (1){ if (!fgets(line, sizeof(line), stdin)){ vTaskDelay(pdMS_TO_TICKS(50)); continue; } trim(line); if (!in_cfg){ if (strcmp(line, "CFG")==0){ in_cfg = true; ssid[0]=pass[0]=ip[0]=mask[0]=gw[0]=0; dhcp = true; } continue; } if (strcmp(line, "END")==0){ save_cfg(ssid, pass, ip, mask, gw, dhcp); printf("OK\n"); wifi_cfg_apply_from_nvs(); in_cfg = false; continue; } if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, sizeof(ssid)-1); continue; } if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, sizeof(pass)-1); continue; } if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, sizeof(ip)-1); continue; } if (strncmp(line, "MASK:",5)==0){ strncpy(mask, line+5, sizeof(mask)-1); continue; } if (strncmp(line, "GW:",3)==0){ strncpy(gw, line+3, sizeof(gw)-1); continue; } if (strncmp(line, "DHCP:",5)==0){ dhcp = atoi(line+5) ? true:false; continue; } } } void wifi_cfg_init(void){ nvs_flash_init(); xTaskCreatePinnedToCore(cfg_listener_task, "cfg_listener", 6144, NULL, 5, NULL, tskNO_AFFINITY); }