main/task_wifi.c

changeset 4
d0155c16e992
child 5
b1f38105ca7e
--- /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);
+}
+
+

mercurial