From d65d945550d0d112479255eb5e7301e9bd11eb2d Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 11:41:13 +0800 Subject: [PATCH 01/12] wip 2.0 --- wifi_manager/main/Kconfig.projbuild | 10 +- wifi_manager/main/dns_server.c | 2 +- wifi_manager/main/http_server.c | 16 +- wifi_manager/main/http_server.h | 3 +- wifi_manager/main/main.c | 18 +- wifi_manager/main/wifi_manager.c | 447 ++++++++++++++++++++++++++-- wifi_manager/main/wifi_manager.h | 104 +++++-- 7 files changed, 530 insertions(+), 70 deletions(-) diff --git a/wifi_manager/main/Kconfig.projbuild b/wifi_manager/main/Kconfig.projbuild index 3d928274..8efd485f 100644 --- a/wifi_manager/main/Kconfig.projbuild +++ b/wifi_manager/main/Kconfig.projbuild @@ -1,5 +1,11 @@ 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 DEFAULT_AP_SSID string "Access Point SSID" default "esp32" @@ -20,13 +26,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..368588ce 100644 --- a/wifi_manager/main/dns_server.c +++ b/wifi_manager/main/dns_server.c @@ -58,7 +58,7 @@ static const char TAG[] = "dns_server"; static TaskHandle_t task_dns_server = NULL; 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); } diff --git a/wifi_manager/main/http_server.c b/wifi_manager/main/http_server.c index 80ae0f81..99abb564 100644 --- a/wifi_manager/main/http_server.c +++ b/wifi_manager/main/http_server.c @@ -64,6 +64,8 @@ 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,20 +92,24 @@ const static char http_redirect_hdr_end[] = "/\n\n"; +//TODO: delete 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(){ + 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"); + //TODO: delete ESP_LOGD(TAG, "waiting for start bit"); + //TODO: delete uxBits = xEventGroupWaitBits(http_server_event_group, HTTP_SERVER_START_BIT_0, pdFALSE, pdTRUE, portMAX_DELAY ); + //TODO: delete ESP_LOGD(TAG, "received start bit, starting server"); struct netconn *conn, *newconn; err_t err; @@ -117,10 +123,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 */ + vTaskDelay( pdMS_TO_TICKS(50) ); /* allows the freeRTOS scheduler to take over if needed. 50ms = 5ticks at 100Hz tickrate */ } while(err == ERR_OK); netconn_close(conn); netconn_delete(conn); + + vTaskDelete( NULL ); } diff --git a/wifi_manager/main/http_server.h b/wifi_manager/main/http_server.h index 2ac7c321..4097afa0 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/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..69614e9d 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -55,6 +55,10 @@ 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; uint16_t ap_num = MAX_AP_NUM; wifi_ap_record_t *accessp_records; @@ -64,6 +68,7 @@ wifi_config_t* wifi_manager_config_sta = NULL; /* @brief tag used for ESP serial console messages */ static const char TAG[] = "wifi_manager"; +static TaskHandle_t task_wifi_manager = NULL; /** * The actual WiFi settings in use @@ -99,14 +104,18 @@ const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3; 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; +const int WIFI_MANAGER_REQUEST_WIFI_SCAN = BIT5; //TODO: DELETE /* @brief When set, means a client requested to disconnect from currently connected AP. */ const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT = BIT6; +/* @brief When set, means a scan is in progress */ +const int WIFI_MANAGER_SCAN_BIT = BIT7; + void wifi_manager_scan_async(){ - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_SCAN); + //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_SCAN); + wifi_manager_send_message_to_front(ORDER_START_WIFI_SCAN, NULL); } void wifi_manager_disconnect_async(){ @@ -114,11 +123,23 @@ void wifi_manager_disconnect_async(){ } +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 +213,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")); /* settings */ sz = sizeof(wifi_settings); @@ -206,19 +228,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'; @@ -342,6 +364,80 @@ 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_LOGI(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: + ESP_LOGI(TAG, "SYSTEM_EVENT_AP_START"); + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED); + break; + + case SYSTEM_EVENT_AP_STOP: + break; + + case SYSTEM_EVENT_AP_PROBEREQRECVED: + break; + + case SYSTEM_EVENT_AP_STACONNECTED: + 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, NULL ); + break; + + case SYSTEM_EVENT_STA_CONNECTED: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_CONNECTED"); + break; + + case SYSTEM_EVENT_STA_DISCONNECTED: + ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED - REASON CODE %d", event->event_info.disconnected.reason); + /* post disconnect event with reason code */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT); + wifi_manager_send_message(EVENT_STA_DISCONNECTED, (void*)( (uint32_t)event->event_info.disconnected.reason) ); + break; + + default: + break; + } + return ESP_OK; +} + +esp_err_t wifi_manager_event_handlerBACKUP(void *ctx, system_event_t *event) +{ switch(event->event_id) { case SYSTEM_EVENT_AP_START: @@ -477,10 +573,305 @@ 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); + accessp_json = (char*)malloc(MAX_AP_NUM * JSON_ONE_APP_SIZE + 4); /* 4 bytes for json encapsulation of "[\n" and "]\0" */ + wifi_manager_clear_access_points_json(); + ip_info_json = (char*)malloc(sizeof(char) * JSON_IP_INFO_SIZE); + wifi_manager_clear_ip_info_json(); + 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)); + + + /* initialize the tcp stack */ + tcpip_adapter_init(); + + /* event handler and event group for the wifi driver */ + wifi_manager_event_group = xEventGroupCreate(); //TODO: DELETE + ESP_ERROR_CHECK(esp_event_loop_init(wifi_manager_event_handler, NULL)); + + /* wifi scanner config */ + wifi_scan_config_t scan_config = { + .ssid = 0, + .bssid = 0, + .channel = 0, + .show_hidden = true + }; + + + /* 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)); + + + + /* Access Point configuration setup + * + * CODE BELOW RELATES TO ACCESS POINT CONFIGURATION + * + * */ + tcpip_adapter_ip_info_t info; + memset(&info, 0x00, sizeof(info)); + 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)); + + + /** STA setup */ + tcpip_adapter_dhcp_status_t status; + if(wifi_settings.sta_static_ip) { + ESP_LOGI(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)); + + /* 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_LOGI(TAG, "wifi_manager: Start DHCP client for STA interface. If not already running\n"); + 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)); + } + + + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); + + + + /* enqueue first event: load previous config */ + wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL); + + /* 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_LOGI(TAG, "wifi_manager: could not get access to json mutex in wifi_scan"); + } + break; + + case ORDER_START_WIFI_SCAN: + ESP_LOGI(TAG, "MESSAGE: ORDER_START_WIFI_SCAN"); + + /* 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)); + } + + break; + + 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; + + case ORDER_CONNECT_STA: + ESP_LOGI(TAG, "MESSAGE: ORDER_CONNECT_STA"); + + /* 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); + + uxBits = xEventGroupGetBits(wifi_manager_event_group); + if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){ + wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL); + } + 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()); + } + + 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 NOT set, it's a lost connection + * + * In this version of the software, reason codes are not used. + * + * 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 + * 13 IE_INVALID + * 14 MIC_FAILURE + * 15 4WAY_HANDSHAKE_TIMEOUT wrong password! This was personnaly tested on my home wifi with a wrong password. + * 16 GROUP_KEY_UPDATE_TIMEOUT + * 17 IE_IN_4WAY_DIFFERS + * 18 GROUP_CIPHER_INVALID + * 19 PAIRWISE_CIPHER_INVALID + * 20 AKMP_INVALID + * 21 UNSUPP_RSN_IE_VERSION + * 22 INVALID_RSN_IE_CAP + * 23 802_1X_AUTH_FAILED wrong password? + * 24 CIPHER_SUITE_REJECTED + * 200 BEACON_TIMEOUT + * 201 NO_AP_FOUND + * 202 AUTH_FAIL + * 203 ASSOC_FAIL + * 204 HANDSHAKE_TIMEOUT + * + * */ + uxBits = xEventGroupGetBits(wifi_manager_event_group); + if( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_BIT ){ + /* there are no retries when it's a user requested connection by design. This avoids a user hanging too much + * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + } + else{ + /* lost connection ? */ + if(retries < WIFI_MANAGER_MAX_RETRY){ + retries++; + wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT); + } + else{ + /* connection was lost beyond repair: kick start the AP! */ + retries = 0; + wifi_manager_send_message(ORDER_START_AP, NULL); + } + } + break; + + case ORDER_START_AP: + ESP_LOGI(TAG, "MESSAGE: ORDER_START_AP"); + esp_wifi_set_mode(WIFI_MODE_APSTA); + + http_server_start(); + dns_server_start(); + + break; + + case EVENT_STA_GOT_IP: + + break; + + case ORDER_DISCONNECT_STA: + ESP_LOGI(TAG, "MESSAGE: ORDER_DISCONNECT_STA"); + + /* order wifi discconect */ + ESP_ERROR_CHECK(esp_wifi_disconnect()); + + /* 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 ); + break; + default: + break; + + } + } + + } + + vTaskDelete( NULL ); + +} + +void wifi_managerBACKUP( void * pvParameters ){ + /* 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,9 +882,9 @@ 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); + //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); /* initialize the tcp stack */ tcpip_adapter_init(); @@ -513,7 +904,7 @@ 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"); + ESP_LOGI(TAG, "Saved wifi found on startup"); /* request a connection */ xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); } @@ -529,16 +920,16 @@ void wifi_manager( void * pvParameters ){ 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)); + /* start dhcp server */ + ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); - /* start dhcp server */ - ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); 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\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)); /* stop DHCP client*/ ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)); @@ -548,7 +939,7 @@ void wifi_manager( void * pvParameters ){ } 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\n"); 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)); @@ -580,14 +971,14 @@ void wifi_manager( void * pvParameters ){ ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); 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); + ESP_LOGI(TAG, "starting softAP with ssid %s", ap_config.ap.ssid); + ESP_LOGI(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"); + ESP_LOGI(TAG, "softAP started, starting http_server"); /* start http server */ http_server_set_event_start(); @@ -719,7 +1110,7 @@ void wifi_manager( void * pvParameters ){ wifi_manager_unlock_json_buffer(); } else{ - ESP_LOGD(TAG, "wifi_manager: could not get access to json mutex in wifi_scan\n"); + ESP_LOGI(TAG, "wifi_manager: could not get access to json mutex in wifi_scan\n"); } /* finally: release the scan request bit */ diff --git a/wifi_manager/main/wifi_manager.h b/wifi_manager/main/wifi_manager.h index d807954a..69c51cd1 100644 --- a/wifi_manager/main/wifi_manager.h +++ b/wifi_manager/main/wifi_manager.h @@ -43,13 +43,13 @@ extern "C" { * @brief Defines the maximum size of a SSID name. 32 is IEEE standard. * @warning limit is also hard coded in wifi_config_t. Never extend this value. */ -#define MAX_SSID_SIZE 32 +#define MAX_SSID_SIZE 32 /** * @brief Defines the maximum size of a WPA2 passkey. 64 is IEEE standard. * @warning limit is also hard coded in wifi_config_t. Never extend this value. */ -#define MAX_PASSWORD_SIZE 64 +#define MAX_PASSWORD_SIZE 64 /** @@ -58,37 +58,53 @@ extern "C" { * To save memory and avoid nasty out of memory errors, * we can limit the number of APs detected in a wifi scan. */ -#define MAX_AP_NUM 15 +#define MAX_AP_NUM 15 + +/** + * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up. + * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries) + */ +#define WIFI_MANAGER_MAX_RETRY 2 + +/** @brief Defines the task priority of the wifi_manager. + * + * Tasks spawn by the manager will have a priority of WIFI_MANAGER_TASK_PRIORITY-1. + * For this particular reason, minimum task priority is 1. It it highly not recommended to set + * it to 1 though as the sub-tasks will now have a priority of 0 which is the priority + * of freeRTOS' idle task. + */ +#define WIFI_MANAGER_TASK_PRIORITY CONFIG_WIFI_MANAGER_TASK_PRIORITY + /** @brief Defines the auth mode as an access point * Value must be of type wifi_auth_mode_t * @see esp_wifi_types.h * @warning if set to WIFI_AUTH_OPEN, passowrd me be empty. See DEFAULT_AP_PASSWORD. */ -#define AP_AUTHMODE WIFI_AUTH_WPA2_PSK +#define AP_AUTHMODE WIFI_AUTH_WPA2_PSK /** @brief Defines visibility of the access point. 0: visible AP. 1: hidden */ -#define DEFAULT_AP_SSID_HIDDEN 0 +#define DEFAULT_AP_SSID_HIDDEN 0 /** @brief Defines access point's name. Default value: esp32. Run 'make menuconfig' to setup your own value or replace here by a string */ -#define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID +#define DEFAULT_AP_SSID CONFIG_DEFAULT_AP_SSID /** @brief Defines access point's password. * @warning In the case of an open access point, the password must be a null string "" or "\0" if you want to be verbose but waste one byte. * In addition, the AP_AUTHMODE must be WIFI_AUTH_OPEN */ -#define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD +#define DEFAULT_AP_PASSWORD CONFIG_DEFAULT_AP_PASSWORD /** @brief Defines the hostname broadcasted by mDNS */ -#define DEFAULT_HOSTNAME "esp32" +#define DEFAULT_HOSTNAME "esp32" /** @brief Defines access point's bandwidth. * Value: WIFI_BW_HT20 for 20 MHz or WIFI_BW_HT40 for 40 MHz * 20 MHz minimize channel interference but is not suitable for * applications with high data speeds */ -#define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20 +#define DEFAULT_AP_BANDWIDTH WIFI_BW_HT20 /** @brief Defines access point's channel. * Channel selection is only effective when not connected to another AP. @@ -96,38 +112,38 @@ extern "C" { * For 20 MHz: 1, 6 or 11 in USA and 1, 5, 9 or 13 in most parts of the world * For 40 MHz: 3 in USA and 3 or 11 in most parts of the world */ -#define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL +#define DEFAULT_AP_CHANNEL CONFIG_DEFAULT_AP_CHANNEL -/** @brief Defines the access point's default IP address. Default: "192.168.1.1" */ -#define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP +/** @brief Defines the access point's default IP address. Default: "10.10.0.1 */ +#define DEFAULT_AP_IP CONFIG_DEFAULT_AP_IP -/** @brief Defines the access point's gateway. This should be the same as your IP. Default: "192.168.1.1" */ -#define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY +/** @brief Defines the access point's gateway. This should be the same as your IP. Default: "10.10.0.1" */ +#define DEFAULT_AP_GATEWAY CONFIG_DEFAULT_AP_GATEWAY /** @brief Defines the access point's netmask. Default: "255.255.255.0" */ -#define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK +#define DEFAULT_AP_NETMASK CONFIG_DEFAULT_AP_NETMASK /** @brief Defines access point's maximum number of clients. Default: 4 */ -#define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS +#define DEFAULT_AP_MAX_CONNECTIONS CONFIG_DEFAULT_AP_MAX_CONNECTIONS /** @brief Defines access point's beacon interval. 100ms is the recommended default. */ -#define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL +#define DEFAULT_AP_BEACON_INTERVAL CONFIG_DEFAULT_AP_BEACON_INTERVAL /** @brief Defines if esp32 shall run both AP + STA when connected to another AP. * Value: 0 will have the own AP always on (APSTA mode) * Value: 1 will turn off own AP when connected to another AP (STA only mode when connected) * Turning off own AP when connected to another AP minimize channel interference and increase throughput */ -#define DEFAULT_STA_ONLY 1 +#define DEFAULT_STA_ONLY 1 /** @brief Defines if wifi power save shall be enabled. * Value: WIFI_PS_NONE for full power (wifi modem always on) * Value: WIFI_PS_MODEM for power save (wifi modem sleep periodically) * Note: Power save is only effective when in STA only mode */ -#define DEFAULT_STA_POWER_SAVE WIFI_PS_NONE +#define DEFAULT_STA_POWER_SAVE WIFI_PS_NONE /** * @brief Defines the maximum length in bytes of a JSON representation of an access point. @@ -138,16 +154,35 @@ extern "C" { * this is an edge case but I don't think we should crash in a catastrophic manner just because * someone decided to have a funny wifi name. */ -#define JSON_ONE_APP_SIZE 99 +#define JSON_ONE_APP_SIZE 99 /** * @brief Defines the maximum length in bytes of a JSON representation of the IP information * assuming all ips are 4*3 digits, and all characters in the ssid require to be escaped. * example: {"ssid":"abcdefghijklmnopqrstuvwxyz012345","ip":"192.168.1.119","netmask":"255.255.255.0","gw":"192.168.1.1","urc":0} */ -#define JSON_IP_INFO_SIZE 150 +#define JSON_IP_INFO_SIZE 150 + + +typedef enum message_code_t { + NONE = 0, + ORDER_START_HTTP_SERVER = 1, + ORDER_STOP_HTTP_SERVER = 2, + ORDER_START_DNS_SERVICE = 3, + ORDER_STOP_DNS_SERVICE = 4, + ORDER_START_WIFI_SCAN = 5, + ORDER_LOAD_AND_RESTORE_STA = 6, + ORDER_CONNECT_STA = 7, + ORDER_DISCONNECT_STA = 8, + ORDER_START_AP = 9, + ORDER_START_HTTP = 10, + ORDER_START_DNS_HIJACK = 11, + EVENT_STA_DISCONNECTED = 100, + EVENT_SCAN_DONE = 101, + EVENT_STA_GOT_IP = 102 +}message_code_t; typedef enum update_reason_code_t { UPDATE_CONNECTION_OK = 0, @@ -156,6 +191,14 @@ typedef enum update_reason_code_t { UPDATE_LOST_CONNECTION = 3 }update_reason_code_t; +typedef enum connection_request_made_by_code_t{ + CONNECTION_REQUEST_NONE = 0, + CONNECTION_REQUEST_USER = 1, + CONNECTION_REQUEST_AUTO_RECONNECT = 2, + CONNECTION_REQUEST_RESTORE_CONNECTION = 3, + CONNECTION_REQUEST_MAX = 0x7fffffff /*force the creation of this enum as a 32 bit int */ +}connection_request_made_by_code_t; + /** * The actual WiFi settings in use */ @@ -173,6 +216,21 @@ struct wifi_settings_t{ extern struct wifi_settings_t wifi_settings; +/** + * @brief Structure used to store one message in the queue. + */ +typedef struct{ + message_code_t code; + void *param; +} queue_message; + + + +/** + * + */ +void wifi_manager_start(); + /** * Frees up all memory allocated by the wifi_manager and kill the task. */ @@ -288,6 +346,10 @@ void wifi_manager_clear_access_points_json(); */ void wifi_manager_initialise_mdns(); + +BaseType_t wifi_manager_send_message(message_code_t code, void *param); +BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param); + #ifdef __cplusplus } #endif From 40ee347cd71750909d7ecc076fec3ce161dcb607 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 17:52:00 +0800 Subject: [PATCH 02/12] added dns_server_stop --- wifi_manager/main/dns_server.c | 17 ++++++- wifi_manager/main/dns_server.h | 1 + wifi_manager/main/wifi_manager.c | 83 +++++++++++++++----------------- 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/wifi_manager/main/dns_server.c b/wifi_manager/main/dns_server.c index 368588ce..cce537ab 100644 --- a/wifi_manager/main/dns_server.c +++ b/wifi_manager/main/dns_server.c @@ -56,17 +56,27 @@ 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, 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; + } + +} + 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/wifi_manager.c b/wifi_manager/main/wifi_manager.c index 69614e9d..9bfa33ed 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -91,7 +91,6 @@ 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 */ @@ -112,10 +111,14 @@ const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT = 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_to_front(ORDER_START_WIFI_SCAN, NULL); + wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL); } void wifi_manager_disconnect_async(){ @@ -395,7 +398,7 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) case SYSTEM_EVENT_AP_PROBEREQRECVED: break; - case SYSTEM_EVENT_AP_STACONNECTED: + 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; @@ -425,43 +428,12 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) case SYSTEM_EVENT_STA_DISCONNECTED: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED - REASON CODE %d", event->event_info.disconnected.reason); - /* post disconnect event with reason code */ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT); - wifi_manager_send_message(EVENT_STA_DISCONNECTED, (void*)( (uint32_t)event->event_info.disconnected.reason) ); - break; - - default: - break; - } - return ESP_OK; -} - -esp_err_t wifi_manager_event_handlerBACKUP(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - - case SYSTEM_EVENT_AP_START: - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED); - break; - - case SYSTEM_EVENT_AP_STACONNECTED: - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT); - break; - - case SYSTEM_EVENT_AP_STADISCONNECTED: - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT); - break; - case SYSTEM_EVENT_STA_START: - break; + /* 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); - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT); - 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); + /* post disconnect event with reason code */ + wifi_manager_send_message(EVENT_STA_DISCONNECTED, (void*)( (uint32_t)event->event_info.disconnected.reason) ); break; default: @@ -472,9 +444,6 @@ esp_err_t wifi_manager_event_handlerBACKUP(void *ctx, system_event_t *event) - - - wifi_config_t* wifi_manager_get_wifi_sta_config(){ return wifi_manager_config_sta; } @@ -489,7 +458,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); } @@ -822,6 +791,11 @@ void wifi_manager( void * pvParameters ){ * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */ xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); } + else if (uxBits & WIFI_MANAGER_REQUEST_DISCONNECT_BIT){ + /* user manually requested a disconnect so the lost connection is a normal event. Clear the flag and restart the AP */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT); + wifi_manager_send_message(ORDER_START_AP, NULL); + } else{ /* lost connection ? */ if(retries < WIFI_MANAGER_MAX_RETRY){ @@ -846,12 +820,35 @@ void wifi_manager( void * pvParameters ){ break; case EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "MESSAGE: EVENT_STA_GOT_IP"); + + /* reset connection requests bits -- doesn't matter if it was set or not */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + + /* refresh JSON with the new IP */ + if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ + /* generate the connection info with success */ + wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK ); + + /* save wifi config in NVS */ + wifi_manager_save_sta_config(); + + wifi_manager_unlock_json_buffer(); + } + else { abort(); } + + /* bring down DNS hijack */ + ESP_LOGI(TAG, "Call to dns_server_stop();"); + dns_server_stop(); break; case ORDER_DISCONNECT_STA: ESP_LOGI(TAG, "MESSAGE: ORDER_DISCONNECT_STA"); + /* precise this is coming from a user request */ + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT); + /* order wifi discconect */ ESP_ERROR_CHECK(esp_wifi_disconnect()); From de7682cc4df2636d2970d55bb0153c78807e6dc7 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 17:53:18 +0800 Subject: [PATCH 03/12] updated copyright --- wifi_manager/main/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@

