esp32-wifi-manager/main/esp32-wifi-manager.c

218 lines
5.4 KiB
C

#include <string.h>
#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;
void wifi_manager_connect();
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);
ap_store.last++;
if(ap_store.count == ap_store.last) {
ap_store.last = 0;
}
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;
};