diff --git a/wifi_manager/main/Kconfig.projbuild b/wifi_manager/main/Kconfig.projbuild index 3d928274..b1dbe5fe 100644 --- a/wifi_manager/main/Kconfig.projbuild +++ b/wifi_manager/main/Kconfig.projbuild @@ -1,5 +1,17 @@ menu "Wifi Manager Configuration" +config WIFI_MANAGER_TASK_PRIORITY + int "RTOS Task Priority for the wifi_manager" + default 5 + help + Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. For this particular reason, minimum recommended task priority is 2. + +config WIFI_MANAGER_MAX_RETRY + int "Max Retry on failed connection" + default 2 + help + Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up. + config DEFAULT_AP_SSID string "Access Point SSID" default "esp32" @@ -20,13 +32,13 @@ config DEFAULT_AP_CHANNEL config DEFAULT_AP_IP string "Access Point IP Address" - default "192.168.1.1" + default "10.10.0.1" help This is used for the redirection to the captive portal. It is recommended to leave unchanged. config DEFAULT_AP_GATEWAY string "Access Point IP Gateway" - default "192.168.1.1" + default "10.10.0.1" help This is used for the redirection to the captive portal. It is recommended to leave unchanged. diff --git a/wifi_manager/main/dns_server.c b/wifi_manager/main/dns_server.c index 7305446c..cce537ab 100644 --- a/wifi_manager/main/dns_server.c +++ b/wifi_manager/main/dns_server.c @@ -56,9 +56,19 @@ Contains the freeRTOS task for the DNS server that processes the requests. static const char TAG[] = "dns_server"; static TaskHandle_t task_dns_server = NULL; +int socket_fd; void dns_server_start() { - xTaskCreate(&dns_server, "dns_server", 3072, NULL, 5, &task_dns_server); + xTaskCreate(&dns_server, "dns_server", 3072, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_dns_server); +} + +void dns_server_stop(){ + if(task_dns_server){ + vTaskDelete(task_dns_server); + close(socket_fd); + task_dns_server = NULL; + } + } @@ -66,7 +76,7 @@ void dns_server_start() { void dns_server(void *pvParameters) { - int socket_fd; + struct sockaddr_in sa, ra; /* Set redirection DNS hijack to the access point IP */ @@ -108,6 +118,7 @@ void dns_server(void *pvParameters) { /* Start loop to process DNS requests */ for(;;) { + memset(data, 0x00, sizeof(data)); /* reset buffer */ length = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr *)&client, &client_len); /* read udp request */ @@ -159,10 +170,12 @@ void dns_server(void *pvParameters) { } } - vTaskDelay( (TickType_t)10); /* allows the freeRTOS scheduler to take over if needed. DNS daemon should not be taxing on the system */ + taskYIELD(); /* allows the freeRTOS scheduler to take over if needed. DNS daemon should not be taxing on the system */ + } close(socket_fd); + vTaskDelete ( NULL ); } diff --git a/wifi_manager/main/dns_server.h b/wifi_manager/main/dns_server.h index 11ff6577..d1da1f8c 100644 --- a/wifi_manager/main/dns_server.h +++ b/wifi_manager/main/dns_server.h @@ -125,6 +125,7 @@ typedef struct __attribute__((__packed__)) dns_answer_t{ void dns_server(void *pvParameters); void dns_server_start(); +void dns_server_stop(); diff --git a/wifi_manager/main/http_server.c b/wifi_manager/main/http_server.c index 80ae0f81..d10b14dc 100644 --- a/wifi_manager/main/http_server.c +++ b/wifi_manager/main/http_server.c @@ -60,10 +60,12 @@ function to process requests, decode URLs, serve files, etc. etc. #include "wifi_manager.h" -EventGroupHandle_t http_server_event_group = NULL; -EventBits_t uxBits; +//EventGroupHandle_t http_server_event_group = NULL; +//EventBits_t uxBits; static const char TAG[] = "http_server"; +static TaskHandle_t task_http_server = NULL; + /* embedded binary data */ extern const uint8_t style_css_start[] asm("_binary_style_css_start"); @@ -90,21 +92,14 @@ const static char http_redirect_hdr_end[] = "/\n\n"; -void http_server_set_event_start(){ - if(!http_server_event_group) http_server_event_group = xEventGroupCreate(); - xEventGroupSetBits(http_server_event_group, HTTP_SERVER_START_BIT_0 ); +void http_server_start(){ + if(task_http_server == NULL){ + xTaskCreate(&http_server, "http_server", 2048, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); + } } - void http_server(void *pvParameters) { - if(!http_server_event_group) http_server_event_group = xEventGroupCreate(); - - /* do not start the task until wifi_manager says it's safe to do so! */ - ESP_LOGD(TAG, "waiting for start bit"); - uxBits = xEventGroupWaitBits(http_server_event_group, HTTP_SERVER_START_BIT_0, pdFALSE, pdTRUE, portMAX_DELAY ); - ESP_LOGD(TAG, "received start bit, starting server"); - struct netconn *conn, *newconn; err_t err; conn = netconn_new(NETCONN_TCP); @@ -117,10 +112,12 @@ void http_server(void *pvParameters) { http_server_netconn_serve(newconn); netconn_delete(newconn); } - vTaskDelay( (TickType_t)10); /* allows the freeRTOS scheduler to take over if needed */ + taskYIELD(); /* allows the freeRTOS scheduler to take over if needed. */ } while(err == ERR_OK); netconn_close(conn); netconn_delete(conn); + + vTaskDelete( NULL ); } @@ -162,98 +159,104 @@ void http_server_netconn_serve(struct netconn *conn) { if(line) { - - /* captive portal functionality: redirect to the access point IP addresss */ + /* captive portal functionality: redirect to access point IP for HOST that are not the access point IP OR the STA IP */ int lenH = 0; char *host = http_server_get_header(save_ptr, "Host: ", &lenH); - if ((sizeof(host) > 0) && !strstr(host, DEFAULT_AP_IP)) { + /* determine if Host is from the STA IP address */ + wifi_manager_lock_sta_ip_string(portMAX_DELAY); + bool access_from_sta_ip = lenH > 0?strstr(host, wifi_manager_get_sta_ip_string()):false; + wifi_manager_unlock_sta_ip_string(); + + if (lenH > 0 && !strstr(host, DEFAULT_AP_IP) && !access_from_sta_ip) { netconn_write(conn, http_redirect_hdr_start, sizeof(http_redirect_hdr_start) - 1, NETCONN_NOCOPY); netconn_write(conn, DEFAULT_AP_IP, sizeof(DEFAULT_AP_IP) - 1, NETCONN_NOCOPY); netconn_write(conn, http_redirect_hdr_end, sizeof(http_redirect_hdr_end) - 1, NETCONN_NOCOPY); } - /* default page */ - else if(strstr(line, "GET / ")) { - netconn_write(conn, http_html_hdr, sizeof(http_html_hdr) - 1, NETCONN_NOCOPY); - netconn_write(conn, index_html_start, index_html_end - index_html_start, NETCONN_NOCOPY); - } - else if(strstr(line, "GET /jquery.js ")) { - netconn_write(conn, http_jquery_gz_hdr, sizeof(http_jquery_gz_hdr) - 1, NETCONN_NOCOPY); - netconn_write(conn, jquery_gz_start, jquery_gz_end - jquery_gz_start, NETCONN_NOCOPY); - } - else if(strstr(line, "GET /code.js ")) { - netconn_write(conn, http_js_hdr, sizeof(http_js_hdr) - 1, NETCONN_NOCOPY); - netconn_write(conn, code_js_start, code_js_end - code_js_start, NETCONN_NOCOPY); - } - else if(strstr(line, "GET /ap.json ")) { - /* if we can get the mutex, write the last version of the AP list */ - if(wifi_manager_lock_json_buffer(( TickType_t ) 10)){ - netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); - char *buff = wifi_manager_get_ap_list_json(); - netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); - wifi_manager_unlock_json_buffer(); + else{ + /* default page */ + if(strstr(line, "GET / ")) { + netconn_write(conn, http_html_hdr, sizeof(http_html_hdr) - 1, NETCONN_NOCOPY); + netconn_write(conn, index_html_start, index_html_end - index_html_start, NETCONN_NOCOPY); } - else{ - netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); - ESP_LOGD(TAG, "http_server_netconn_serve: GET /ap.json failed to obtain mutex"); + else if(strstr(line, "GET /jquery.js ")) { + netconn_write(conn, http_jquery_gz_hdr, sizeof(http_jquery_gz_hdr) - 1, NETCONN_NOCOPY); + netconn_write(conn, jquery_gz_start, jquery_gz_end - jquery_gz_start, NETCONN_NOCOPY); } - /* request a wifi scan */ - wifi_manager_scan_async(); - } - else if(strstr(line, "GET /style.css ")) { - netconn_write(conn, http_css_hdr, sizeof(http_css_hdr) - 1, NETCONN_NOCOPY); - netconn_write(conn, style_css_start, style_css_end - style_css_start, NETCONN_NOCOPY); - } - else if(strstr(line, "GET /status.json ")){ - if(wifi_manager_lock_json_buffer(( TickType_t ) 10)){ - char *buff = wifi_manager_get_ip_info_json(); - if(buff){ + else if(strstr(line, "GET /code.js ")) { + netconn_write(conn, http_js_hdr, sizeof(http_js_hdr) - 1, NETCONN_NOCOPY); + netconn_write(conn, code_js_start, code_js_end - code_js_start, NETCONN_NOCOPY); + } + else if(strstr(line, "GET /ap.json ")) { + /* if we can get the mutex, write the last version of the AP list */ + if(wifi_manager_lock_json_buffer(( TickType_t ) 10)){ netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); + char *buff = wifi_manager_get_ap_list_json(); netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); wifi_manager_unlock_json_buffer(); } else{ netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); + ESP_LOGD(TAG, "http_server_netconn_serve: GET /ap.json failed to obtain mutex"); } + /* request a wifi scan */ + wifi_manager_scan_async(); } - else{ - netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); - ESP_LOGD(TAG, "http_server_netconn_serve: GET /status failed to obtain mutex"); + else if(strstr(line, "GET /style.css ")) { + netconn_write(conn, http_css_hdr, sizeof(http_css_hdr) - 1, NETCONN_NOCOPY); + netconn_write(conn, style_css_start, style_css_end - style_css_start, NETCONN_NOCOPY); } - } - else if(strstr(line, "DELETE /connect.json ")) { - ESP_LOGD(TAG, "http_server_netconn_serve: DELETE /connect.json"); - /* request a disconnection from wifi and forget about it */ - wifi_manager_disconnect_async(); - netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */ - } - else if(strstr(line, "POST /connect.json ")) { - ESP_LOGD(TAG, "http_server_netconn_serve: POST /connect.json"); - - bool found = false; - int lenS = 0, lenP = 0; - char *ssid = NULL, *password = NULL; - ssid = http_server_get_header(save_ptr, "X-Custom-ssid: ", &lenS); - password = http_server_get_header(save_ptr, "X-Custom-pwd: ", &lenP); - - if(ssid && lenS <= MAX_SSID_SIZE && password && lenP <= MAX_PASSWORD_SIZE){ - wifi_config_t* config = wifi_manager_get_wifi_sta_config(); - memset(config, 0x00, sizeof(wifi_config_t)); - memcpy(config->sta.ssid, ssid, lenS); - memcpy(config->sta.password, password, lenP); - ESP_LOGD(TAG, "http_server_netconn_serve: wifi_manager_connect_async() call"); - wifi_manager_connect_async(); - netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok - found = true; + else if(strstr(line, "GET /status.json ")){ + if(wifi_manager_lock_json_buffer(( TickType_t ) 10)){ + char *buff = wifi_manager_get_ip_info_json(); + if(buff){ + netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); + netconn_write(conn, buff, strlen(buff), NETCONN_NOCOPY); + wifi_manager_unlock_json_buffer(); + } + else{ + netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); + } + } + else{ + netconn_write(conn, http_503_hdr, sizeof(http_503_hdr) - 1, NETCONN_NOCOPY); + ESP_LOGD(TAG, "http_server_netconn_serve: GET /status failed to obtain mutex"); + } + } + else if(strstr(line, "DELETE /connect.json ")) { + ESP_LOGD(TAG, "http_server_netconn_serve: DELETE /connect.json"); + /* request a disconnection from wifi and forget about it */ + wifi_manager_disconnect_async(); + netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); /* 200 ok */ } + else if(strstr(line, "POST /connect.json ")) { + ESP_LOGD(TAG, "http_server_netconn_serve: POST /connect.json"); + + bool found = false; + int lenS = 0, lenP = 0; + char *ssid = NULL, *password = NULL; + ssid = http_server_get_header(save_ptr, "X-Custom-ssid: ", &lenS); + password = http_server_get_header(save_ptr, "X-Custom-pwd: ", &lenP); + + if(ssid && lenS <= MAX_SSID_SIZE && password && lenP <= MAX_PASSWORD_SIZE){ + wifi_config_t* config = wifi_manager_get_wifi_sta_config(); + memset(config, 0x00, sizeof(wifi_config_t)); + memcpy(config->sta.ssid, ssid, lenS); + memcpy(config->sta.password, password, lenP); + ESP_LOGD(TAG, "http_server_netconn_serve: wifi_manager_connect_async() call"); + wifi_manager_connect_async(); + netconn_write(conn, http_ok_json_no_cache_hdr, sizeof(http_ok_json_no_cache_hdr) - 1, NETCONN_NOCOPY); //200ok + found = true; + } + + if(!found){ + /* bad request the authentification header is not complete/not the correct format */ + netconn_write(conn, http_400_hdr, sizeof(http_400_hdr) - 1, NETCONN_NOCOPY); + } - if(!found){ - /* bad request the authentification header is not complete/not the correct format */ + } + else{ netconn_write(conn, http_400_hdr, sizeof(http_400_hdr) - 1, NETCONN_NOCOPY); } - - } - else{ - netconn_write(conn, http_400_hdr, sizeof(http_400_hdr) - 1, NETCONN_NOCOPY); } } else{ diff --git a/wifi_manager/main/http_server.h b/wifi_manager/main/http_server.h index 2ac7c321..eba6a5f0 100644 --- a/wifi_manager/main/http_server.h +++ b/wifi_manager/main/http_server.h @@ -43,7 +43,8 @@ extern "C" { void http_server(void *pvParameters); void http_server_netconn_serve(struct netconn *conn); -void http_server_set_event_start(); +//void http_server_set_event_start(); //TODO: delete +void http_server_start(); /** * @brief gets a char* pointer to the first occurence of header_name withing the complete http request request. diff --git a/wifi_manager/main/index.html b/wifi_manager/main/index.html index 8b82d581..b4a218d8 100644 --- a/wifi_manager/main/index.html +++ b/wifi_manager/main/index.html @@ -119,7 +119,7 @@
esp32-wifi-manager, © 2017, Tony Pottier
Licender under the MIT License.
esp32-wifi-manager, © 2017-2019, Tony Pottier
Licender under the MIT License.
This app would not be possible without the following libraries:
diff --git a/wifi_manager/main/main.c b/wifi_manager/main/main.c index 4ab80ee6..6836b9cf 100644 --- a/wifi_manager/main/main.c +++ b/wifi_manager/main/main.c @@ -52,8 +52,7 @@ SOFTWARE. -static TaskHandle_t task_http_server = NULL; -static TaskHandle_t task_wifi_manager = NULL; + /* @brief tag used for ESP serial console messages */ static const char TAG[] = "main"; @@ -65,8 +64,8 @@ static const char TAG[] = "main"; void monitoring_task(void *pvParameter) { for(;;){ - ESP_LOGD(TAG, "free heap: %d",esp_get_free_heap_size()); - vTaskDelay(10000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "free heap: %d",esp_get_free_heap_size()); + vTaskDelay( pdMS_TO_TICKS(10000) ); } } @@ -75,17 +74,10 @@ void app_main() { - /* disable the default wifi logging */ - esp_log_level_set("wifi", ESP_LOG_NONE); - - /* initialize flash memory */ - nvs_flash_init(); - /* start the HTTP Server task */ - xTaskCreate(&http_server, "http_server", 2048, NULL, 5, &task_http_server); - /* start the wifi manager task */ - xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, 4, &task_wifi_manager); + /* start the wifi manager */ + wifi_manager_start(); /* your code should go here. Here we simply create a task on core 2 that monitors free heap memory */ xTaskCreatePinnedToCore(&monitoring_task, "monitoring_task", 2048, NULL, 1, NULL, 1); diff --git a/wifi_manager/main/wifi_manager.c b/wifi_manager/main/wifi_manager.c index e8be6e95..b010ede2 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -47,6 +47,7 @@ Contains the freeRTOS task and all necessary support #include "lwip/api.h" #include "lwip/err.h" #include "lwip/netdb.h" +#include "lwip/ip4_addr.h" #include "json.h" #include "http_server.h" @@ -55,7 +56,13 @@ Contains the freeRTOS task and all necessary support +/* objects used to manipulate the main queue of events */ +QueueHandle_t wifi_manager_queue; + + SemaphoreHandle_t wifi_manager_json_mutex = NULL; +SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL; +char *wifi_manager_sta_ip = NULL; uint16_t ap_num = MAX_AP_NUM; wifi_ap_record_t *accessp_records; char *accessp_json = NULL; @@ -65,6 +72,9 @@ wifi_config_t* wifi_manager_config_sta = NULL; /* @brief tag used for ESP serial console messages */ static const char TAG[] = "wifi_manager"; +/* @brief task handle for the main wifi_manager task */ +static TaskHandle_t task_wifi_manager = NULL; + /** * The actual WiFi settings in use */ @@ -86,11 +96,10 @@ EventGroupHandle_t wifi_manager_event_group; /* @brief indicate that the ESP32 is currently connected. */ const int WIFI_MANAGER_WIFI_CONNECTED_BIT = BIT0; - const int WIFI_MANAGER_AP_STA_CONNECTED_BIT = BIT1; /* @brief Set automatically once the SoftAP is started */ -const int WIFI_MANAGER_AP_STARTED = BIT2; +const int WIFI_MANAGER_AP_STARTED_BIT = BIT2; /* @brief When set, means a client requested to connect to an access point.*/ const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3; @@ -98,27 +107,48 @@ const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3; /* @brief This bit is set automatically as soon as a connection was lost */ const int WIFI_MANAGER_STA_DISCONNECT_BIT = BIT4; -/* @brief When set, means a client requested to scan wireless networks. */ -const int WIFI_MANAGER_REQUEST_WIFI_SCAN = BIT5; +/* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */ +const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT = BIT5; /* @brief When set, means a client requested to disconnect from currently connected AP. */ -const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT = BIT6; +const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT = BIT6; + +/* @brief When set, means a scan is in progress */ +const int WIFI_MANAGER_SCAN_BIT = BIT7; + +/* @brief When set, means user requested for a disconnect */ +const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8; + + void wifi_manager_scan_async(){ - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_SCAN); + wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL); } void wifi_manager_disconnect_async(){ - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT); + wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL); + //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete } +void wifi_manager_start(){ + + /* disable the default wifi logging */ + esp_log_level_set("wifi", ESP_LOG_NONE); + + /* initialize flash memory */ + nvs_flash_init(); + + /* start wifi manager task */ + xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager); +} + esp_err_t wifi_manager_save_sta_config(){ nvs_handle handle; esp_err_t esp_err; - ESP_LOGD(TAG, "About to save config to flash"); + ESP_LOGI(TAG, "About to save config to flash"); if(wifi_manager_config_sta){ @@ -192,6 +222,7 @@ bool wifi_manager_fetch_wifi_sta_config(){ return false; } memcpy(wifi_manager_config_sta->sta.password, buff, sz); + /* memcpy(wifi_manager_config_sta->sta.password, "lewrong", strlen("lewrong")); this is debug to force a wrong password event. ignore! */ /* settings */ sz = sizeof(wifi_settings); @@ -206,19 +237,19 @@ bool wifi_manager_fetch_wifi_sta_config(){ nvs_close(handle); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_sta_config: ssid:%s password:%s\n",wifi_manager_config_sta->sta.ssid,wifi_manager_config_sta->sta.password); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_ssid:%s\n",wifi_settings.ap_ssid); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_pwd:%s\n",wifi_settings.ap_pwd); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_channel:%i\n",wifi_settings.ap_channel); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_hidden (1 = yes):%i\n",wifi_settings.ap_ssid_hidden); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_bandwidth (1 = 20MHz, 2 = 40MHz)%i\n",wifi_settings.ap_bandwidth); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_only (0 = APSTA, 1 = STA when connected):%i\n",wifi_settings.sta_only); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_power_save (1 = yes):%i\n",wifi_settings.sta_power_save); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_static_ip (0 = dhcp client, 1 = static ip):%i\n",wifi_settings.sta_static_ip); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_static_ip_config: IP: %s , GW: %s , Mask: %s\n", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_ip_addr: %s\n", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip)); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_gw_addr: %s\n", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw)); - ESP_LOGD(TAG, "wifi_manager_fetch_wifi_settings: sta_netmask: %s\n", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_sta_config: ssid:%s password:%s",wifi_manager_config_sta->sta.ssid,wifi_manager_config_sta->sta.password); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_ssid:%s",wifi_settings.ap_ssid); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_pwd:%s",wifi_settings.ap_pwd); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_channel:%i",wifi_settings.ap_channel); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_hidden (1 = yes):%i",wifi_settings.ap_ssid_hidden); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: SoftAP_bandwidth (1 = 20MHz, 2 = 40MHz)%i",wifi_settings.ap_bandwidth); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_only (0 = APSTA, 1 = STA when connected):%i",wifi_settings.sta_only); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_power_save (1 = yes):%i",wifi_settings.sta_power_save); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_static_ip (0 = dhcp client, 1 = static ip):%i",wifi_settings.sta_static_ip); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_static_ip_config: IP: %s , GW: %s , Mask: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_ip_addr: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip)); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_gw_addr: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw)); + ESP_LOGI(TAG, "wifi_manager_fetch_wifi_settings: sta_netmask: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); return wifi_manager_config_sta->sta.ssid[0] != '\0'; @@ -317,6 +348,47 @@ void wifi_manager_generate_acess_points_json(){ } + +bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){ + if(wifi_manager_sta_ip_mutex){ + if( xSemaphoreTake( wifi_manager_sta_ip_mutex, xTicksToWait ) == pdTRUE ) { + return true; + } + else{ + return false; + } + } + else{ + return false; + } + +} +void wifi_manager_unlock_sta_ip_string(){ + xSemaphoreGive( wifi_manager_sta_ip_mutex ); +} + +void wifi_manager_safe_update_sta_ip_string(uint32_t ip){ + + if(wifi_manager_lock_sta_ip_string(portMAX_DELAY)){ + + struct ip4_addr ip4; + ip4.addr = ip; + + strcpy(wifi_manager_sta_ip, ip4addr_ntoa(&ip4)); + + ESP_LOGI(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip); + + wifi_manager_unlock_sta_ip_string(); + + + } +} + +char* wifi_manager_get_sta_ip_string(){ + return wifi_manager_sta_ip; +} + + bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait){ if(wifi_manager_json_mutex){ if( xSemaphoreTake( wifi_manager_json_mutex, xTicksToWait ) == pdTRUE ) { @@ -342,30 +414,73 @@ char* wifi_manager_get_ap_list_json(){ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) { + + + switch(event->event_id) { + case SYSTEM_EVENT_WIFI_READY: + ESP_LOGI(TAG, "SYSTEM_EVENT_WIFI_READY"); + break; + + case SYSTEM_EVENT_SCAN_DONE: + ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE"); + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT); + wifi_manager_send_message(EVENT_SCAN_DONE, NULL); + break; + + case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHANGE"); + break; + + case SYSTEM_EVENT_AP_START: - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED); + ESP_LOGI(TAG, "SYSTEM_EVENT_AP_START"); + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED_BIT); break; - case SYSTEM_EVENT_AP_STACONNECTED: + case SYSTEM_EVENT_AP_STOP: + break; + + case SYSTEM_EVENT_AP_PROBEREQRECVED: + break; + + case SYSTEM_EVENT_AP_STACONNECTED: /* a user disconnected from the SoftAP */ + ESP_LOGI(TAG, "SYSTEM_EVENT_AP_STACONNECTED"); xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT); break; case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED"); xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT); break; case SYSTEM_EVENT_STA_START: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START"); break; + case SYSTEM_EVENT_STA_STOP: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_STOP"); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP"); xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT); + wifi_manager_send_message(EVENT_STA_GOT_IP, (void*)event->event_info.got_ip.ip_info.ip.addr ); break; + case SYSTEM_EVENT_STA_CONNECTED: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_CONNECTED"); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT); - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT); + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED"); + + /* if a DISCONNECT message is posted while a scan is in progress this scan will NEVER end, causing scan to never work again. For this reason SCAN_BIT is cleared too */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_SCAN_BIT); + + /* post disconnect event with reason code */ + wifi_manager_send_message(EVENT_STA_DISCONNECTED, (void*)( (uint32_t)event->event_info.disconnected.reason) ); break; default: @@ -376,9 +491,6 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) - - - wifi_config_t* wifi_manager_get_wifi_sta_config(){ return wifi_manager_config_sta; } @@ -393,7 +505,7 @@ void wifi_manager_connect_async(){ wifi_manager_clear_ip_info_json(); wifi_manager_unlock_json_buffer(); } - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER); } @@ -404,6 +516,9 @@ char* wifi_manager_get_ip_info_json(){ void wifi_manager_destroy(){ + vTaskDelete(task_wifi_manager); + task_wifi_manager = NULL; + /* heap buffers */ free(accessp_records); accessp_records = NULL; @@ -411,6 +526,8 @@ void wifi_manager_destroy(){ accessp_json = NULL; free(ip_info_json); ip_info_json = NULL; + free(wifi_manager_sta_ip); + wifi_manager_sta_ip = NULL; if(wifi_manager_config_sta){ free(wifi_manager_config_sta); wifi_manager_config_sta = NULL; @@ -419,9 +536,14 @@ void wifi_manager_destroy(){ /* RTOS objects */ vSemaphoreDelete(wifi_manager_json_mutex); wifi_manager_json_mutex = NULL; + vSemaphoreDelete(wifi_manager_sta_ip_mutex); + wifi_manager_sta_ip_mutex = NULL; vEventGroupDelete(wifi_manager_event_group); + wifi_manager_event_group = NULL; + vQueueDelete(wifi_manager_queue); + wifi_manager_queue = NULL; + - vTaskDelete(NULL); } @@ -477,10 +599,31 @@ void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) { } +BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param){ + queue_message msg; + msg.code = code; + msg.param = param; + return xQueueSendToFront( wifi_manager_queue, &msg, portMAX_DELAY); +} +BaseType_t wifi_manager_send_message(message_code_t code, void *param){ + queue_message msg; + msg.code = code; + msg.param = param; + return xQueueSend( wifi_manager_queue, &msg, portMAX_DELAY); +} void wifi_manager( void * pvParameters ){ + + queue_message msg; + BaseType_t xStatus; + EventBits_t uxBits; + uint8_t retries = 0; + + /* initiate queue objects that are needed for the wifi manager */ + wifi_manager_queue = xQueueCreate( 3, sizeof( queue_message) ); + /* memory allocation of objects used by the task */ wifi_manager_json_mutex = xSemaphoreCreateMutex(); accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * MAX_AP_NUM); @@ -491,18 +634,21 @@ void wifi_manager( void * pvParameters ){ wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t)); memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); memset(&wifi_settings.sta_static_ip_config, 0x00, sizeof(tcpip_adapter_ip_info_t)); - IP4_ADDR(&wifi_settings.sta_static_ip_config.ip, 192, 168, 0, 10); - IP4_ADDR(&wifi_settings.sta_static_ip_config.gw, 192, 168, 0, 1); - IP4_ADDR(&wifi_settings.sta_static_ip_config.netmask, 255, 255, 255, 0); + + wifi_manager_sta_ip_mutex = xSemaphoreCreateMutex(); + wifi_manager_sta_ip = (char*)malloc(sizeof(char) * IP4ADDR_STRLEN_MAX); + wifi_manager_safe_update_sta_ip_string((uint32_t)0); + + /* initialize the tcp stack */ tcpip_adapter_init(); - /* event handler and event group for the wifi driver */ + /* event handler and event group for the wifi driver */ wifi_manager_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_event_loop_init(wifi_manager_event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_loop_init(wifi_manager_event_handler, NULL)); - /* wifi scanner config */ + /* wifi scanner config */ wifi_scan_config_t scan_config = { .ssid = 0, .bssid = 0, @@ -511,220 +657,333 @@ void wifi_manager( void * pvParameters ){ }; - /* try to get access to previously saved wifi */ - if(wifi_manager_fetch_wifi_sta_config()){ - ESP_LOGD(TAG, "Saved wifi found on startup"); - /* request a connection */ - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); - } + /* default wifi config */ + wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + - /* start the softAP access point */ - /* stop DHCP server */ - ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); - /* assign a static IP to the AP network interface */ + /* SoftAP - Wifi Access Point configuration setup */ tcpip_adapter_ip_info_t info; memset(&info, 0x00, sizeof(info)); - inet_pton(AF_INET, DEFAULT_AP_IP, &info.ip); /*avoid hardcoding IP such like old style: IP4_ADDR(&info.ip, 192, 168, 1, 1); */ + wifi_config_t ap_config = { + .ap = { + .ssid_len = 0, + .channel = wifi_settings.ap_channel, + .authmode = WIFI_AUTH_WPA2_PSK, + .ssid_hidden = wifi_settings.ap_ssid_hidden, + .max_connection = DEFAULT_AP_MAX_CONNECTIONS, + .beacon_interval = DEFAULT_AP_BEACON_INTERVAL, + }, + }; + memcpy(ap_config.ap.ssid, wifi_settings.ap_ssid , sizeof(wifi_settings.ap_ssid)); + memcpy(ap_config.ap.password, wifi_settings.ap_pwd, sizeof(wifi_settings.ap_pwd)); + + ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); /* stop AP DHCP server */ + inet_pton(AF_INET, DEFAULT_AP_IP, &info.ip); /* access point is on a static IP */ inet_pton(AF_INET, DEFAULT_AP_GATEWAY, &info.gw); inet_pton(AF_INET, DEFAULT_AP_NETMASK, &info.netmask); ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info)); + ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); /* start AP DHCP server */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); + ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, wifi_settings.ap_bandwidth)); + ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save)); - /* start dhcp server */ - ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); - + /* STA - Wifi Station configuration setup */ tcpip_adapter_dhcp_status_t status; if(wifi_settings.sta_static_ip) { - - ESP_LOGD(TAG, "Assigning static ip to STA interface. IP: %s , GW: %s , Mask: %s\n", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); + ESP_LOGI(TAG, "Assigning static ip to STA interface. IP: %s , GW: %s , Mask: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw), ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask)); /* stop DHCP client*/ ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)); - /* assign a static IP to the STA network interface */ ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &wifi_settings.sta_static_ip_config)); } else { /* start DHCP client if not started*/ - ESP_LOGD(TAG, "wifi_manager: Start DHCP client for STA interface. If not already running\n"); + ESP_LOGI(TAG, "wifi_manager: Start DHCP client for STA interface. If not already running"); ESP_ERROR_CHECK(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status)); if (status!=TCPIP_ADAPTER_DHCP_STARTED) ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA)); } - /* init wifi as station + access point */ - wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA)); - ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, wifi_settings.ap_bandwidth)); - ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save)); - - /* configure the softAP and start it */ - wifi_config_t ap_config = { - .ap = { - .ssid_len = 0, - .channel = wifi_settings.ap_channel, - .authmode = WIFI_AUTH_WPA2_PSK, - .ssid_hidden = wifi_settings.ap_ssid_hidden, - .max_connection = DEFAULT_AP_MAX_CONNECTIONS, - .beacon_interval = DEFAULT_AP_BEACON_INTERVAL, - }, - }; - memcpy(ap_config.ap.ssid, wifi_settings.ap_ssid , sizeof(wifi_settings.ap_ssid)); - memcpy(ap_config.ap.password, wifi_settings.ap_pwd, sizeof(wifi_settings.ap_pwd)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); + /* by default the mode is STA because wifi_manager will not start the access point unless it has to! */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGD(TAG, "starting softAP with ssid %s", ap_config.ap.ssid); - ESP_LOGD(TAG, "starting softAP on channel %i", wifi_settings.ap_channel); - - - /* wait for access point to start */ - xEventGroupWaitBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED, pdFALSE, pdTRUE, portMAX_DELAY ); - - ESP_LOGD(TAG, "softAP started, starting http_server"); /* start http server */ - http_server_set_event_start(); + http_server_start(); - /* start DNS server */ - dns_server_start(); + /* enqueue first event: load previous config */ + wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL); - EventBits_t uxBits; + /* main processing loop */ for(;;){ + xStatus = xQueueReceive( wifi_manager_queue, &msg, portMAX_DELAY ); + + if( xStatus == pdPASS ){ + switch(msg.code){ + + case EVENT_SCAN_DONE: + /* As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns. + * As a consequence, ap_num MUST be reset to MAX_AP_NUM at every scan */ + ap_num = MAX_AP_NUM; + ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, accessp_records)); + /* make sure the http server isn't trying to access the list while it gets refreshed */ + if(wifi_manager_lock_json_buffer( pdMS_TO_TICKS(1000) )){ + /* Will remove the duplicate SSIDs from the list and update ap_num */ + wifi_manager_filter_unique(accessp_records, &ap_num); + wifi_manager_generate_acess_points_json(); + wifi_manager_unlock_json_buffer(); + } + else{ + ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); + } + break; - /* actions that can trigger: request a connection, a scan, or a disconnection */ - uxBits = xEventGroupWaitBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT | WIFI_MANAGER_REQUEST_WIFI_SCAN | WIFI_MANAGER_REQUEST_WIFI_DISCONNECT, pdFALSE, pdFALSE, portMAX_DELAY ); - if(uxBits & WIFI_MANAGER_REQUEST_WIFI_DISCONNECT){ - /* user requested a disconnect, this will in effect disconnect the wifi but also erase NVS memory*/ + case ORDER_START_WIFI_SCAN: + ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN"); - /*disconnect only if it was connected to begin with! */ - if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT); - ESP_ERROR_CHECK(esp_wifi_disconnect()); + /* if a scan is already in progress this message is simply ignored thanks to the WIFI_MANAGER_SCAN_BIT uxBit */ + uxBits = xEventGroupGetBits(wifi_manager_event_group); + if(! (uxBits & WIFI_MANAGER_SCAN_BIT) ){ + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT); + ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, false)); + } - /* wait until wifi disconnects. From experiments, it seems to take about 150ms to disconnect */ - xEventGroupWaitBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT, pdFALSE, pdTRUE, portMAX_DELAY ); - } - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT); + break; - /* erase configuration */ - if(wifi_manager_config_sta){ - memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); - } + case ORDER_LOAD_AND_RESTORE_STA: + ESP_LOGI(TAG, "MESSAGE: ORDER_LOAD_AND_RESTORE_STA"); + if(wifi_manager_fetch_wifi_sta_config()){ + ESP_LOGI(TAG, "Saved wifi found on startup. Will attempt to connect."); + wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_RESTORE_CONNECTION); + } + else{ + /* no wifi saved: start soft AP! This is what should happen during a first run */ + ESP_LOGI(TAG, "No saved wifi found on startup. Starting access point."); + wifi_manager_send_message(ORDER_START_AP, NULL); + } + break; - /* save NVS memory */ - wifi_manager_save_sta_config(); + case ORDER_CONNECT_STA: + ESP_LOGI(TAG, "MESSAGE: ORDER_CONNECT_STA"); - /* update JSON status */ - if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ - wifi_manager_generate_ip_info_json(UPDATE_USER_DISCONNECT); - wifi_manager_unlock_json_buffer(); - } - else{ - /* Even if someone were to furiously refresh a web resource that needs the json mutex, - * it seems impossible that this thread cannot obtain the mutex. Abort here is reasonnable. - */ - abort(); - } + /* very important: precise that this connection attempt is specifically requested. + * Param in that case is a boolean indicating if the request was made automatically + * by the wifi_manager. + * */ + if((BaseType_t)msg.param == CONNECTION_REQUEST_USER) { + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + } + else if((BaseType_t)msg.param == CONNECTION_REQUEST_RESTORE_CONNECTION) { + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT); + } - /* finally: release the scan request bit */ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT); - } - if(uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_BIT){ - //someone requested a connection! + uxBits = xEventGroupGetBits(wifi_manager_event_group); + if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){ + wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL); + /* todo: reconnect */ + } + else{ + /* update config to latest and attempt connection */ + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config())); + ESP_ERROR_CHECK(esp_wifi_connect()); + } - /* first thing: if the esp32 is already connected to a access point: disconnect */ - if( (uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT) == (WIFI_MANAGER_WIFI_CONNECTED_BIT) ){ + break; + + case EVENT_STA_DISCONNECTED: + ESP_LOGI(TAG, "MESSAGE: EVENT_STA_DISCONNECTED with Reason code: %d", (uint32_t)msg.param); + + /* this even can be posted in numerous different conditions + * + * 1. SSID password is wrong + * 2. Manual disconnection ordered + * 3. Connection lost + * + * Having clear understand as to WHY the event was posted is key to having an efficient wifi manager + * + * With wifi_manager, we determine: + * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, We consider it's a client that requested the connection. + * When SYSTEM_EVENT_STA_DISCONNECTED is posted, it's probably a password/something went wrong with the handshake. + * + * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, it's a disconnection that was ASKED by the client (clicking disconnect in the app) + * When SYSTEM_EVENT_STA_DISCONNECTED is posted, saved wifi is erased from the NVS memory. + * + * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT and WIFI_MANAGER_REQUEST_STA_CONNECT_BIT are NOT set, it's a lost connection + * + * In this version of the software, reason codes are not used. They are indicated here for potential future usage. + * + * REASON CODE: + * 1 UNSPECIFIED + * 2 AUTH_EXPIRE auth no longer valid, this smells like someone changed a password on the AP + * 3 AUTH_LEAVE + * 4 ASSOC_EXPIRE + * 5 ASSOC_TOOMANY too many devices already connected to the AP => AP fails to respond + * 6 NOT_AUTHED + * 7 NOT_ASSOCED + * 8 ASSOC_LEAVE + * 9 ASSOC_NOT_AUTHED + * 10 DISASSOC_PWRCAP_BAD + * 11 DISASSOC_SUPCHAN_BAD + * 12