About this app...

-

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:

From debf2de84e0d23b86d12f77d6848fd745e904aa8 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 20:49:34 +0800 Subject: [PATCH 04/12] fixed connection to HTTP from within local STA network --- wifi_manager/main/http_server.c | 168 ++++++++++++++++---------------- wifi_manager/main/http_server.h | 2 +- 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/wifi_manager/main/http_server.c b/wifi_manager/main/http_server.c index 99abb564..0cd9444e 100644 --- a/wifi_manager/main/http_server.c +++ b/wifi_manager/main/http_server.c @@ -60,8 +60,8 @@ 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; @@ -93,10 +93,10 @@ const static char http_redirect_hdr_end[] = "/\n\n"; //TODO: delete -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_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(){ xTaskCreate(&http_server, "http_server", 2048, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); @@ -104,12 +104,8 @@ void http_server_start(){ void http_server(void *pvParameters) { - if(!http_server_event_group) http_server_event_group = xEventGroupCreate(); + //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! */ - //TODO: delete ESP_LOGD(TAG, "waiting for start bit"); - //TODO: delete uxBits = xEventGroupWaitBits(http_server_event_group, HTTP_SERVER_START_BIT_0, pdFALSE, pdTRUE, portMAX_DELAY ); - //TODO: delete ESP_LOGD(TAG, "received start bit, starting server"); struct netconn *conn, *newconn; err_t err; @@ -123,7 +119,7 @@ void http_server(void *pvParameters) { http_server_netconn_serve(newconn); netconn_delete(newconn); } - vTaskDelay( pdMS_TO_TICKS(50) ); /* allows the freeRTOS scheduler to take over if needed. 50ms = 5ticks at 100Hz tickrate */ + taskYIELD(); /* allows the freeRTOS scheduler to take over if needed. */ } while(err == ERR_OK); netconn_close(conn); netconn_delete(conn); @@ -170,98 +166,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 */ + 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); + } + + } + 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 4097afa0..eba6a5f0 100644 --- a/wifi_manager/main/http_server.h +++ b/wifi_manager/main/http_server.h @@ -43,7 +43,7 @@ extern "C" { void http_server(void *pvParameters); void http_server_netconn_serve(struct netconn *conn); -void http_server_set_event_start(); //TODO: delete +//void http_server_set_event_start(); //TODO: delete void http_server_start(); /** From 413c159364ac3925ddc1e8916902745fb9508a8c Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 20:50:02 +0800 Subject: [PATCH 05/12] added STA IP stored as a string --- wifi_manager/main/wifi_manager.c | 85 +++++++++++++++++++++++++++----- wifi_manager/main/wifi_manager.h | 12 +++++ 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/wifi_manager/main/wifi_manager.c b/wifi_manager/main/wifi_manager.c index 9bfa33ed..2b202069 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" @@ -60,6 +61,9 @@ 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; @@ -342,6 +346,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 ) { @@ -419,7 +464,7 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) 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, NULL ); + wifi_manager_send_message(EVENT_STA_GOT_IP, (void*)event->event_info.got_ip.ip_info.ip.addr ); break; case SYSTEM_EVENT_STA_CONNECTED: @@ -469,6 +514,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; @@ -476,6 +524,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; @@ -484,9 +534,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); } @@ -578,6 +633,11 @@ void wifi_manager( void * pvParameters ){ memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); memset(&wifi_settings.sta_static_ip_config, 0x00, sizeof(tcpip_adapter_ip_info_t)); + 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(); @@ -602,11 +662,7 @@ void wifi_manager( void * pvParameters ){ - /* Access Point configuration setup - * - * CODE BELOW RELATES TO ACCESS POINT CONFIGURATION - * - * */ + /* SoftAP - Wifi Access Point configuration setup */ tcpip_adapter_ip_info_t info; memset(&info, 0x00, sizeof(info)); wifi_config_t ap_config = { @@ -635,10 +691,10 @@ void wifi_manager( void * pvParameters ){ ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save)); - /** STA setup */ + /* STA - Wifi Station configuration setup */ tcpip_adapter_dhcp_status_t status; if(wifi_settings.sta_static_ip) { - ESP_LOGI(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)); @@ -647,7 +703,7 @@ void wifi_manager( void * pvParameters ){ } else { /* start DHCP client if not started*/ - ESP_LOGI(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)); @@ -785,6 +841,10 @@ void wifi_manager( void * pvParameters ){ * 204 HANDSHAKE_TIMEOUT * * */ + + /* reset saved sta IP */ + wifi_manager_safe_update_sta_ip_string((uint32_t)0); + uxBits = xEventGroupGetBits(wifi_manager_event_group); if( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_BIT ){ /* there are no retries when it's a user requested connection by design. This avoids a user hanging too much @@ -825,6 +885,9 @@ void wifi_manager( void * pvParameters ){ /* reset connection requests bits -- doesn't matter if it was set or not */ xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + /* save IP as a string for the HTTP server host */ + wifi_manager_safe_update_sta_ip_string((uint32_t)msg.param); + /* refresh JSON with the new IP */ if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ /* generate the connection info with success */ @@ -978,7 +1041,7 @@ void wifi_managerBACKUP( void * pvParameters ){ ESP_LOGI(TAG, "softAP started, starting http_server"); /* start http server */ - http_server_set_event_start(); + //http_server_set_event_start(); /* start DNS server */ dns_server_start(); diff --git a/wifi_manager/main/wifi_manager.h b/wifi_manager/main/wifi_manager.h index 69c51cd1..c8b6ad26 100644 --- a/wifi_manager/main/wifi_manager.h +++ b/wifi_manager/main/wifi_manager.h @@ -347,6 +347,18 @@ void wifi_manager_clear_access_points_json(); void wifi_manager_initialise_mdns(); + + +bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait); +void wifi_manager_unlock_sta_ip_string(); +char* wifi_manager_get_sta_ip_string(); + +/** + * @brief thread safe char representation of the STA IP update + */ +void wifi_manager_safe_update_sta_ip_string(uint32_t ip); + + BaseType_t wifi_manager_send_message(message_code_t code, void *param); BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param); From 13f536b0eee4cc625d5811eedb99013e9fa6756b Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Fri, 10 May 2019 21:11:46 +0800 Subject: [PATCH 06/12] recoded disconnect in new event model --- wifi_manager/main/wifi_manager.c | 34 ++++++++++++++++++++++++-------- wifi_manager/main/wifi_manager.h | 3 +++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/wifi_manager/main/wifi_manager.c b/wifi_manager/main/wifi_manager.c index 2b202069..084b4e82 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -126,7 +126,8 @@ void wifi_manager_scan_async(){ } 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); TODO: delete } @@ -422,7 +423,7 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) break; case SYSTEM_EVENT_SCAN_DONE: - ESP_LOGI(TAG, "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; @@ -472,7 +473,7 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) break; case SYSTEM_EVENT_STA_DISCONNECTED: - ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED - REASON CODE %d", event->event_info.disconnected.reason); + 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); @@ -643,7 +644,7 @@ void wifi_manager( void * pvParameters ){ tcpip_adapter_init(); /* event handler and event group for the wifi driver */ - wifi_manager_event_group = xEventGroupCreate(); //TODO: DELETE + wifi_manager_event_group = xEventGroupCreate(); ESP_ERROR_CHECK(esp_event_loop_init(wifi_manager_event_handler, NULL)); /* wifi scanner config */ @@ -739,12 +740,12 @@ void wifi_manager( void * pvParameters ){ wifi_manager_unlock_json_buffer(); } else{ - ESP_LOGI(TAG, "wifi_manager: could not get access to json mutex in wifi_scan"); + ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan"); } break; case ORDER_START_WIFI_SCAN: - ESP_LOGI(TAG, "MESSAGE: ORDER_START_WIFI_SCAN"); + ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN"); /* 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); @@ -850,14 +851,33 @@ void wifi_manager( void * pvParameters ){ /* there are no retries when it's a user requested connection by design. This avoids a user hanging too much * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */ xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); + + if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ + wifi_manager_generate_ip_info_json( UPDATE_FAILED_ATTEMPT ); + wifi_manager_unlock_json_buffer(); + } + } else if (uxBits & WIFI_MANAGER_REQUEST_DISCONNECT_BIT){ /* user manually requested a disconnect so the lost connection is a normal event. Clear the flag and restart the AP */ xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT); + + if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ + wifi_manager_generate_ip_info_json( UPDATE_USER_DISCONNECT ); + wifi_manager_unlock_json_buffer(); + } + + /* TODO: FORGET SAVED WIFI IN NVS MEMORY */ + wifi_manager_send_message(ORDER_START_AP, NULL); } else{ /* lost connection ? */ + if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ + wifi_manager_generate_ip_info_json( UPDATE_LOST_CONNECTION ); + wifi_manager_unlock_json_buffer(); + } + if(retries < WIFI_MANAGER_MAX_RETRY){ retries++; wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT); @@ -915,8 +935,6 @@ void wifi_manager( void * pvParameters ){ /* order wifi discconect */ ESP_ERROR_CHECK(esp_wifi_disconnect()); - /* 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 ); break; default: break; diff --git a/wifi_manager/main/wifi_manager.h b/wifi_manager/main/wifi_manager.h index c8b6ad26..2cb45570 100644 --- a/wifi_manager/main/wifi_manager.h +++ b/wifi_manager/main/wifi_manager.h @@ -184,6 +184,9 @@ typedef enum message_code_t { }message_code_t; +/** + * @brief simplified reason codes for a lost connection + */ typedef enum update_reason_code_t { UPDATE_CONNECTION_OK = 0, UPDATE_FAILED_ATTEMPT = 1, From 95865b927f2a646ac008593e01882d16fa496e8a Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:24:53 +0800 Subject: [PATCH 07/12] removed event group for the HTTP server --- wifi_manager/main/http_server.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/wifi_manager/main/http_server.c b/wifi_manager/main/http_server.c index 0cd9444e..56d037c2 100644 --- a/wifi_manager/main/http_server.c +++ b/wifi_manager/main/http_server.c @@ -92,21 +92,12 @@ const static char http_redirect_hdr_end[] = "/\n\n"; -//TODO: delete -//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(){ 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(); - - struct netconn *conn, *newconn; err_t err; conn = netconn_new(NETCONN_TCP); From 8a1acaec7fbe4529b6dc66e82a137a7295408335 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:25:04 +0800 Subject: [PATCH 08/12] added max retries to the config --- wifi_manager/main/Kconfig.projbuild | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wifi_manager/main/Kconfig.projbuild b/wifi_manager/main/Kconfig.projbuild index 8efd485f..b1dbe5fe 100644 --- a/wifi_manager/main/Kconfig.projbuild +++ b/wifi_manager/main/Kconfig.projbuild @@ -6,6 +6,12 @@ config WIFI_MANAGER_TASK_PRIORITY 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" From 27b05417b54bd28679edde82752dd14af580d464 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:25:32 +0800 Subject: [PATCH 09/12] added max retry to the config --- wifi_manager/main/wifi_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wifi_manager/main/wifi_manager.h b/wifi_manager/main/wifi_manager.h index 2cb45570..2ea291c6 100644 --- a/wifi_manager/main/wifi_manager.h +++ b/wifi_manager/main/wifi_manager.h @@ -66,7 +66,7 @@ extern "C" { * @brief Defines when a connection is lost/attempt to connect is made, how many retries should be made before giving up. * Setting it to 2 for instance means there will be 3 attempts in total (original request + 2 retries) */ -#define WIFI_MANAGER_MAX_RETRY 2 +#define WIFI_MANAGER_MAX_RETRY CONFIG_WIFI_MANAGER_MAX_RETRY /** @brief Defines the task priority of the wifi_manager. * From 2e6cedb754f8b19c97a6b8cb74ae6e5191ba3b0a Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:25:50 +0800 Subject: [PATCH 10/12] removed old wifi_manager task --- wifi_manager/main/wifi_manager.c | 294 ++++--------------------------- 1 file changed, 33 insertions(+), 261 deletions(-) diff --git a/wifi_manager/main/wifi_manager.c b/wifi_manager/main/wifi_manager.c index 084b4e82..e63fa199 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -63,7 +63,6 @@ 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; @@ -72,6 +71,8 @@ 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; /** @@ -107,7 +108,7 @@ const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3; 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; //TODO: DELETE +//const int WIFI_MANAGER_REQUEST_WIFI_SCAN = BIT5; //TODO: DELETE /* @brief When set, means a client requested to disconnect from currently connected AP. */ const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT = BIT6; @@ -221,7 +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")); + /* 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); @@ -782,6 +783,7 @@ void wifi_manager( void * pvParameters ){ 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 */ @@ -804,11 +806,14 @@ void wifi_manager( void * pvParameters ){ * * 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 + * 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 is NOT set, it's a lost connection + * 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. + * In this version of the software, reason codes are not used. They are indicated here for potential future usage. * * REASON CODE: * 1 UNSPECIFIED @@ -867,8 +872,15 @@ void wifi_manager( void * pvParameters ){ wifi_manager_unlock_json_buffer(); } - /* TODO: FORGET SAVED WIFI IN NVS MEMORY */ + /* erase configuration */ + if(wifi_manager_config_sta){ + memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); + } + /* save NVS memory */ + wifi_manager_save_sta_config(); + + /* start SoftAP */ wifi_manager_send_message(ORDER_START_AP, NULL); } else{ @@ -883,8 +895,18 @@ void wifi_manager( void * pvParameters ){ wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT); } else{ - /* connection was lost beyond repair: kick start the AP! */ + /* In this scenario the connection was lost beyond repair: kick start the AP! */ retries = 0; + + /* erase configuration that could not be used to connect */ + if(wifi_manager_config_sta){ + memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); + } + + /* save empty connection info in NVS memory */ + wifi_manager_save_sta_config(); + + /* start SoftAP */ wifi_manager_send_message(ORDER_START_AP, NULL); } } @@ -921,7 +943,6 @@ void wifi_manager( void * pvParameters ){ else { abort(); } /* bring down DNS hijack */ - ESP_LOGI(TAG, "Call to dns_server_stop();"); dns_server_stop(); break; @@ -939,261 +960,12 @@ void wifi_manager( void * pvParameters ){ default: break; - } - } - - } + } /* end of switch/case */ + } /* end of if status=pdPASS */ + } /* end of for loop */ vTaskDelete( NULL ); } -void wifi_managerBACKUP( void * pvParameters ){ - - /* 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); - accessp_json = (char*)malloc(MAX_AP_NUM * JSON_ONE_APP_SIZE + 4); /* 4 bytes for json encapsulation of "[\n" and "]\0" */ - wifi_manager_clear_access_points_json(); - ip_info_json = (char*)malloc(sizeof(char) * JSON_IP_INFO_SIZE); - wifi_manager_clear_ip_info_json(); - 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); - - /* initialize the tcp stack */ - tcpip_adapter_init(); - - /* 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)); - - /* wifi scanner config */ - wifi_scan_config_t scan_config = { - .ssid = 0, - .bssid = 0, - .channel = 0, - .show_hidden = true - }; - - - /* try to get access to previously saved wifi */ - if(wifi_manager_fetch_wifi_sta_config()){ - ESP_LOGI(TAG, "Saved wifi found on startup"); - /* request a connection */ - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); - } - - /* 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 */ - 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); */ - 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)); - /* start dhcp server */ - ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); - - - - - tcpip_adapter_dhcp_status_t status; - if(wifi_settings.sta_static_ip) { - - ESP_LOGI(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)); - - /* 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_LOGI(TAG, "wifi_manager: Start DHCP client for STA interface. If not already running\n"); - 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)); - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_LOGI(TAG, "starting softAP with ssid %s", ap_config.ap.ssid); - ESP_LOGI(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_LOGI(TAG, "softAP started, starting http_server"); - - /* start http server */ - //http_server_set_event_start(); - - /* start DNS server */ - dns_server_start(); - - - EventBits_t uxBits; - for(;;){ - - /* 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*/ - - /*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()); - - /* 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); - - /* erase configuration */ - if(wifi_manager_config_sta){ - memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); - } - - /* save NVS memory */ - wifi_manager_save_sta_config(); - - /* 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(); - } - - /* 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! - - /* 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) ){ - - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT); - ESP_ERROR_CHECK(esp_wifi_disconnect()); - - /* 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 ); - } - - /* set the new config and connect - reset the disconnect bit first as it is later tested */ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_STA_DISCONNECT_BIT); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config())); - ESP_ERROR_CHECK(esp_wifi_connect()); - - /* 2 scenarios here: connection is successful and SYSTEM_EVENT_STA_GOT_IP will be posted - * or it's a failure and we get a SYSTEM_EVENT_STA_DISCONNECTED with a reason code. - * Note that the reason code is not exploited. For all intent and purposes a failure is a failure. - */ - uxBits = xEventGroupWaitBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_STA_DISCONNECT_BIT, pdFALSE, pdFALSE, portMAX_DELAY ); - - if(uxBits & (WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_STA_DISCONNECT_BIT)){ - - /* Update the json regardless of connection status. - * If connection was succesful an IP will get assigned. - * If the connection attempt is failed we mark it as a failed connection attempt - * as it is important for the front end app to distinguish failed attempt to - * regular disconnects - */ - if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ - - /* only save the config if the connection was successful! */ - if(uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT){ - - /* generate the connection info with success */ - wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK ); - - /* save wifi config in NVS */ - wifi_manager_save_sta_config(); - } - else{ - - /* failed attempt to connect regardles of the reason */ - wifi_manager_generate_ip_info_json( UPDATE_FAILED_ATTEMPT ); - - /* otherwise: reset the config */ - memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); - } - 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(); - } - } - else{ - /* hit portMAX_DELAY limit ? */ - abort(); - } - /* finally: release the connection request bit */ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); - } - else if(uxBits & WIFI_MANAGER_REQUEST_WIFI_SCAN){ - ap_num = MAX_AP_NUM; - - ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true)); - 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( ( TickType_t ) 20 )){ - /* 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_LOGI(TAG, "wifi_manager: could not get access to json mutex in wifi_scan\n"); - } - - /* finally: release the scan request bit */ - xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_SCAN); - } - } /* for(;;) */ - vTaskDelay( (TickType_t)10); -} /*void wifi_manager*/ From 9105d3bf6845d3327827aec0273201b660959aa2 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:55:11 +0800 Subject: [PATCH 11/12] start serv only if no task yet --- wifi_manager/main/http_server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wifi_manager/main/http_server.c b/wifi_manager/main/http_server.c index 56d037c2..d10b14dc 100644 --- a/wifi_manager/main/http_server.c +++ b/wifi_manager/main/http_server.c @@ -93,7 +93,9 @@ const static char http_redirect_hdr_end[] = "/\n\n"; void http_server_start(){ - xTaskCreate(&http_server, "http_server", 2048, NULL, WIFI_MANAGER_TASK_PRIORITY-1, &task_http_server); + 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) { From dc66d777aa3b2949b041775c697e9ff6cc1f09b2 Mon Sep 17 00:00:00 2001 From: tonyp7 Date: Sat, 11 May 2019 11:55:26 +0800 Subject: [PATCH 12/12] moved http start to top --- wifi_manager/main/wifi_manager.c | 42 +++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/wifi_manager/main/wifi_manager.c b/wifi_manager/main/wifi_manager.c index e63fa199..b010ede2 100644 --- a/wifi_manager/main/wifi_manager.c +++ b/wifi_manager/main/wifi_manager.c @@ -99,7 +99,7 @@ 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; @@ -107,11 +107,11 @@ 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; //TODO: DELETE +/* @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; @@ -128,7 +128,7 @@ void wifi_manager_scan_async(){ void wifi_manager_disconnect_async(){ wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL); - //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT); TODO: delete + //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete } @@ -436,7 +436,7 @@ esp_err_t wifi_manager_event_handler(void *ctx, system_event_t *event) case SYSTEM_EVENT_AP_START: ESP_LOGI(TAG, "SYSTEM_EVENT_AP_START"); - xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED); + xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED_BIT); break; case SYSTEM_EVENT_AP_STOP: @@ -713,14 +713,18 @@ void wifi_manager( void * pvParameters ){ + /* 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()); + /* start http server */ + http_server_start(); /* enqueue first event: load previous config */ wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL); + /* main processing loop */ for(;;){ xStatus = xQueueReceive( wifi_manager_queue, &msg, portMAX_DELAY ); @@ -777,8 +781,12 @@ void wifi_manager( void * pvParameters ){ * 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) + 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); + } uxBits = xEventGroupGetBits(wifi_manager_event_group); if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){ @@ -898,6 +906,9 @@ void wifi_manager( void * pvParameters ){ /* In this scenario the connection was lost beyond repair: kick start the AP! */ retries = 0; + /* if it was a restore attempt connection, we clear the bit */ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT); + /* erase configuration that could not be used to connect */ if(wifi_manager_config_sta){ memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t)); @@ -916,7 +927,7 @@ void wifi_manager( void * pvParameters ){ ESP_LOGI(TAG, "MESSAGE: ORDER_START_AP"); esp_wifi_set_mode(WIFI_MODE_APSTA); - http_server_start(); + //http_server_start(); dns_server_start(); break; @@ -924,20 +935,26 @@ void wifi_manager( void * pvParameters ){ case EVENT_STA_GOT_IP: ESP_LOGI(TAG, "MESSAGE: EVENT_STA_GOT_IP"); + uxBits = xEventGroupGetBits(wifi_manager_event_group); + /* reset connection requests bits -- doesn't matter if it was set or not */ xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT); /* save IP as a string for the HTTP server host */ wifi_manager_safe_update_sta_ip_string((uint32_t)msg.param); + /* save wifi config in NVS if it wasn't a restored of a connection */ + if(uxBits & WIFI_MANAGER_REQUEST_RESTORE_STA_BIT){ + xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT); + } + else{ + wifi_manager_save_sta_config(); + } + /* refresh JSON with the new IP */ if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ /* generate the connection info with success */ wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK ); - - /* save wifi config in NVS */ - wifi_manager_save_sta_config(); - wifi_manager_unlock_json_buffer(); } else { abort(); } @@ -957,6 +974,7 @@ void wifi_manager( void * pvParameters ){ ESP_ERROR_CHECK(esp_wifi_disconnect()); break; + default: break;