Thu, 13 Apr 2023 12:08:24 +0200
Version 0.4.0. Disable normal logging mqtt.
/** * @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. esp_event_handler_instance_t instance_any_id; ///< WiFi event handler. esp_event_handler_instance_t instance_got_ip; ///< IP event handler. 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. static void init_wifi(void); void wifi_connect(void); /****************************************************************************/ bool ready_WiFi(void) { if ((xEventGroupGetBits(xEventGroupWifi) & (TASK_WIFI_STA_CONNECTED | TASK_WIFI_HAS_IP)) == (TASK_WIFI_STA_CONNECTED | TASK_WIFI_HAS_IP)) 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 break; case WIFI_EVENT_STA_CONNECTED: { 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: { wifi_event_sta_disconnected_t* disconnected = (wifi_event_sta_disconnected_t*) event_data; ESP_LOGI(TAG, "Event STA disconnected, reason: %d", disconnected->reason); /* * If it's not a normal request to disconnect, make sure the mqtt * connection will be removed. */ if (disconnected->reason != 8) request_mqtt(false); /* * Error conditions. */ if (disconnected->reason == 2) { ESP_LOGW(TAG, "Auth Expire: try to recover"); wifi_connect(); } else if (disconnected->reason == 39) { ESP_LOGW(TAG, "Timeout: try to recover"); ESP_ERROR_CHECK(esp_wifi_connect()); } if (xSemaphoreTake(xSemaphoreWiFi, 25) == pdTRUE) { wifi_state->STA_connected = false; wifi_state->STA_online = false; xSemaphoreGive(xSemaphoreWiFi); } else { ESP_LOGE(TAG, "wifi_event_handler() lock error WIFI_EVENT_STA_DISCONNECTED"); } 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"); } 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"); } break; default: ESP_LOGW(TAG, "Unknown IP event %d", (int)event_id); break; } } static void init_wifi(void) { ESP_ERROR_CHECK(esp_event_loop_create_default()); xSemaphoreWiFi = xSemaphoreCreateMutex(); /* initialize the tcp stack */ ESP_ERROR_CHECK(esp_netif_init()); sta_netif = esp_netif_create_default_wifi_sta(); assert(sta_netif); wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); 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, 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_start()); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_CONNECTED); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_DISCONNECTED); } void wifi_connect(void) { ESP_LOGI(TAG, "wifi_connect() start"); wifi_config_t wifi_Config = { ///< Current STA configuration. .sta = { .ssid = ESP_WIFI_SSID, .password = ESP_WIFI_PASS, .threshold.authmode = WIFI_AUTH_WPA2_PSK, }, }; // .threshold.authmode = WIFI_AUTH_WPA2_PSK, ESP_ERROR_CHECK(esp_wifi_disconnect()); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_Config) ); xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); esp_err_t wifierror = esp_wifi_connect(); if (wifierror != ESP_OK) { ESP_LOGE(TAG, "esp_wifi_connect() rc=%04x %s", (int)wifierror, esp_err_to_name(wifierror)); xEventGroupSetBits(xEventGroupWifi, TASK_WIFI_STA_FAILED); } else { ESP_LOGI(TAG, "Connected Ok"); } ESP_LOGI(TAG, "wifi_connect() done"); } void task_wifi( void * pvParameters ) { // uint64_t starttime = 0; ESP_LOGI(TAG, "Starting WiFi task"); esp_log_level_set("wifi", ESP_LOG_ERROR); /* * memory allocation of objects used by the task */ wifi_state = malloc(sizeof(WIFI_State)); memset(wifi_state, 0x00, sizeof(WIFI_State)); /* * event group for the wifi driver */ xEventGroupWifi = xEventGroupCreate(); /* * init wifi as station */ init_wifi(); EventBits_t uxBits; int8_t tx_level; ESP_ERROR_CHECK(esp_wifi_get_max_tx_power(&tx_level)); ESP_LOGI(TAG, "Startup completed, maximum transmit power %d dBm", tx_level / 4); 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 */ 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); // ESP_LOGI(TAG, "Connection time %llu", (esp_timer_get_time() / 1000) - starttime); } else if (uxBits & TASK_WIFI_REQUEST_STA_CONNECT) { ESP_LOGI(TAG, "Request STA connect `%s' `%s'", ESP_WIFI_SSID, ESP_WIFI_PASS); // starttime = esp_timer_get_time() / 1000; wifi_connect(); /* * 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_FAILED) { ESP_LOGI(TAG, "No AP found"); vTaskDelay(3000 / portTICK_PERIOD_MS); ESP_LOGW(TAG, "Connection failed"); /* failed attempt to connect regardles of the reason */ } } /* * Finally: release the request bit */ xEventGroupClearBits(xEventGroupWifi, TASK_WIFI_REQUEST_STA_CONNECT); } } /* for(;;) */ }