diff -r e5d91caa6ab4 -r d0155c16e992 main/task_wifi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/task_wifi.c Wed Mar 29 21:39:07 2023 +0200 @@ -0,0 +1,286 @@ +/** + * @file task_wifi.c + * @brief WiFi task. Connects to a known Access Point. + */ + + +#include "config.h" + + +static const char *TAG = "task_wifi"; + +#define ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +SemaphoreHandle_t xSemaphoreWiFi = NULL; ///< Semaphore WiFi task. +EventGroupHandle_t xEventGroupWifi; ///< Events WiFi task. +wifi_config_t wifi_Config = { ///< Current STA configuration. + .sta = { + .ssid = ESP_WIFI_SSID, + .password = ESP_WIFI_PASS, + .scan_method = WIFI_FAST_SCAN, + .sort_method = WIFI_CONNECT_AP_BY_SECURITY, + .threshold.rssi = -127, + .threshold.authmode = WIFI_AUTH_WPA2_PSK, + }, +}; +WIFI_State *wifi_state = NULL; ///< Public state for other tasks. +esp_netif_t *sta_netif = NULL; ///< Station interface + + +const int TASK_WIFI_REQUEST_STA_DISCONNECT = BIT1; ///< When set, means a client requested to disconnect from currently connected AP. +const int TASK_WIFI_REQUEST_STA_CONNECT = BIT2; ///< When set, means a client requested to connect to an access point. + +const int TASK_WIFI_HAS_IP = BIT3; ///< Indicate that we have an IP address +const int TASK_WIFI_STA_FAILED = BIT5; ///< Indicate that we could not get a connection to AP as station. +const int TASK_WIFI_STA_DISCONNECTED = BIT6; ///< Indicate that we are disconnected from an ap station. +const int TASK_WIFI_STA_CONNECTED = BIT7; ///< Indicate that we are connected to AP as station, flip of BIT6. + + +/****************************************************************************/ + + +bool ready_WiFi(void) +{ + if (wifi_state->STA_connected && wifi_state->STA_online) + return true; + return false; +} + + + +void request_WiFi(bool connect) +{ + if (connect) + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); + else + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); +} + + + +static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + switch (event_id) { + + case WIFI_EVENT_STA_START: + ESP_LOGI(TAG, "Event wifi START"); + // Set the hostname for the dhcp client. +#ifdef CONFIG_CODE_PRODUCTION + ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "balkon")); +#endif +#ifdef CONFIG_CODE_TESTING + ESP_ERROR_CHECK(esp_netif_set_hostname(sta_netif, "wemos")); +#endif +// ESP_ERROR_CHECK(esp_wifi_connect()); + break; + + case WIFI_EVENT_STA_CONNECTED: { +// system_event_sta_connected_t* event = (wifi_event_sta_connected_t*) event_data; + wifi_ap_record_t ap_info; + esp_wifi_sta_get_ap_info(&ap_info); + ESP_LOGI(TAG, "Event STA connected rssi=%d", ap_info.rssi); + if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { + wifi_state->STA_connected = true; + wifi_state->STA_rssi = ap_info.rssi; + xSemaphoreGive(xSemaphoreWiFi); + } else { + ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_CONNECTED"); + } + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); + break; + } + + case WIFI_EVENT_STA_DISCONNECTED: { + ESP_LOGI(TAG, "Event STA disconnected"); +// wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; +// ESP_LOGI(TAG, "Event STA disconnected, reason:%d", disconnected->reason); + if (xSemaphoreTake(xSemaphoreWiFi, 35) == pdTRUE) { + wifi_state->STA_connected = false; + wifi_state->STA_online = false; + //wifi_state->STA_rssi = 0; + xSemaphoreGive(xSemaphoreWiFi); + } else { + ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED"); + } +// connect_mqtt(false); + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); + break; + } + + default: + ESP_LOGW(TAG, "Unknown WiFi event %d", (int)event_id); + break; + } +} + + + +static void got_ip_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + switch (event_id) { + + case IP_EVENT_STA_GOT_IP: + ESP_LOGE(TAG, "got_ip_event_handler()"); + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_HAS_IP); + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { + wifi_state->STA_online = true; + snprintf(wifi_state->STA_ip, 16, IPSTR, IP2STR(&event->ip_info.ip)); + snprintf(wifi_state->STA_nm, 16, IPSTR, IP2STR(&event->ip_info.netmask)); + snprintf(wifi_state->STA_gw, 16, IPSTR, IP2STR(&event->ip_info.gw)); + xSemaphoreGive(xSemaphoreWiFi); + } else { + ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_GOT_IP"); + } +// connect_mqtt(true); + break; + + case IP_EVENT_STA_LOST_IP: + ESP_LOGW(TAG, "Lost IP address"); + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_HAS_IP); + if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { + wifi_state->STA_ip[0] = '\0'; + wifi_state->STA_nm[0] = '\0'; + wifi_state->STA_gw[0] = '\0'; + wifi_state->STA_online = false; + xSemaphoreGive(xSemaphoreWiFi); + } else { + ESP_LOGE(TAG, "got_ip_event_handler() lock error IP_EVENT_STA_LOST_IP"); + } +// connect_mqtt(false); + break; + + case IP_EVENT_AP_STAIPASSIGNED: + ESP_LOGI(TAG, "IP_EVENT_AP_STAIPASSIGNED"); + break; + + default: + ESP_LOGW(TAG, "Unknown IP event %d", (int)event_id); + break; + } +} + + + +void task_wifi( void * pvParameters ) +{ + ESP_LOGI(TAG, "Start WiFi"); + + /* + * Initialize NVS + */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + /* event handler and event group for the wifi driver */ + xEventGroupWifi = xEventGroupCreate(); + /* initialize the tcp stack */ + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + sta_netif = esp_netif_create_default_wifi_sta(); + assert(sta_netif); + + /* + * memory allocation of objects used by the task + */ + xSemaphoreWiFi = xSemaphoreCreateMutex(); + wifi_state = malloc(sizeof(WIFI_State)); + memset(wifi_state, 0x00, sizeof(WIFI_State)); + sprintf(wifi_state->STA_ssid, "%s", ESP_WIFI_SSID); + + /* + * init wifi as station + */ + wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id) ); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, /*IP_EVENT_STA_GOT_IP*/ ESP_EVENT_ANY_ID, &got_ip_event_handler, NULL, &instance_got_ip) ); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_Config) ); + ESP_ERROR_CHECK(esp_wifi_start()); + + //xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); + EventBits_t uxBits; + + ESP_LOGI(TAG, "Startup completed, enter task loop"); + + for(;;) { + + /* actions that can trigger: request a connection or a disconnection */ + uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT | TASK_WIFI_REQUEST_STA_DISCONNECT, + pdFALSE, pdFALSE, portMAX_DELAY ); + + if (uxBits & TASK_WIFI_REQUEST_STA_DISCONNECT) { + /* + * user requested a disconnect, this will in effect disconnect the wifi + */ +// connect_mqtt(false); + ESP_LOGI(TAG, "Request STA disconnect"); + ESP_ERROR_CHECK(esp_wifi_disconnect()); + xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED, pdFALSE, pdTRUE, portMAX_DELAY ); + + /* finally: release the request bit */ + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_DISCONNECT); + + } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) { + + ESP_LOGI(TAG, "Request STA connect `%s' `%s'", wifi_Config.sta.ssid, wifi_Config.sta.password); + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_Config)); + + esp_err_t wifierror = esp_wifi_connect(); + if (wifierror != ESP_OK) { + ESP_LOGE(TAG, "esp_wifi_connect() rc=%04x", (int)wifierror); + xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); + } else { + ESP_LOGI(TAG, "Connected Ok"); + } + + /* + * 3 scenarios here: connection is successful and TASK_WIFI_STA_CONNECTED will be posted + * or it's a failure and we get a TASK_WIFI_STA_FAILED with a reason code. + * Or, option 3, the 5 seconds timeout is reached. This happens when the AP is not in range. + * Note that the reason code is not exploited. For all intent and purposes a failure is a failure. + */ + uxBits = xEventGroupWaitBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED, pdFALSE, pdFALSE, 5000 / portTICK_PERIOD_MS); + + if (uxBits & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_STA_FAILED)) { + /* + * only save the config if the connection was successful! + */ + if (uxBits & TASK_WIFI_STA_CONNECTED) { + /* save wifi config */ + //SaveStaConfig(); + } else { + ESP_LOGI(TAG, "No AP found"); + vTaskDelay(3000 / portTICK_PERIOD_MS); + ESP_LOGW(TAG, "Connection failed"); + /* failed attempt to connect regardles of the reason */ + + /* otherwise: reset the config */ + //memset(task_wifi_ConfigSTA, 0x00, sizeof(wifi_config_t)); + } + } + + /* finally: release the request bit */ + xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); + } + + } /* for(;;) */ + vTaskDelay(10 / portTICK_PERIOD_MS); +} + +