12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139 |
- /*
- Copyright (c) 2017-2019 Tony Pottier
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- @file wifi_manager.c
- @author Tony Pottier
- @brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
- Contains the freeRTOS task and all necessary support
- @see https://idyl.io
- @see https://github.com/tonyp7/esp32-wifi-manager
- */
- #include "wifi_manager.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdbool.h>
- #include "dns_server.h"
- #include "http_server.h"
- #include "json.h"
- #include "esp_system.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/event_groups.h"
- #include "esp_event_loop.h"
- #include "esp_wifi.h"
- #include "esp_wifi_types.h"
- #include "esp_log.h"
- #include "nvs.h"
- #include "nvs_flash.h"
- #include "mdns.h"
- #include "lwip/api.h"
- #include "lwip/err.h"
- #include "lwip/netdb.h"
- #include "lwip/ip4_addr.h"
- #include "esp_ota_ops.h"
- #include "esp_app_format.h"
- #ifndef SQUEEZELITE_ESP32_RELEASE_URL
- #define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
- #endif
- #if RECOVERY_APPLICATION
- extern const char * ota_get_status();
- extern uint8_t ota_get_pct_complete();
- #endif
- /* 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;
- char *ip_info_json = NULL;
- wifi_config_t* wifi_manager_config_sta = NULL;
- void (**cb_ptr_arr)(void*) = 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
- */
- struct wifi_settings_t wifi_settings = {
- .ap_ssid = DEFAULT_AP_SSID,
- .ap_pwd = DEFAULT_AP_PASSWORD,
- .ap_channel = DEFAULT_AP_CHANNEL,
- .ap_ssid_hidden = DEFAULT_AP_SSID_HIDDEN,
- .ap_bandwidth = DEFAULT_AP_BANDWIDTH,
- .sta_only = DEFAULT_STA_ONLY,
- .sta_power_save = DEFAULT_STA_POWER_SAVE,
- .sta_static_ip = 0,
- };
- const char wifi_manager_nvs_namespace[] = "espwifimgr";
- extern char current_namespace[];
- 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_BIT = BIT2;
- /* @brief When set, means a client requested to connect to an access point.*/
- 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 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_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(){
- wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL);
- }
- void wifi_manager_disconnect_async(){
- 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();
- /* memory allocation */
- wifi_manager_queue = xQueueCreate( 3, sizeof( queue_message) );
- 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));
- cb_ptr_arr = malloc( sizeof( sizeof( void (*)( void* ) ) ) * MESSAGE_CODE_COUNT);
- for(int i=0; i<MESSAGE_CODE_COUNT; i++){
- cb_ptr_arr[i] = NULL;
- }
- 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);
- /* start wifi manager task */
- xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager);
- }
- uint8_t wifi_manager_get_flag(){
- uint8_t value=0;
- nvs_handle handle;
- esp_err_t esp_err;
- ESP_LOGI(TAG, "About to get config from flash");
- esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle);
- if (esp_err != ESP_OK) return 0;
- esp_err= nvs_get_u8(handle, "autoexec", &value);
- nvs_close(handle);
- return value;
- }
- char * wifi_manager_alloc_get_config(char * name, size_t * l){
- size_t len=0;
- char * value=NULL;
- nvs_handle handle;
- ESP_LOGD(TAG, "About to get config value %s from flash",name);
- if (nvs_open(current_namespace, NVS_READWRITE, &handle) == ESP_OK) {
- if (nvs_get_str(handle, name, NULL, &len)==ESP_OK) {
- value=(char *)malloc(len);
- memset(value,0x0, len);
- nvs_get_str(handle, name, value, &len);
- *l=len;
- ESP_LOGD(TAG,"Found value %s, length %u = %s",name,*l,value);
- }
- else
- {
- ESP_LOGW(TAG, "Value %s does one exist in flash",name);
- }
- nvs_close(handle);
- }
- else
- {
- ESP_LOGE(TAG,"Unable to open nvs namespace %s",wifi_manager_nvs_namespace);
- }
- return value;
- }
- esp_err_t wifi_manager_save_autoexec_flag(uint8_t flag){
- nvs_handle handle;
- esp_err_t esp_err;
- ESP_LOGI(TAG, "About to save config to flash");
- esp_err=nvs_open(current_namespace, NVS_READWRITE, &handle);
- if (esp_err != ESP_OK) {
- ESP_LOGE(TAG,"Unable to open nvs namespace %s",wifi_manager_nvs_namespace);
- return esp_err;
- }
- esp_err = nvs_set_u8(handle, "autoexec", flag);
- if (esp_err != ESP_OK){
- ESP_LOGE(TAG,"Unable to save autoexec flag value %u",flag);
- nvs_close(handle);
- return esp_err;
- }
- esp_err = nvs_commit(handle);
- if (esp_err != ESP_OK){
- ESP_LOGE(TAG,"nvs commit error");
- return esp_err;
- }
- nvs_close(handle);
- ESP_LOGD(TAG, "wifi_manager_wrote autoexec flag value %u",flag);
- return ESP_OK;
- }
- esp_err_t wifi_manager_save_autoexec_config(char * value, char * name, int len){
- nvs_handle handle;
- esp_err_t esp_err;
- ESP_LOGI(TAG, "About to save config to flash");
- esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle);
- if (esp_err != ESP_OK) {
- ESP_LOGE(TAG,"Unable to open nvs namespace %s",current_namespace);
- return esp_err;
- }
- esp_err = nvs_set_str(handle, name, value);
- if (esp_err != ESP_OK){
- ESP_LOGE(TAG,"Unable to save value %s=%s",name,value);
- nvs_close(handle);
- return esp_err;
- }
- esp_err = nvs_commit(handle);
- if (esp_err != ESP_OK){
- ESP_LOGE(TAG,"nvs commit error");
- return esp_err;
- }
- nvs_close(handle);
- ESP_LOGD(TAG, "wifi_manager_wrote %s=%s with length %i", name, value, len);
- return ESP_OK;
- }
- esp_err_t wifi_manager_save_sta_config(){
- nvs_handle handle;
- esp_err_t esp_err;
- ESP_LOGI(TAG, "About to save config to flash");
- if(wifi_manager_config_sta){
- esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle);
- if (esp_err != ESP_OK) return esp_err;
- esp_err = nvs_set_blob(handle, "ssid", wifi_manager_config_sta->sta.ssid, 32);
- if (esp_err != ESP_OK) return esp_err;
- esp_err = nvs_set_blob(handle, "password", wifi_manager_config_sta->sta.password, 64);
- if (esp_err != ESP_OK) return esp_err;
- esp_err = nvs_set_blob(handle, "settings", &wifi_settings, sizeof(wifi_settings));
- if (esp_err != ESP_OK) return esp_err;
- esp_err = nvs_commit(handle);
- if (esp_err != ESP_OK) return esp_err;
- nvs_close(handle);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_sta_config: ssid:%s password:%s",wifi_manager_config_sta->sta.ssid,wifi_manager_config_sta->sta.password);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: SoftAP_ssid: %s",wifi_settings.ap_ssid);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: SoftAP_pwd: %s",wifi_settings.ap_pwd);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: SoftAP_channel: %i",wifi_settings.ap_channel);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: SoftAP_hidden (1 = yes): %i",wifi_settings.ap_ssid_hidden);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: SoftAP_bandwidth (1 = 20MHz, 2 = 40MHz): %i",wifi_settings.ap_bandwidth);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_only (0 = APSTA, 1 = STA when connected): %i",wifi_settings.sta_only);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_power_save (1 = yes): %i",wifi_settings.sta_power_save);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_static_ip (0 = dhcp client, 1 = static ip): %i",wifi_settings.sta_static_ip);
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_ip_addr: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip));
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_gw_addr: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw));
- ESP_LOGD(TAG, "wifi_manager_wrote wifi_settings: sta_netmask: %s", ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask));
- }
- return ESP_OK;
- }
- bool wifi_manager_fetch_wifi_sta_config(){
- nvs_handle handle;
- esp_err_t esp_err;
- if(nvs_open(wifi_manager_nvs_namespace, NVS_READONLY, &handle) == ESP_OK){
- if(wifi_manager_config_sta == NULL){
- 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, 0x00, sizeof(struct wifi_settings_t));
- /* allocate buffer */
- size_t sz = sizeof(wifi_settings);
- uint8_t *buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
- memset(buff, 0x00, sizeof(sz));
- /* ssid */
- sz = sizeof(wifi_manager_config_sta->sta.ssid);
- esp_err = nvs_get_blob(handle, "ssid", buff, &sz);
- if(esp_err != ESP_OK){
- free(buff);
- return false;
- }
- memcpy(wifi_manager_config_sta->sta.ssid, buff, sz);
- /* password */
- sz = sizeof(wifi_manager_config_sta->sta.password);
- esp_err = nvs_get_blob(handle, "password", buff, &sz);
- if(esp_err != ESP_OK){
- free(buff);
- 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);
- esp_err = nvs_get_blob(handle, "settings", buff, &sz);
- if(esp_err != ESP_OK){
- free(buff);
- return false;
- }
- memcpy(&wifi_settings, buff, sz);
- free(buff);
- nvs_close(handle);
- 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';
- }
- else{
- return false;
- }
- }
- void wifi_manager_clear_ip_info_json(){
- strcpy(ip_info_json, "{}\n");
- }
- void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){
- wifi_config_t *config = wifi_manager_get_wifi_sta_config();
- if(config){
- #if RECOVERY_APPLICATION
- const char ip_info_json_format[] = ",\"ip\":\"%s\",\"netmask\":\"%s\",\"gw\":\"%s\",\"urc\":%d,\"project_name\":\"%s\",\"version\":\"%s\", \"ota_dsc\":\"%s\", \"ota_pct\":%d}\n";
- #else
- const char ip_info_json_format[] = ",\"ip\":\"%s\",\"netmask\":\"%s\",\"gw\":\"%s\",\"urc\":%d,\"project_name\":\"%s\",\"version\":\"%s\"}\n";
- #endif
- memset(ip_info_json, 0x00, JSON_IP_INFO_SIZE);
- const esp_app_desc_t* desc = esp_ota_get_app_description();
- /* to avoid declaring a new buffer we copy the data directly into the buffer at its correct address */
- strcpy(ip_info_json, "{\"ssid\":");
- json_print_string(config->sta.ssid, (unsigned char*)(ip_info_json+strlen(ip_info_json)) );
- if(update_reason_code == UPDATE_CONNECTION_OK){
- /* rest of the information is copied after the ssid */
- tcpip_adapter_ip_info_t ip_info;
- ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
- char ip[IP4ADDR_STRLEN_MAX]; /* note: IP4ADDR_STRLEN_MAX is defined in lwip */
- char gw[IP4ADDR_STRLEN_MAX];
- char netmask[IP4ADDR_STRLEN_MAX];
- strcpy(ip, ip4addr_ntoa(&ip_info.ip));
- strcpy(netmask, ip4addr_ntoa(&ip_info.netmask));
- strcpy(gw, ip4addr_ntoa(&ip_info.gw));
- snprintf( (ip_info_json + strlen(ip_info_json)), JSON_IP_INFO_SIZE, ip_info_json_format,
- ip,
- netmask,
- gw,
- (int)update_reason_code,
- desc->project_name,
- desc->version
- #if RECOVERY_APPLICATION
- ,ota_get_status(),
- ota_get_pct_complete()
- #endif
- );
- }
- else{
- /* notify in the json output the reason code why this was updated without a connection */
- snprintf( (ip_info_json + strlen(ip_info_json)), JSON_IP_INFO_SIZE, ip_info_json_format,
- "0",
- "0",
- "0",
- (int)update_reason_code,
- desc->project_name,
- desc->version
- #if RECOVERY_APPLICATION
- ,"",
- 0
- #endif
- );
- }
- }
- else{
- wifi_manager_clear_ip_info_json();
- }
- }
- void wifi_manager_clear_access_points_json(){
- strcpy(accessp_json, "[]\n");
- }
- void wifi_manager_generate_acess_points_json(){
- strcpy(accessp_json, "[");
- const char oneap_str[] = ",\"chan\":%d,\"rssi\":%d,\"auth\":%d}%c\n";
- /* stack buffer to hold on to one AP until it's copied over to accessp_json */
- char one_ap[JSON_ONE_APP_SIZE];
- for(int i=0; i<ap_num;i++){
- wifi_ap_record_t ap = accessp_records[i];
- /* ssid needs to be json escaped. To save on heap memory it's directly printed at the correct address */
- strcat(accessp_json, "{\"ssid\":");
- json_print_string( (unsigned char*)ap.ssid, (unsigned char*)(accessp_json+strlen(accessp_json)) );
- /* print the rest of the json for this access point: no more string to escape */
- snprintf(one_ap, (size_t)JSON_ONE_APP_SIZE, oneap_str,
- ap.primary,
- ap.rssi,
- ap.authmode,
- i==ap_num-1?']':',');
- /* add it to the list */
- strcat(accessp_json, one_ap);
- }
- }
- 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 ) {
- return true;
- }
- else{
- return false;
- }
- }
- else{
- return false;
- }
- }
- void wifi_manager_unlock_json_buffer(){
- xSemaphoreGive( wifi_manager_json_mutex );
- }
- char* wifi_manager_get_ap_list_json(){
- return accessp_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:
- ESP_LOGI(TAG, "SYSTEM_EVENT_AP_START");
- xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED_BIT);
- break;
- 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:
- 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:
- break;
- }
- return ESP_OK;
- }
- wifi_config_t* wifi_manager_get_wifi_sta_config(){
- return wifi_manager_config_sta;
- }
- void wifi_manager_connect_async(){
- /* in order to avoid a false positive on the front end app we need to quickly flush the ip json
- * There'se a risk the front end sees an IP or a password error when in fact
- * it's a remnant from a previous connection
- */
- if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
- wifi_manager_clear_ip_info_json();
- wifi_manager_unlock_json_buffer();
- }
- wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER);
- }
- char* wifi_manager_get_ip_info_json(){
- return ip_info_json;
- }
- void wifi_manager_destroy(){
- vTaskDelete(task_wifi_manager);
- task_wifi_manager = NULL;
- /* heap buffers */
- free(accessp_records);
- accessp_records = NULL;
- free(accessp_json);
- 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;
- }
- /* 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;
- }
- void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) {
- int total_unique;
- wifi_ap_record_t * first_free;
- total_unique=*aps;
- first_free=NULL;
- for(int i=0; i<*aps-1;i++) {
- wifi_ap_record_t * ap = &aplist[i];
- /* skip the previously removed APs */
- if (ap->ssid[0] == 0) continue;
- /* remove the identical SSID+authmodes */
- for(int j=i+1; j<*aps;j++) {
- wifi_ap_record_t * ap1 = &aplist[j];
- if ( (strcmp((const char *)ap->ssid, (const char *)ap1->ssid)==0) &&
- (ap->authmode == ap1->authmode) ) { /* same SSID, different auth mode is skipped */
- /* save the rssi for the display */
- if ((ap1->rssi) > (ap->rssi)) ap->rssi=ap1->rssi;
- /* clearing the record */
- memset(ap1,0, sizeof(wifi_ap_record_t));
- }
- }
- }
- /* reorder the list so APs follow each other in the list */
- for(int i=0; i<*aps;i++) {
- wifi_ap_record_t * ap = &aplist[i];
- /* skipping all that has no name */
- if (ap->ssid[0] == 0) {
- /* mark the first free slot */
- if (first_free==NULL) first_free=ap;
- total_unique--;
- continue;
- }
- if (first_free!=NULL) {
- memcpy(first_free, ap, sizeof(wifi_ap_record_t));
- memset(ap,0, sizeof(wifi_ap_record_t));
- /* find the next free slot */
- for(int j=0; j<*aps;j++) {
- if (aplist[j].ssid[0]==0) {
- first_free=&aplist[j];
- break;
- }
- }
- }
- }
- /* update the length of the list */
- *aps = total_unique;
- }
- 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_set_callback(message_code_t message_code, void (*func_ptr)(void*) ){
- if(cb_ptr_arr && message_code < MESSAGE_CODE_COUNT){
- cb_ptr_arr[message_code] = func_ptr;
- }
- }
- void wifi_manager( void * pvParameters ){
- queue_message msg;
- BaseType_t xStatus;
- EventBits_t uxBits;
- uint8_t retries = 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
- };
- /* 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));
- /* SoftAP - Wifi Access Point configuration setup */
- 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 - 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",
- 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");
- 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));
- }
- /* 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 );
- 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");
- }
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- break;
- case 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);
- 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));
- }
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- 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);
- }
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(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);
- }
- 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 ){
- 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());
- }
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- 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 <n/a>
- * 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
- *
- * */
- /* 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
- * 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();
- }
- /* 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{
- /* 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);
- }
- else{
- /* 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));
- }
- /* save empty connection info in NVS memory */
- wifi_manager_save_sta_config();
- /* start SoftAP */
- wifi_manager_send_message(ORDER_START_AP, NULL);
- }
- }
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(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();
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- break;
- 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 );
- wifi_manager_unlock_json_buffer();
- }
- else { abort(); }
- /* bring down DNS hijack */
- dns_server_stop();
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- 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());
- /* callback */
- if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
- break;
- default:
- break;
- } /* end of switch/case */
- } /* end of if status=pdPASS */
- } /* end of for loop */
- vTaskDelete( NULL );
- }
|