diff --git a/main/esp32-wifi-manager.c b/main/esp32-wifi-manager.c index 45cc857..d5c409a 100644 --- a/main/esp32-wifi-manager.c +++ b/main/esp32-wifi-manager.c @@ -2,31 +2,200 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" -#include "esp_log.h" +#include "esp_event_loop.h" #include "esp_heap_caps.h" -#include "esp_spi_flash.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" -typedef struct wifi_man_ap_info { +#include "lwip/err.h" +#include "lwip/sys.h" -} wifi_man_ap_info_t; +#include "esp32-wifi-manager.h" -static struct wifi_man_ap_store { +#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; - struct wifi_man_ap_info aps[CONFIG_WIFI_MANAGER_MAX_AP]; -} wifi_man_ap_store; + wifi_manager_ap_info_t aps[CONFIG_WIFI_MANAGER_MAX_AP]; +} ap_store_t; -void wifi_man_init_config() { - spi_flash_read(CONFIG_WIFI_MANAGER_MEM_ADDR, &wifi_man_ap_store, sizeof(struct wifi_man_ap_store)); +ap_store_t ap_store; +static EventGroupHandle_t wm_event_group; +const int WIFI_CONNECTED = BIT0; +const int WIFI_CONNECTING = BIT1; +const int AP_AVAILABLE = BIT2; + +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"); + ESP_ERROR_CHECK(esp_wifi_connect()); + + xEventGroupClearBits(wm_event_group, WIFI_CONNECTED); + break; + default: + break; + } + return ESP_OK; + + return ESP_OK; } -int wifi_man_load_config() { - uint8_t count = 0; +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); - return count; + ++ap_store.count; + + wifi_manager_save_config(); + + return ap_store.count; +}; + +void wifi_manager_connect() { + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config = { + .sta = { + } + }; + + 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() { + 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); + + ap_store.last = 0; + + 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() { + 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); +}; + +void wifi_manager_start() { + ESP_ERROR_CHECK(nvs_open("wm-config", NVS_READWRITE, &nvs)); + + wm_event_group = xEventGroupCreate(); + + wifi_manager_load_config(); + + xTaskCreate(&wifi_manager_main_loop, "wm_main_loop", 4096, NULL, 6, NULL); };