#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_event_loop.h" #include "esp_heap_caps.h" #include "esp_log.h" #include "esp_wifi.h" #include "nvs_flash.h" #include "driver/gpio.h" #include "driver/uart.h" #include "driver/spi_common.h" #include "driver/spi_master.h" #include "lwip/err.h" #include "lwip/sys.h" #include "esp32-wifi-manager.h" #define MAX_ESSID (32) #define MAX_PASSWORD (64) static const char *TAG = "WM"; nvs_handle nvs; typedef struct wifi_manager_ap_info { char ssid[MAX_ESSID]; char password[MAX_PASSWORD]; } wifi_manager_ap_info_t; typedef struct ap_store_base { int8_t last; uint8_t count; uint32_t magic; wifi_manager_ap_info_t aps[CONFIG_WIFI_MANAGER_MAX_AP]; } ap_store_t; ap_store_t ap_store; static EventGroupHandle_t wm_event_group; uint8_t wifi_manager_ap_count() { return ap_store.count; }; static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) { ESP_LOGI(TAG, "wifi event: %d", event->event_id); switch (event->event_id) { case SYSTEM_EVENT_STA_START: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); ESP_ERROR_CHECK(esp_wifi_connect()); break; case SYSTEM_EVENT_STA_GOT_IP: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); ESP_LOGI(TAG, "Got IP: %s\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); xEventGroupSetBits(wm_event_group, WIFI_CONNECTED); break; case SYSTEM_EVENT_STA_DISCONNECTED: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); xEventGroupClearBits(wm_event_group, WIFI_CONNECTED); vTaskDelay(CONFIG_WIFI_MANAGER_CONNECTION_DELAY / portTICK_PERIOD_MS); // inc to the next ap, if it's the last one go IDLE // else attempt to connect ap_store.last++; if(ap_store.count == ap_store.last) { ap_store.last = 0; xEventGroupSetBits(wm_event_group, WIFI_IDLE); } else { wifi_manager_connect(); ESP_ERROR_CHECK(esp_wifi_connect()); } break; default: break; } return ESP_OK; return ESP_OK; } uint8_t wifi_manager_add_ap(char *ssid, char *password) { strcpy(ap_store.aps[ap_store.count].ssid, (char *)ssid); strcpy(ap_store.aps[ap_store.count].password, (char *)password); ++ap_store.count; if(ap_store.last == -1) ap_store.last = 0; wifi_manager_save_config(); return ap_store.count; }; void wifi_manager_connect() { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { .sta = { } }; ESP_LOGI(TAG, "connecting to AP %d of %d", ap_store.last, ap_store.count); memcpy((char *)&wifi_config.sta.ssid, ap_store.aps[ap_store.last].ssid, strlen(ap_store.aps[ap_store.last].ssid) + 1); memcpy((char *)&wifi_config.sta.password, ap_store.aps[ap_store.last].password, strlen(ap_store.aps[ap_store.last].password) + 1); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "wifi_init_sta finished."); ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", wifi_config.sta.ssid, wifi_config.sta.password); }; void wifi_manager_main_loop() { ap_store.last = 0; while(true) { EventBits_t ev_bits = xEventGroupGetBits(wm_event_group); if(ev_bits & AP_AVAILABLE && (ev_bits & WIFI_CONNECTING) == 0) { ESP_LOGI(TAG, "AP Available, starting WiFi connect"); xEventGroupSetBits(wm_event_group, WIFI_CONNECTING); wifi_manager_connect(); } vTaskDelay(3000 / portTICK_PERIOD_MS); } } void wifi_manager_save_config() { ESP_LOGI(TAG, "writing %d byte config", sizeof(ap_store)); ESP_LOGI(TAG, "ap_store.magic = 0x%4X", ap_store.magic); ESP_LOGI(TAG, "ap_store.count = %d", ap_store.count); ESP_LOGI(TAG, "ap_store.last = %d", ap_store.last); uint8_t i = 0; for(; i < ap_store.count; i++) { ESP_LOGI(TAG, "AP: %s", ap_store.aps[i].ssid); } if(ap_store.count > 0) { ESP_LOGI(TAG, "setting AP_AVAILABLE"); xEventGroupSetBits(wm_event_group, AP_AVAILABLE); } ESP_ERROR_CHECK(nvs_set_blob(nvs, "config", &ap_store, (size_t)sizeof(ap_store))); nvs_commit(nvs); }; void wifi_manager_reset_store() { ESP_LOGW(TAG, "resetting store"); memset(&ap_store, 0, sizeof(ap_store)); ap_store.magic = WIFI_MANAGER_MAGIC; ap_store.last = -1; wifi_manager_save_config(); }; void wifi_manager_load_config() { size_t store_size = 0; esp_err_t err; err = nvs_get_blob(nvs, "config", NULL, &store_size); if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) ESP_ERROR_CHECK(err); err = nvs_get_blob(nvs, "config", &ap_store, &store_size); if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) ESP_ERROR_CHECK(err); if(ap_store.magic != WIFI_MANAGER_MAGIC) { ESP_LOGI(TAG, "load_config got bad magic: 0x%8X", ap_store.magic); wifi_manager_reset_store(); return wifi_manager_save_config(); } if(ap_store.count > 0) { xEventGroupSetBits(wm_event_group, AP_AVAILABLE); } uint8_t i = 0; for(; i < ap_store.count; i++) ESP_LOGI(TAG, "AP: %s", ap_store.aps[i].ssid); ESP_LOGI(TAG, "load_config found %d APs", ap_store.count); }; EventGroupHandle_t wifi_manager_start() { ESP_ERROR_CHECK(nvs_open("wm-config", NVS_READWRITE, &nvs)); wm_event_group = xEventGroupCreate(); wifi_manager_load_config(); tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL) ); xTaskCreate(&wifi_manager_main_loop, "wm_main_loop", 4096, NULL, 6, NULL); return wm_event_group; };