#include "wifi_manager.h" #include "esp_log.h" #include "esp_system.h" #include "nvs_flash.h" #include static const char *TAG = "WIFI_MANAGER"; // WiFi manager state static bool is_initialized = false; static wifi_status_t current_status = WIFI_STATUS_DISCONNECTED; static EventGroupHandle_t wifi_event_group = NULL; static wifi_event_callback_t user_callback = NULL; static char stored_ip[16] = {0}; // Event group bits #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 // Event handler instances static esp_event_handler_instance_t instance_any_id; static esp_event_handler_instance_t instance_got_ip; // WiFi event handler static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "WiFi started, connecting..."); current_status = WIFI_STATUS_CONNECTING; esp_wifi_connect(); if (user_callback) { user_callback(current_status, NULL); } } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { ESP_LOGI(TAG, "WiFi disconnected, trying to reconnect..."); current_status = WIFI_STATUS_DISCONNECTED; memset(stored_ip, 0, sizeof(stored_ip)); esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); if (user_callback) { user_callback(current_status, NULL); } } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; snprintf(stored_ip, sizeof(stored_ip), IPSTR, IP2STR(&event->ip_info.ip)); ESP_LOGI(TAG, "WiFi connected! IP: %s", stored_ip); current_status = WIFI_STATUS_CONNECTED; xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); if (user_callback) { user_callback(current_status, stored_ip); } } } esp_err_t wifi_manager_init(const char *ssid, const char *password, wifi_event_callback_t event_callback) { if (is_initialized) { ESP_LOGW(TAG, "WiFi manager already initialized"); return ESP_OK; } if (ssid == NULL || password == NULL) { ESP_LOGE(TAG, "SSID and password cannot be NULL"); return ESP_ERR_INVALID_ARG; } ESP_LOGI(TAG, "Initializing WiFi manager"); user_callback = event_callback; current_status = WIFI_STATUS_DISCONNECTED; // Create event group wifi_event_group = xEventGroupCreate(); if (wifi_event_group == NULL) { ESP_LOGE(TAG, "Failed to create WiFi event group"); return ESP_ERR_NO_MEM; } // Initialize netif ESP_ERROR_CHECK(esp_netif_init()); // Create default event loop if not exists esp_err_t ret = esp_event_loop_create_default(); if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { ESP_LOGE(TAG, "Failed to create event loop: %s", esp_err_to_name(ret)); vEventGroupDelete(wifi_event_group); wifi_event_group = NULL; return ret; } // Create default WiFi STA esp_netif_create_default_wifi_sta(); // Initialize WiFi wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ret = esp_wifi_init(&cfg); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize WiFi: %s", esp_err_to_name(ret)); vEventGroupDelete(wifi_event_group); wifi_event_group = NULL; return ret; } // Register event handlers ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to register WiFi event handler: %s", esp_err_to_name(ret)); esp_wifi_deinit(); vEventGroupDelete(wifi_event_group); wifi_event_group = NULL; return ret; } ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to register IP event handler: %s", esp_err_to_name(ret)); esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id); esp_wifi_deinit(); vEventGroupDelete(wifi_event_group); wifi_event_group = NULL; return ret; } // Configure WiFi wifi_config_t wifi_config = { .sta = { .threshold.authmode = WIFI_AUTH_WPA2_PSK, }, }; strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid) - 1); strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password) - 1); ret = esp_wifi_set_mode(WIFI_MODE_STA); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi mode: %s", esp_err_to_name(ret)); wifi_manager_deinit(); return ret; } ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_config); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set WiFi config: %s", esp_err_to_name(ret)); wifi_manager_deinit(); return ret; } is_initialized = true; ESP_LOGI(TAG, "WiFi manager initialized successfully"); return ESP_OK; } esp_err_t wifi_manager_start(void) { if (!is_initialized) { ESP_LOGE(TAG, "WiFi manager not initialized"); return ESP_ERR_INVALID_STATE; } ESP_LOGI(TAG, "Starting WiFi"); esp_err_t ret = esp_wifi_start(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to start WiFi: %s", esp_err_to_name(ret)); current_status = WIFI_STATUS_ERROR; return ret; } return ESP_OK; } esp_err_t wifi_manager_stop(void) { if (!is_initialized) { ESP_LOGE(TAG, "WiFi manager not initialized"); return ESP_ERR_INVALID_STATE; } ESP_LOGI(TAG, "Stopping WiFi"); current_status = WIFI_STATUS_DISCONNECTED; memset(stored_ip, 0, sizeof(stored_ip)); esp_err_t ret = esp_wifi_stop(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to stop WiFi: %s", esp_err_to_name(ret)); return ret; } return ESP_OK; } wifi_status_t wifi_manager_get_status(void) { return current_status; } bool wifi_manager_wait_for_connection(uint32_t timeout_ms) { if (!is_initialized || wifi_event_group == NULL) { ESP_LOGE(TAG, "WiFi manager not initialized"); return false; } TickType_t timeout_ticks = (timeout_ms == 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms); EventBits_t bits = xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, timeout_ticks); return (bits & WIFI_CONNECTED_BIT) != 0; } esp_err_t wifi_manager_get_ip_address(char *ip_str, size_t buffer_size) { if (ip_str == NULL || buffer_size < 16) { ESP_LOGE(TAG, "Invalid parameters for IP address"); return ESP_ERR_INVALID_ARG; } if (current_status != WIFI_STATUS_CONNECTED || strlen(stored_ip) == 0) { ESP_LOGW(TAG, "WiFi not connected or no IP address available"); return ESP_ERR_INVALID_STATE; } strncpy(ip_str, stored_ip, buffer_size - 1); ip_str[buffer_size - 1] = '\0'; return ESP_OK; } bool wifi_manager_is_connected(void) { return current_status == WIFI_STATUS_CONNECTED; } esp_err_t wifi_manager_deinit(void) { if (!is_initialized) { ESP_LOGW(TAG, "WiFi manager not initialized"); return ESP_OK; } ESP_LOGI(TAG, "Deinitializing WiFi manager"); // Stop WiFi if running esp_wifi_stop(); // Unregister event handlers if (instance_any_id != NULL) { esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id); instance_any_id = NULL; } if (instance_got_ip != NULL) { esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip); instance_got_ip = NULL; } // Deinitialize WiFi esp_wifi_deinit(); // Delete event group if (wifi_event_group != NULL) { vEventGroupDelete(wifi_event_group); wifi_event_group = NULL; } current_status = WIFI_STATUS_DISCONNECTED; memset(stored_ip, 0, sizeof(stored_ip)); user_callback = NULL; is_initialized = false; ESP_LOGI(TAG, "WiFi manager deinitialized"); return ESP_OK; }