wifi_manager.c 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673
  1. /*
  2. Copyright (c) 2017-2019 Tony Pottier
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in all
  10. copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. @file wifi_manager.c
  19. @author Tony Pottier
  20. @brief Defines all functions necessary for esp32 to connect to a wifi/scan wifis
  21. Contains the freeRTOS task and all necessary support
  22. @see https://idyl.io
  23. @see https://github.com/tonyp7/esp32-wifi-manager
  24. */
  25. #include "wifi_manager.h"
  26. #include "platform_esp32.h"
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <stdbool.h>
  31. #include "dns_server.h"
  32. #include "esp_system.h"
  33. #include "freertos/FreeRTOS.h"
  34. #include "freertos/task.h"
  35. #include "freertos/event_groups.h"
  36. #include <esp_event.h>
  37. #include "esp_event_loop.h"
  38. #include "tcpip_adapter.h"
  39. // IDF-V4++ #include "esp_netif.h"
  40. #include "esp_event.h"
  41. #include "esp_wifi.h"
  42. #include "esp_wifi_types.h"
  43. #include "esp_log.h"
  44. #include "nvs.h"
  45. #include "nvs_flash.h"
  46. #include "mdns.h"
  47. #include "lwip/api.h"
  48. #include "lwip/err.h"
  49. #include "lwip/netdb.h"
  50. #include "lwip/ip4_addr.h"
  51. #include "esp_ota_ops.h"
  52. #include "esp_app_format.h"
  53. #include "cJSON.h"
  54. #include "platform_config.h"
  55. #include "trace.h"
  56. #include "cmd_system.h"
  57. #include "messaging.h"
  58. #include "bt_app_core.h"
  59. #include "http_server_handlers.h"
  60. #include "monitor.h"
  61. #include "globdefs.h"
  62. #ifndef CONFIG_SQUEEZELITE_ESP32_RELEASE_URL
  63. #pragma message "Defaulting release url"
  64. #define CONFIG_SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
  65. #endif
  66. #define STR_OR_BLANK(p) p==NULL?"":p
  67. BaseType_t wifi_manager_task;
  68. /* objects used to manipulate the main queue of events */
  69. QueueHandle_t wifi_manager_queue;
  70. SemaphoreHandle_t wifi_manager_json_mutex = NULL;
  71. SemaphoreHandle_t wifi_manager_sta_ip_mutex = NULL;
  72. char *wifi_manager_sta_ip = NULL;
  73. #define STA_IP_LEN sizeof(char) * IP4ADDR_STRLEN_MAX
  74. uint16_t ap_num = MAX_AP_NUM;
  75. wifi_ap_record_t *accessp_records=NULL;
  76. cJSON * accessp_cjson=NULL;
  77. char *ip_info_json = NULL;
  78. char * release_url=NULL;
  79. cJSON * ip_info_cjson=NULL;
  80. wifi_config_t* wifi_manager_config_sta = NULL;
  81. static void (*chained_notify)(in_addr_t, u16_t, u16_t);
  82. static int32_t total_connected_time=0;
  83. static int64_t last_connected=0;
  84. static uint16_t num_disconnect=0;
  85. static char lms_server_ip[IP4ADDR_STRLEN_MAX]={0};
  86. static uint16_t lms_server_port=0;
  87. static uint16_t lms_server_cport=0;
  88. void (**cb_ptr_arr)(void*) = NULL;
  89. /* @brief tag used for ESP serial console messages */
  90. static const char TAG[] = "wifi_manager";
  91. /* @brief task handle for the main wifi_manager task */
  92. static TaskHandle_t task_wifi_manager = NULL;
  93. #define STA_POLLING_MIN (15*1000)
  94. #define STA_POLLING_MAX (10*60*1000)
  95. /**
  96. * The actual WiFi settings in use
  97. */
  98. //struct wifi_settings_t wifi_settings = {
  99. // .sta_only = DEFAULT_STA_ONLY,
  100. // .sta_power_save = DEFAULT_STA_POWER_SAVE,
  101. // .sta_static_ip = 0
  102. //};
  103. /* wifi scanner config */
  104. wifi_scan_config_t scan_config = {
  105. .ssid = 0,
  106. .bssid = 0,
  107. .channel = 0,
  108. .show_hidden = true
  109. };
  110. const char wifi_manager_nvs_namespace[] = "config";
  111. EventGroupHandle_t wifi_manager_event_group;
  112. /* @brief indicate that the ESP32 is currently connected. */
  113. const int WIFI_MANAGER_WIFI_CONNECTED_BIT = BIT0;
  114. const int WIFI_MANAGER_AP_STA_CONNECTED_BIT = BIT1;
  115. /* @brief Set automatically once the SoftAP is started */
  116. const int WIFI_MANAGER_AP_STARTED_BIT = BIT2;
  117. /* @brief When set, means a client requested to connect to an access point.*/
  118. const int WIFI_MANAGER_REQUEST_STA_CONNECT_BIT = BIT3;
  119. /* @brief This bit is set automatically as soon as a connection was lost */
  120. const int WIFI_MANAGER_STA_DISCONNECT_BIT = BIT4;
  121. /* @brief When set, means the wifi manager attempts to restore a previously saved connection at startup. */
  122. const int WIFI_MANAGER_REQUEST_RESTORE_STA_BIT = BIT5;
  123. /* @brief When set, means a client requested to disconnect from currently connected AP. */
  124. const int WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT = BIT6;
  125. /* @brief When set, means a scan is in progress */
  126. const int WIFI_MANAGER_SCAN_BIT = BIT7;
  127. /* @brief When set, means user requested for a disconnect */
  128. const int WIFI_MANAGER_REQUEST_DISCONNECT_BIT = BIT8;
  129. /* @brief When set, means user requested connecting to a new network and it failed */
  130. const int WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT = BIT9;
  131. char * get_disconnect_code_desc(uint8_t reason){
  132. switch (reason) {
  133. case 1 : return "UNSPECIFIED"; break;
  134. case 2 : return "AUTH_EXPIRE"; break;
  135. case 3 : return "AUTH_LEAVE"; break;
  136. case 4 : return "ASSOC_EXPIRE"; break;
  137. case 5 : return "ASSOC_TOOMANY"; break;
  138. case 6 : return "NOT_AUTHED"; break;
  139. case 7 : return "NOT_ASSOCED"; break;
  140. case 8 : return "ASSOC_LEAVE"; break;
  141. case 9 : return "ASSOC_NOT_AUTHED"; break;
  142. case 10 : return "DISASSOC_PWRCAP_BAD"; break;
  143. case 11 : return "DISASSOC_SUPCHAN_BAD"; break;
  144. case 12 : return "<n/a>"; break;
  145. case 13 : return "IE_INVALID"; break;
  146. case 14 : return "MIC_FAILURE"; break;
  147. case 15 : return "4WAY_HANDSHAKE_TIMEOUT"; break;
  148. case 16 : return "GROUP_KEY_UPDATE_TIMEOUT"; break;
  149. case 17 : return "IE_IN_4WAY_DIFFERS"; break;
  150. case 18 : return "GROUP_CIPHER_INVALID"; break;
  151. case 19 : return "PAIRWISE_CIPHER_INVALID"; break;
  152. case 20 : return "AKMP_INVALID"; break;
  153. case 21 : return "UNSUPP_RSN_IE_VERSION"; break;
  154. case 22 : return "INVALID_RSN_IE_CAP"; break;
  155. case 23 : return "802_1X_AUTH_FAILED"; break;
  156. case 24 : return "CIPHER_SUITE_REJECTED"; break;
  157. case 200 : return "BEACON_TIMEOUT"; break;
  158. case 201 : return "NO_AP_FOUND"; break;
  159. case 202 : return "AUTH_FAIL"; break;
  160. case 203 : return "ASSOC_FAIL"; break;
  161. case 204 : return "HANDSHAKE_TIMEOUT"; break;
  162. default: return "UNKNOWN"; break;
  163. }
  164. return "";
  165. }
  166. void wifi_manager_update_status(){
  167. wifi_manager_send_message(ORDER_UPDATE_STATUS,NULL);
  168. }
  169. void set_host_name(){
  170. esp_err_t err;
  171. ESP_LOGD(TAG, "Retrieving host name from nvs");
  172. char * host_name = (char * )config_alloc_get(NVS_TYPE_STR, "host_name");
  173. if(host_name ==NULL){
  174. ESP_LOGE(TAG, "Could not retrieve host name from nvs");
  175. }
  176. else {
  177. ESP_LOGD(TAG, "Setting host name to : %s",host_name);
  178. if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, host_name)) !=ESP_OK){
  179. ESP_LOGE(TAG, "Unable to set host name. Error: %s",esp_err_to_name(err));
  180. }
  181. // if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, host_name)) !=ESP_OK){
  182. // ESP_LOGE(TAG, "Unable to set host name. Error: %s",esp_err_to_name(err));
  183. // }
  184. free(host_name);
  185. }
  186. }
  187. bool isGroupBitSet(uint8_t bit){
  188. EventBits_t uxBits= xEventGroupGetBits(wifi_manager_event_group);
  189. return (uxBits & bit);
  190. }
  191. void wifi_manager_scan_async(){
  192. wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL);
  193. }
  194. void wifi_manager_disconnect_async(){
  195. wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
  196. //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
  197. }
  198. void wifi_manager_reboot_ota(char * url){
  199. if(url == NULL){
  200. wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
  201. }
  202. else {
  203. wifi_manager_send_message(ORDER_RESTART_OTA_URL,strdup(url) );
  204. }
  205. }
  206. void wifi_manager_reboot(reboot_type_t rtype){
  207. switch (rtype) {
  208. case OTA:
  209. wifi_manager_send_message(ORDER_RESTART_OTA, NULL);
  210. break;
  211. case RECOVERY:
  212. wifi_manager_send_message(ORDER_RESTART_RECOVERY, NULL);
  213. break;
  214. case RESTART:
  215. wifi_manager_send_message(ORDER_RESTART, NULL);
  216. break;
  217. default:
  218. ESP_LOGE(TAG,"Unknown reboot type %d", rtype);
  219. break;
  220. }
  221. wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
  222. //xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_WIFI_DISCONNECT_BIT); TODO: delete
  223. }
  224. void wifi_manager_init_wifi(){
  225. /* event handler and event group for the wifi driver */
  226. ESP_LOGD(TAG, "Initializing wifi. Creating event group");
  227. wifi_manager_event_group = xEventGroupCreate();
  228. // Now Initialize the Wifi Stack
  229. ESP_LOGD(TAG, "Initializing wifi. Initializing tcp_ip adapter");
  230. tcpip_adapter_init();
  231. ESP_LOGD(TAG, "Initializing wifi. Creating the default event loop");
  232. ESP_ERROR_CHECK(esp_event_loop_create_default());
  233. ESP_LOGD(TAG, "Initializing wifi. Getting default wifi configuration");
  234. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  235. ESP_LOGD(TAG, "Initializing wifi. Initializing wifi. ");
  236. ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
  237. ESP_LOGD(TAG, "Initializing wifi. Calling register handlers");
  238. wifi_manager_register_handlers();
  239. ESP_LOGD(TAG, "Initializing wifi. Setting WiFi storage as RAM");
  240. ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
  241. ESP_LOGD(TAG, "Initializing wifi. Setting WiFi mode to WIFI_MODE_NULL");
  242. ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
  243. ESP_LOGD(TAG, "Initializing wifi. Starting wifi");
  244. ESP_ERROR_CHECK( esp_wifi_start() );
  245. taskYIELD();
  246. ESP_LOGD(TAG, "Initializing wifi. done");
  247. }
  248. void set_lms_server_details(in_addr_t ip, u16_t hport, u16_t cport){
  249. strncpy(lms_server_ip,inet_ntoa(ip),sizeof(lms_server_ip));
  250. lms_server_ip[sizeof(lms_server_ip)-1]='\0';
  251. ESP_LOGI(TAG,"LMS IP: %s, hport: %d, cport: %d",lms_server_ip, hport, cport);
  252. lms_server_port = hport;
  253. lms_server_cport = cport;
  254. }
  255. static void connect_notify(in_addr_t ip, u16_t hport, u16_t cport) {
  256. set_lms_server_details(ip,hport,cport);
  257. if (chained_notify) (*chained_notify)(ip, hport, cport);
  258. wifi_manager_update_status();
  259. }
  260. static void polling_STA(void* timer_id) {
  261. wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
  262. }
  263. void wifi_manager_start(){
  264. /* memory allocation */
  265. ESP_LOGD(TAG, "wifi_manager_start. Creating message queue");
  266. wifi_manager_queue = xQueueCreate( 3, sizeof( queue_message) );
  267. ESP_LOGD(TAG, "wifi_manager_start. Creating mutexes");
  268. wifi_manager_json_mutex = xSemaphoreCreateMutex();
  269. wifi_manager_sta_ip_mutex = xSemaphoreCreateMutex();
  270. ESP_LOGD(TAG, "wifi_manager_start. Creating access point json structure");
  271. accessp_cjson = NULL;
  272. accessp_cjson = wifi_manager_clear_ap_list_json(&accessp_cjson);
  273. ip_info_json = NULL;
  274. ESP_LOGD(TAG, "wifi_manager_start. Creating status jcon structure");
  275. ip_info_cjson = wifi_manager_clear_ip_info_json(&ip_info_cjson);
  276. ESP_LOGD(TAG, "wifi_manager_start. Allocating memory for wifi configuration structure");
  277. wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
  278. memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
  279. // memset(&wifi_settings, 0x00, sizeof(wifi_settings));
  280. ESP_LOGD(TAG, "wifi_manager_start. Allocating memory for callback functions registration");
  281. cb_ptr_arr = malloc( sizeof( sizeof( void (*)( void* ) )) * MESSAGE_CODE_COUNT);
  282. for(int i=0; i<MESSAGE_CODE_COUNT; i++){
  283. cb_ptr_arr[i] = NULL;
  284. }
  285. ESP_LOGD(TAG, "About to set the STA IP String to 0.0.0.0");
  286. wifi_manager_sta_ip = (char*)malloc(STA_IP_LEN);
  287. wifi_manager_safe_update_sta_ip_string(NULL);
  288. ESP_LOGD(TAG, "Getting release url ");
  289. char * release_url = (char * )config_alloc_get_default(NVS_TYPE_STR, "release_url", QUOTE(CONFIG_SQUEEZELITE_ESP32_RELEASE_URL), 0);
  290. if(release_url == NULL){
  291. ESP_LOGE(TAG, "Unable to retrieve the release url from nvs");
  292. }
  293. else {
  294. ESP_LOGD(TAG, "Found release url %s", release_url);
  295. }
  296. chained_notify = server_notify;
  297. server_notify = connect_notify;
  298. ESP_LOGD(TAG, "About to call init wifi");
  299. wifi_manager_init_wifi();
  300. /* start wifi manager task */
  301. ESP_LOGD(TAG, "Creating wifi manager task");
  302. wifi_manager_task= xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager);
  303. }
  304. esp_err_t wifi_manager_save_sta_config(){
  305. nvs_handle handle;
  306. esp_err_t esp_err;
  307. ESP_LOGD(TAG, "About to save config to flash");
  308. if(wifi_manager_config_sta){
  309. esp_err = nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle);
  310. if (esp_err != ESP_OK) {
  311. ESP_LOGE(TAG, "Unable to open name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
  312. return esp_err;
  313. }
  314. esp_err = nvs_set_blob(handle, "ssid", wifi_manager_config_sta->sta.ssid, sizeof(wifi_manager_config_sta->sta.ssid));
  315. if (esp_err != ESP_OK) {
  316. ESP_LOGE(TAG, "Unable to save ssid in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
  317. return esp_err;
  318. }
  319. esp_err = nvs_set_blob(handle, "password", wifi_manager_config_sta->sta.password, sizeof(wifi_manager_config_sta->sta.password));
  320. if (esp_err != ESP_OK) {
  321. ESP_LOGE(TAG, "Unable to save password in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
  322. return esp_err;
  323. }
  324. // esp_err = nvs_set_blob(handle, "settings", &wifi_settings, sizeof(wifi_settings));
  325. // if (esp_err != ESP_OK) {
  326. // ESP_LOGE(TAG, "Unable to save wifi_settings in name namespace %s. Error %s", wifi_manager_nvs_namespace, esp_err_to_name(esp_err));
  327. // return esp_err;
  328. // }
  329. esp_err = nvs_commit(handle);
  330. if (esp_err != ESP_OK) {
  331. ESP_LOGE(TAG, "Unable to commit changes. Error %s", esp_err_to_name(esp_err));
  332. messaging_post_message(MESSAGING_ERROR,MESSAGING_CLASS_SYSTEM,"Unable to save wifi credentials. %s",esp_err_to_name(esp_err));
  333. return esp_err;
  334. }
  335. nvs_close(handle);
  336. 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);
  337. }
  338. return ESP_OK;
  339. }
  340. bool wifi_manager_fetch_wifi_sta_config(){
  341. nvs_handle handle;
  342. esp_err_t esp_err;
  343. ESP_LOGD(TAG, "Fetching wifi sta config.");
  344. esp_err=nvs_open(wifi_manager_nvs_namespace, NVS_READONLY, &handle);
  345. if(esp_err == ESP_OK){
  346. if(wifi_manager_config_sta == NULL){
  347. ESP_LOGD(TAG, "Allocating memory for structure.");
  348. wifi_manager_config_sta = (wifi_config_t*)malloc(sizeof(wifi_config_t));
  349. }
  350. memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
  351. /* ssid */
  352. ESP_LOGD(TAG, "Fetching value for ssid.");
  353. size_t sz = sizeof(wifi_manager_config_sta->sta.ssid);
  354. uint8_t *buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
  355. memset(buff,0x00,sizeof(uint8_t) * sz);
  356. esp_err = nvs_get_blob(handle, "ssid", buff, &sz);
  357. if(esp_err != ESP_OK){
  358. ESP_LOGD(TAG, "No ssid found in nvs.");
  359. FREE_AND_NULL(buff);
  360. nvs_close(handle);
  361. return false;
  362. }
  363. memcpy(wifi_manager_config_sta->sta.ssid, buff, sizeof(wifi_manager_config_sta->sta.ssid));
  364. FREE_AND_NULL(buff);
  365. ESP_LOGD(TAG, "wifi_manager_fetch_wifi_sta_config: ssid:%s ",wifi_manager_config_sta->sta.ssid);
  366. /* password */
  367. sz = sizeof(wifi_manager_config_sta->sta.password);
  368. buff = (uint8_t*)malloc(sizeof(uint8_t) * sz);
  369. memset(buff,0x00,sizeof(uint8_t) * sz);
  370. esp_err = nvs_get_blob(handle, "password", buff, &sz);
  371. if(esp_err != ESP_OK){
  372. // Don't take this as an error. This could be an opened access point?
  373. ESP_LOGW(TAG, "No wifi password found in nvs");
  374. }
  375. else {
  376. memcpy(wifi_manager_config_sta->sta.password, buff, sizeof(wifi_manager_config_sta->sta.password));
  377. ESP_LOGD(TAG, "wifi_manager_fetch_wifi_sta_config: password:%s",wifi_manager_config_sta->sta.password);
  378. }
  379. FREE_AND_NULL(buff);
  380. nvs_close(handle);
  381. return wifi_manager_config_sta->sta.ssid[0] != '\0';
  382. }
  383. else{
  384. ESP_LOGW(TAG, "wifi manager has no previous configuration. %s",esp_err_to_name(esp_err));
  385. return false;
  386. }
  387. }
  388. cJSON * wifi_manager_get_new_json(cJSON **old){
  389. ESP_LOGV(TAG, "wifi_manager_get_new_json called");
  390. cJSON * root=*old;
  391. if(root!=NULL){
  392. cJSON_Delete(root);
  393. *old=NULL;
  394. }
  395. ESP_LOGV(TAG, "wifi_manager_get_new_json done");
  396. return cJSON_CreateObject();
  397. }
  398. cJSON * wifi_manager_get_new_array_json(cJSON **old){
  399. ESP_LOGV(TAG, "wifi_manager_get_new_array_json called");
  400. cJSON * root=*old;
  401. if(root!=NULL){
  402. cJSON_Delete(root);
  403. *old=NULL;
  404. }
  405. ESP_LOGV(TAG, "wifi_manager_get_new_array_json done");
  406. return cJSON_CreateArray();
  407. }
  408. void wifi_manager_update_basic_info(){
  409. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  410. monitor_gpio_t *mgpio= get_jack_insertion_gpio();
  411. cJSON * voltage = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Voltage");
  412. if(voltage){
  413. cJSON_SetNumberValue(voltage, battery_value_svc());
  414. }
  415. cJSON * bt_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_status");
  416. if(bt_status){
  417. cJSON_SetNumberValue(bt_status, bt_app_source_get_a2d_state());
  418. }
  419. cJSON * bt_sub_status = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "bt_sub_status");
  420. if(bt_sub_status){
  421. cJSON_SetNumberValue(bt_sub_status, bt_app_source_get_media_state());
  422. }
  423. cJSON * jack = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "Jack");
  424. if(jack){
  425. jack->type=mgpio->gpio>=0 && jack_inserted_svc()?cJSON_True:cJSON_False;
  426. }
  427. cJSON * disconnect_count = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "disconnect_count");
  428. if(disconnect_count){
  429. cJSON_SetNumberValue(disconnect_count, num_disconnect);
  430. }
  431. cJSON * avg_conn_time = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "avg_conn_time");
  432. if(avg_conn_time){
  433. cJSON_SetNumberValue(avg_conn_time, num_disconnect>0?(total_connected_time/num_disconnect):0);
  434. }
  435. if(lms_server_cport>0){
  436. cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_cport");
  437. if(value){
  438. cJSON_SetNumberValue(value,lms_server_cport);
  439. }
  440. else {
  441. cJSON_AddNumberToObject(ip_info_cjson,"lms_cport",lms_server_cport);
  442. }
  443. }
  444. if(lms_server_port>0){
  445. cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_port");
  446. if(value){
  447. cJSON_SetNumberValue(value,lms_server_port);
  448. }
  449. else {
  450. cJSON_AddNumberToObject(ip_info_cjson,"lms_port",lms_server_port);
  451. }
  452. }
  453. if(strlen(lms_server_ip) >0){
  454. cJSON * value = cJSON_GetObjectItemCaseSensitive(ip_info_cjson, "lms_ip");
  455. if(!value){
  456. // only create if it does not exist. Since we're creating a reference
  457. // to a char buffer, updates to cJSON aren't needed
  458. cJSON_AddItemToObject(ip_info_cjson, "lms_ip", cJSON_CreateStringReference(lms_server_ip));
  459. }
  460. }
  461. wifi_manager_unlock_json_buffer();
  462. }
  463. }
  464. cJSON * wifi_manager_get_basic_info(cJSON **old){
  465. monitor_gpio_t *mgpio= get_jack_insertion_gpio();
  466. const esp_app_desc_t* desc = esp_ota_get_app_description();
  467. ESP_LOGV(TAG, "wifi_manager_get_basic_info called");
  468. cJSON *root = wifi_manager_get_new_json(old);
  469. cJSON_AddItemToObject(root, "project_name", cJSON_CreateString(desc->project_name));
  470. #ifdef CONFIG_FW_PLATFORM_NAME
  471. cJSON_AddItemToObject(root, "platform_name", cJSON_CreateString(CONFIG_FW_PLATFORM_NAME));
  472. #endif
  473. cJSON_AddItemToObject(root, "version", cJSON_CreateString(desc->version));
  474. if(release_url !=NULL) cJSON_AddItemToObject(root, "release_url", cJSON_CreateString(release_url));
  475. cJSON_AddNumberToObject(root,"recovery", is_recovery_running?1:0);
  476. cJSON_AddBoolToObject(root, "Jack", mgpio->gpio>=0 && jack_inserted_svc() );
  477. cJSON_AddNumberToObject(root,"Voltage", battery_value_svc());
  478. cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect );
  479. cJSON_AddNumberToObject(root,"avg_conn_time", num_disconnect>0?(total_connected_time/num_disconnect):0 );
  480. cJSON_AddNumberToObject(root,"bt_status", bt_app_source_get_a2d_state());
  481. cJSON_AddNumberToObject(root,"bt_sub_status", bt_app_source_get_media_state());
  482. #if CONFIG_I2C_LOCKED
  483. cJSON_AddTrueToObject(root, "is_i2c_locked");
  484. #else
  485. cJSON_AddFalseToObject(root, "is_i2c_locked");
  486. #endif
  487. ESP_LOGV(TAG, "wifi_manager_get_basic_info done");
  488. return root;
  489. }
  490. cJSON * wifi_manager_clear_ip_info_json(cJSON **old){
  491. ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json called");
  492. cJSON *root = wifi_manager_get_basic_info(old);
  493. ESP_LOGV(TAG, "wifi_manager_clear_ip_info_json done");
  494. return root;
  495. }
  496. cJSON * wifi_manager_clear_ap_list_json(cJSON **old){
  497. ESP_LOGV(TAG, "wifi_manager_clear_ap_list_json called");
  498. cJSON *root = wifi_manager_get_new_array_json(old);
  499. ESP_LOGV(TAG, "wifi_manager_clear_ap_list_json done");
  500. return root;
  501. }
  502. void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code){
  503. ESP_LOGD(TAG, "wifi_manager_generate_ip_info_json called");
  504. wifi_config_t *config = wifi_manager_get_wifi_sta_config();
  505. ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson);
  506. cJSON_AddNumberToObject(ip_info_cjson, "urc", update_reason_code);
  507. if(config){
  508. if(update_reason_code == UPDATE_CONNECTION_OK || update_reason_code == UPDATE_LOST_CONNECTION || update_reason_code == UPDATE_FAILED_ATTEMPT){
  509. cJSON_AddItemToObject(ip_info_cjson, "ssid", cJSON_CreateString((char *)config->sta.ssid));
  510. }
  511. if(update_reason_code == UPDATE_CONNECTION_OK){
  512. /* rest of the information is copied after the ssid */
  513. tcpip_adapter_ip_info_t ip_info;
  514. ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
  515. cJSON_AddItemToObject(ip_info_cjson, "ip", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.ip)));
  516. cJSON_AddItemToObject(ip_info_cjson, "netmask", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.netmask)));
  517. cJSON_AddItemToObject(ip_info_cjson, "gw", cJSON_CreateString(ip4addr_ntoa((ip4_addr_t *)&ip_info.gw)));
  518. wifi_ap_record_t ap;
  519. esp_wifi_sta_get_ap_info(&ap);
  520. cJSON_AddItemToObject(ip_info_cjson, "rssi", cJSON_CreateNumber(ap.rssi));
  521. }
  522. }
  523. ESP_LOGV(TAG, "wifi_manager_generate_ip_info_json done");
  524. }
  525. #define LOCAL_MAC_SIZE 20
  526. char * get_mac_string(uint8_t mac[6]){
  527. char * macStr=malloc(LOCAL_MAC_SIZE);
  528. memset(macStr, 0x00, LOCAL_MAC_SIZE);
  529. snprintf(macStr, LOCAL_MAC_SIZE,MACSTR, MAC2STR(mac));
  530. return macStr;
  531. }
  532. void wifi_manager_generate_access_points_json(cJSON ** ap_list){
  533. *ap_list = wifi_manager_get_new_array_json(ap_list);
  534. if(*ap_list==NULL) return;
  535. for(int i=0; i<ap_num;i++){
  536. cJSON * ap = cJSON_CreateObject();
  537. if(ap == NULL) {
  538. ESP_LOGE(TAG, "Unable to allocate memory for access point entry #%d",i);
  539. return;
  540. }
  541. cJSON * radio = cJSON_CreateObject();
  542. if(radio == NULL) {
  543. ESP_LOGE(TAG, "Unable to allocate memory for access point entry #%d",i);
  544. cJSON_Delete(ap);
  545. return;
  546. }
  547. wifi_ap_record_t ap_rec = accessp_records[i];
  548. cJSON_AddNumberToObject(ap, "chan", ap_rec.primary);
  549. cJSON_AddNumberToObject(ap, "rssi", ap_rec.rssi);
  550. cJSON_AddNumberToObject(ap, "auth", ap_rec.authmode);
  551. cJSON_AddItemToObject(ap, "ssid", cJSON_CreateString((char *)ap_rec.ssid));
  552. char * bssid = get_mac_string(ap_rec.bssid);
  553. cJSON_AddItemToObject(ap, "bssid", cJSON_CreateString(STR_OR_BLANK(bssid)));
  554. FREE_AND_NULL(bssid);
  555. cJSON_AddNumberToObject(radio, "b", ap_rec.phy_11b?1:0);
  556. cJSON_AddNumberToObject(radio, "g", ap_rec.phy_11g?1:0);
  557. cJSON_AddNumberToObject(radio, "n", ap_rec.phy_11n?1:0);
  558. cJSON_AddNumberToObject(radio, "low_rate", ap_rec.phy_lr?1:0);
  559. cJSON_AddItemToObject(ap,"radio", radio);
  560. cJSON_AddItemToArray(*ap_list, ap);
  561. char * ap_json = cJSON_PrintUnformatted(ap);
  562. if(ap_json!=NULL){
  563. ESP_LOGD(TAG, "New access point found: %s", ap_json);
  564. free(ap_json);
  565. }
  566. }
  567. char * ap_list_json = cJSON_PrintUnformatted(*ap_list);
  568. if(ap_list_json!=NULL){
  569. ESP_LOGV(TAG, "Full access point list: %s", ap_list_json);
  570. free(ap_list_json);
  571. }
  572. }
  573. bool wifi_manager_lock_sta_ip_string(TickType_t xTicksToWait){
  574. if(wifi_manager_sta_ip_mutex){
  575. if( xSemaphoreTake( wifi_manager_sta_ip_mutex, xTicksToWait ) == pdTRUE ) {
  576. return true;
  577. }
  578. else{
  579. return false;
  580. }
  581. }
  582. else{
  583. return false;
  584. }
  585. }
  586. void wifi_manager_unlock_sta_ip_string(){
  587. xSemaphoreGive( wifi_manager_sta_ip_mutex );
  588. }
  589. void wifi_manager_safe_update_sta_ip_string(struct ip4_addr * ip4){
  590. if(wifi_manager_lock_sta_ip_string(portMAX_DELAY)){
  591. strcpy(wifi_manager_sta_ip, ip4!=NULL?ip4addr_ntoa(ip4):"0.0.0.0");
  592. ESP_LOGD(TAG, "Set STA IP String to: %s", wifi_manager_sta_ip);
  593. wifi_manager_unlock_sta_ip_string();
  594. }
  595. }
  596. char* wifi_manager_get_sta_ip_string(){
  597. return wifi_manager_sta_ip;
  598. }
  599. bool wifi_manager_lock_json_buffer(TickType_t xTicksToWait){
  600. ESP_LOGV(TAG, "Locking json buffer");
  601. if(wifi_manager_json_mutex){
  602. if( xSemaphoreTake( wifi_manager_json_mutex, xTicksToWait ) == pdTRUE ) {
  603. ESP_LOGV(TAG, "Json buffer locked!");
  604. return true;
  605. }
  606. else{
  607. ESP_LOGE(TAG, "Semaphore take failed. Unable to lock json buffer mutex");
  608. return false;
  609. }
  610. }
  611. else{
  612. ESP_LOGV(TAG, "Unable to lock json buffer mutex");
  613. return false;
  614. }
  615. }
  616. void wifi_manager_unlock_json_buffer(){
  617. ESP_LOGV(TAG, "Unlocking json buffer!");
  618. xSemaphoreGive( wifi_manager_json_mutex );
  619. }
  620. char* wifi_manager_alloc_get_ap_list_json(){
  621. return cJSON_PrintUnformatted(accessp_cjson);
  622. }
  623. static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){
  624. if(event_base== WIFI_EVENT){
  625. switch(event_id) {
  626. case WIFI_EVENT_WIFI_READY:
  627. ESP_LOGD(TAG, "WIFI_EVENT_WIFI_READY");
  628. break;
  629. case WIFI_EVENT_SCAN_DONE:
  630. ESP_LOGD(TAG, "WIFI_EVENT_SCAN_DONE");
  631. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);
  632. wifi_manager_send_message(EVENT_SCAN_DONE, NULL);
  633. break;
  634. case WIFI_EVENT_STA_AUTHMODE_CHANGE:
  635. ESP_LOGD(TAG, "WIFI_EVENT_STA_AUTHMODE_CHANGE");
  636. // structwifi_event_sta_authmode_change_t
  637. // Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event
  638. //
  639. // Public Members
  640. //
  641. // wifi_auth_mode_told_mode
  642. // the old auth mode of AP
  643. //
  644. // wifi_auth_mode_tnew_mode
  645. // the new auth mode of AP
  646. break;
  647. case WIFI_EVENT_AP_START:
  648. ESP_LOGD(TAG, "WIFI_EVENT_AP_START");
  649. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STARTED_BIT);
  650. break;
  651. case WIFI_EVENT_AP_STOP:
  652. ESP_LOGD(TAG, "WIFI_EVENT_AP_STOP");
  653. break;
  654. case WIFI_EVENT_AP_PROBEREQRECVED:{
  655. // wifi_event_ap_probe_req_rx_t
  656. // Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event
  657. //
  658. // Public Members
  659. //
  660. // int rssi
  661. // Received probe request signal strength
  662. //
  663. // uint8_t mac[6]
  664. // MAC address of the station which send probe request
  665. wifi_event_ap_probe_req_rx_t * s =(wifi_event_ap_probe_req_rx_t*)event_data;
  666. char * mac = get_mac_string(s->mac);
  667. ESP_LOGD(TAG, "WIFI_EVENT_AP_PROBEREQRECVED. RSSI: %d, MAC: %s",s->rssi, STR_OR_BLANK(mac));
  668. FREE_AND_NULL(mac);
  669. }
  670. break;
  671. case WIFI_EVENT_STA_WPS_ER_SUCCESS:
  672. ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_SUCCESS");
  673. break;
  674. case WIFI_EVENT_STA_WPS_ER_FAILED:
  675. ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_FAILED");
  676. break;
  677. case WIFI_EVENT_STA_WPS_ER_TIMEOUT:
  678. ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_TIMEOUT");
  679. break;
  680. case WIFI_EVENT_STA_WPS_ER_PIN:
  681. ESP_LOGD(TAG, "WIFI_EVENT_STA_WPS_ER_PIN");
  682. break;
  683. case WIFI_EVENT_AP_STACONNECTED:{ /* a user disconnected from the SoftAP */
  684. wifi_event_ap_staconnected_t * stac = (wifi_event_ap_staconnected_t *)event_data;
  685. char * mac = get_mac_string(stac->mac);
  686. ESP_LOGD(TAG, "WIFI_EVENT_AP_STACONNECTED. aid: %d, mac: %s",stac->aid,STR_OR_BLANK(mac));
  687. FREE_AND_NULL(mac);
  688. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT);
  689. }
  690. break;
  691. case WIFI_EVENT_AP_STADISCONNECTED:
  692. ESP_LOGD(TAG, "WIFI_EVENT_AP_STADISCONNECTED");
  693. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_AP_STA_CONNECTED_BIT);
  694. break;
  695. case WIFI_EVENT_STA_START:
  696. ESP_LOGD(TAG, "WIFI_EVENT_STA_START");
  697. break;
  698. case WIFI_EVENT_STA_STOP:
  699. ESP_LOGD(TAG, "WIFI_EVENT_STA_STOP");
  700. break;
  701. case WIFI_EVENT_STA_CONNECTED:{
  702. // structwifi_event_sta_connected_t
  703. // Argument structure for WIFI_EVENT_STA_CONNECTED event
  704. //
  705. // Public Members
  706. //
  707. // uint8_t ssid[32]
  708. // SSID of connected AP
  709. //
  710. // uint8_t ssid_len
  711. // SSID length of connected AP
  712. //
  713. // uint8_t bssid[6]
  714. // BSSID of connected AP
  715. //
  716. // uint8_t channel
  717. // channel of connected AP
  718. //
  719. // wifi_auth_mode_tauthmode
  720. // authentication mode used by AP
  721. //, get_mac_string(EVENT_HANDLER_ARG_FIELD(wifi_event_ap_probe_req_rx_t, mac)));
  722. ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. ");
  723. wifi_event_sta_connected_t * s =(wifi_event_sta_connected_t*)event_data;
  724. char * bssid = get_mac_string(s->bssid);
  725. char * ssid = strdup((char*)s->ssid);
  726. ESP_LOGD(TAG, "WIFI_EVENT_STA_CONNECTED. Channel: %d, Access point: %s, BSSID: %s ", s->channel, STR_OR_BLANK(ssid), (bssid));
  727. FREE_AND_NULL(bssid);
  728. FREE_AND_NULL(ssid);
  729. }
  730. break;
  731. case WIFI_EVENT_STA_DISCONNECTED:{
  732. // structwifi_event_sta_disconnected_t
  733. // Argument structure for WIFI_EVENT_STA_DISCONNECTED event
  734. //
  735. // Public Members
  736. //
  737. // uint8_t ssid[32]
  738. // SSID of disconnected AP
  739. //
  740. // uint8_t ssid_len
  741. // SSID length of disconnected AP
  742. //
  743. // uint8_t bssid[6]
  744. // BSSID of disconnected AP
  745. //
  746. // uint8_t reason
  747. // reason of disconnection
  748. wifi_event_sta_disconnected_t * s =(wifi_event_sta_disconnected_t*)event_data;
  749. char * bssid = get_mac_string(s->bssid);
  750. ESP_LOGD(TAG, "WIFI_EVENT_STA_DISCONNECTED. From BSSID: %s, reason code: %d (%s)", STR_OR_BLANK(bssid),s->reason, get_disconnect_code_desc(s->reason));
  751. FREE_AND_NULL(bssid);
  752. if(last_connected>0) total_connected_time+=((esp_timer_get_time()-last_connected)/(1000*1000));
  753. last_connected = 0;
  754. num_disconnect++;
  755. ESP_LOGW(TAG, "Wifi disconnected. Number of disconnects: %d, Average time connected: %d", num_disconnect, num_disconnect>0?(total_connected_time/num_disconnect):0);
  756. /* 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 */
  757. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT | WIFI_MANAGER_SCAN_BIT);
  758. // We want to process this message asynchronously, so make sure we copy the event buffer
  759. ESP_LOGD(TAG, "Preparing to trigger event EVENT_STA_DISCONNECTED ");
  760. void * parm=malloc(sizeof(wifi_event_sta_disconnected_t));
  761. memcpy(parm,event_data,sizeof(wifi_event_sta_disconnected_t));
  762. ESP_LOGD(TAG, "Triggering EVENT_STA_DISCONNECTED ");
  763. /* post disconnect event with reason code */
  764. wifi_manager_send_message(EVENT_STA_DISCONNECTED, parm );
  765. }
  766. break;
  767. default:
  768. break;
  769. }
  770. }
  771. else if(event_base== IP_EVENT){
  772. switch (event_id) {
  773. case IP_EVENT_STA_GOT_IP:{
  774. // structip_event_got_ip_t
  775. // tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */
  776. // tcpip_adapter_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
  777. // // Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events
  778. //
  779. // Public Members
  780. //
  781. // tcpip_adapter_if_tif_index
  782. // Interface for which the event is received
  783. //
  784. // tcpip_adapter_ip_info_t ip_info
  785. // IP address, netmask, gatway IP address
  786. //
  787. // bool ip_changed
  788. // Whether the assigned IP has changed or not
  789. ip_event_got_ip_t * s =(ip_event_got_ip_t*)event_data;
  790. //tcpip_adapter_if_t index = s->if_index;
  791. const tcpip_adapter_ip_info_t *ip_info = &s->ip_info;
  792. ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP. IP="IPSTR", Gateway="IPSTR", NetMask="IPSTR", %s",
  793. IP2STR(&ip_info->ip),
  794. IP2STR(&ip_info->gw),
  795. IP2STR(&ip_info->netmask),
  796. s->ip_changed?"Address was changed":"Address unchanged");
  797. // todo: if ip address was changed, we probably need to restart, as all sockets
  798. // will become abnormal
  799. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_WIFI_CONNECTED_BIT);
  800. last_connected = esp_timer_get_time();
  801. void * parm=malloc(sizeof(ip_event_got_ip_t));
  802. memcpy(parm,event_data,sizeof(ip_event_got_ip_t));
  803. wifi_manager_send_message(EVENT_STA_GOT_IP, parm );
  804. }
  805. break;
  806. case IP_EVENT_STA_LOST_IP:
  807. ESP_LOGD(TAG, "IP_EVENT_STA_LOST_IP");
  808. break;
  809. case IP_EVENT_AP_STAIPASSIGNED:
  810. ESP_LOGD(TAG, "IP_EVENT_AP_STAIPASSIGNED");
  811. break;
  812. case IP_EVENT_GOT_IP6:
  813. ESP_LOGD(TAG, "IP_EVENT_GOT_IP6");
  814. break;
  815. case IP_EVENT_ETH_GOT_IP:
  816. ESP_LOGD(TAG, "IP_EVENT_ETH_GOT_IP");
  817. break;
  818. default:
  819. break;
  820. }
  821. }
  822. }
  823. wifi_config_t* wifi_manager_get_wifi_sta_config(){
  824. return wifi_manager_config_sta;
  825. }
  826. void wifi_manager_connect_async(){
  827. /* in order to avoid a false positive on the front end app we need to quickly flush the ip json
  828. * There'se a risk the front end sees an IP or a password error when in fact
  829. * it's a remnant from a previous connection
  830. */
  831. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  832. ip_info_cjson= wifi_manager_clear_ip_info_json(&ip_info_cjson);
  833. wifi_manager_unlock_json_buffer();
  834. }
  835. wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_USER);
  836. }
  837. char* wifi_manager_alloc_get_ip_info_json(){
  838. return cJSON_PrintUnformatted(ip_info_cjson);
  839. }
  840. void wifi_manager_destroy(){
  841. vTaskDelete(task_wifi_manager);
  842. task_wifi_manager = NULL;
  843. /* heap buffers */
  844. free(ip_info_json);
  845. free(release_url);
  846. cJSON_Delete(ip_info_cjson);
  847. cJSON_Delete(accessp_cjson);
  848. ip_info_cjson=NULL;
  849. accessp_cjson=NULL;
  850. free(wifi_manager_sta_ip);
  851. wifi_manager_sta_ip = NULL;
  852. if(wifi_manager_config_sta){
  853. free(wifi_manager_config_sta);
  854. wifi_manager_config_sta = NULL;
  855. }
  856. /* RTOS objects */
  857. vSemaphoreDelete(wifi_manager_json_mutex);
  858. wifi_manager_json_mutex = NULL;
  859. vSemaphoreDelete(wifi_manager_sta_ip_mutex);
  860. wifi_manager_sta_ip_mutex = NULL;
  861. vEventGroupDelete(wifi_manager_event_group);
  862. wifi_manager_event_group = NULL;
  863. vQueueDelete(wifi_manager_queue);
  864. wifi_manager_queue = NULL;
  865. }
  866. void wifi_manager_filter_unique( wifi_ap_record_t * aplist, uint16_t * aps) {
  867. int total_unique;
  868. wifi_ap_record_t * first_free;
  869. total_unique=*aps;
  870. first_free=NULL;
  871. for(int i=0; i<*aps-1;i++) {
  872. wifi_ap_record_t * ap = &aplist[i];
  873. /* skip the previously removed APs */
  874. if (ap->ssid[0] == 0) continue;
  875. /* remove the identical SSID+authmodes */
  876. for(int j=i+1; j<*aps;j++) {
  877. wifi_ap_record_t * ap1 = &aplist[j];
  878. if ( (strcmp((const char *)ap->ssid, (const char *)ap1->ssid)==0) &&
  879. (ap->authmode == ap1->authmode) ) { /* same SSID, different auth mode is skipped */
  880. /* save the rssi for the display */
  881. if ((ap1->rssi) > (ap->rssi)) ap->rssi=ap1->rssi;
  882. /* clearing the record */
  883. memset(ap1,0, sizeof(wifi_ap_record_t));
  884. }
  885. }
  886. }
  887. /* reorder the list so APs follow each other in the list */
  888. for(int i=0; i<*aps;i++) {
  889. wifi_ap_record_t * ap = &aplist[i];
  890. /* skipping all that has no name */
  891. if (ap->ssid[0] == 0) {
  892. /* mark the first free slot */
  893. if (first_free==NULL) first_free=ap;
  894. total_unique--;
  895. continue;
  896. }
  897. if (first_free!=NULL) {
  898. memcpy(first_free, ap, sizeof(wifi_ap_record_t));
  899. memset(ap,0, sizeof(wifi_ap_record_t));
  900. /* find the next free slot */
  901. for(int j=0; j<*aps;j++) {
  902. if (aplist[j].ssid[0]==0) {
  903. first_free=&aplist[j];
  904. break;
  905. }
  906. }
  907. }
  908. }
  909. /* update the length of the list */
  910. *aps = total_unique;
  911. }
  912. BaseType_t wifi_manager_send_message_to_front(message_code_t code, void *param){
  913. queue_message msg;
  914. msg.code = code;
  915. msg.param = param;
  916. return xQueueSendToFront( wifi_manager_queue, &msg, portMAX_DELAY);
  917. }
  918. BaseType_t wifi_manager_send_message(message_code_t code, void *param){
  919. queue_message msg;
  920. msg.code = code;
  921. msg.param = param;
  922. return xQueueSend( wifi_manager_queue, &msg, portMAX_DELAY);
  923. }
  924. void wifi_manager_set_callback(message_code_t message_code, void (*func_ptr)(void*) ){
  925. if(cb_ptr_arr && message_code < MESSAGE_CODE_COUNT){
  926. cb_ptr_arr[message_code] = func_ptr;
  927. }
  928. }
  929. void wifi_manager_register_handlers(){
  930. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_WIFI_READY, &event_handler, NULL));
  931. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_SCAN_DONE, &event_handler, NULL));
  932. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_AUTHMODE_CHANGE, &event_handler, NULL));
  933. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, &event_handler, NULL));
  934. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STOP, &event_handler, NULL));
  935. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_PROBEREQRECVED, &event_handler, NULL));
  936. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &event_handler, NULL));
  937. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &event_handler, NULL));
  938. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_TIMEOUT, &event_handler, NULL));
  939. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &event_handler, NULL));
  940. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STACONNECTED, &event_handler, NULL ));
  941. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STADISCONNECTED, &event_handler, NULL));
  942. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, &event_handler, NULL));
  943. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, &event_handler, NULL));
  944. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, &event_handler, NULL));
  945. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &event_handler, NULL));
  946. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
  947. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_LOST_IP, &event_handler, NULL));
  948. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &event_handler, NULL));
  949. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &event_handler, NULL));
  950. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &event_handler, NULL));
  951. }
  952. void wifi_manager_config_ap(){
  953. /* SoftAP - Wifi Access Point configuration setup */
  954. tcpip_adapter_ip_info_t info;
  955. esp_err_t err=ESP_OK;
  956. memset(&info, 0x00, sizeof(info));
  957. char * value = NULL;
  958. wifi_config_t ap_config = {
  959. .ap = {
  960. .ssid_len = 0,
  961. },
  962. };
  963. ESP_LOGI(TAG, "Configuring Access Point.");
  964. ESP_LOGD(TAG,"Stopping DHCP on interface ");
  965. if((err= tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP))!=ESP_OK) /* stop AP DHCP server */
  966. {
  967. ESP_LOGW(TAG, "Stopping DHCP failed. Error %s",esp_err_to_name(err));
  968. }
  969. /*
  970. * Set access point mode IP adapter configuration
  971. */
  972. value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_address", DEFAULT_AP_IP, 0);
  973. if(value!=NULL){
  974. ESP_LOGD(TAG, "IP Address: %s", value);
  975. inet_pton(AF_INET,value, &info.ip); /* access point is on a static IP */
  976. }
  977. FREE_AND_NULL(value);
  978. value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_gateway", CONFIG_DEFAULT_AP_GATEWAY, 0);
  979. if(value!=NULL){
  980. ESP_LOGD(TAG, "Gateway: %s", value);
  981. inet_pton(AF_INET,value, &info.gw); /* access point is on a static IP */
  982. }
  983. FREE_AND_NULL(value);
  984. value = config_alloc_get_default(NVS_TYPE_STR, "ap_ip_netmask", CONFIG_DEFAULT_AP_NETMASK, 0);
  985. if(value!=NULL){
  986. ESP_LOGD(TAG, "Netmask: %s", value);
  987. inet_pton(AF_INET,value, &info.netmask); /* access point is on a static IP */
  988. }
  989. FREE_AND_NULL(value);
  990. ESP_LOGD(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP");
  991. if((err=tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info))!=ESP_OK){
  992. ESP_LOGE(TAG, "Setting tcp_ip info for interface TCPIP_ADAPTER_IF_AP. Error %s",esp_err_to_name(err));
  993. return;
  994. }
  995. /*
  996. * Set Access Point configuration
  997. */
  998. value = config_alloc_get_default(NVS_TYPE_STR, "ap_ssid", CONFIG_DEFAULT_AP_SSID, 0);
  999. if(value!=NULL){
  1000. strlcpy((char *)ap_config.ap.ssid, value,sizeof(ap_config.ap.ssid) );
  1001. ESP_LOGI(TAG, "AP SSID: %s", (char *)ap_config.ap.ssid);
  1002. }
  1003. FREE_AND_NULL(value);
  1004. value = config_alloc_get_default(NVS_TYPE_STR, "ap_pwd", DEFAULT_AP_PASSWORD, 0);
  1005. if(value!=NULL){
  1006. strlcpy((char *)ap_config.ap.password, value,sizeof(ap_config.ap.password) );
  1007. ESP_LOGI(TAG, "AP Password: %s", (char *)ap_config.ap.password);
  1008. }
  1009. FREE_AND_NULL(value);
  1010. value = config_alloc_get_default(NVS_TYPE_STR, "ap_channel", STR(CONFIG_DEFAULT_AP_CHANNEL), 0);
  1011. if(value!=NULL){
  1012. ESP_LOGD(TAG, "Channel: %s", value);
  1013. ap_config.ap.channel=atoi(value);
  1014. }
  1015. FREE_AND_NULL(value);
  1016. ap_config.ap.authmode = AP_AUTHMODE;
  1017. ap_config.ap.ssid_hidden = DEFAULT_AP_SSID_HIDDEN;
  1018. ap_config.ap.max_connection = DEFAULT_AP_MAX_CONNECTIONS;
  1019. ap_config.ap.beacon_interval = DEFAULT_AP_BEACON_INTERVAL;
  1020. ESP_LOGD(TAG, "Auth Mode: %d", ap_config.ap.authmode);
  1021. ESP_LOGD(TAG, "SSID Hidden: %d", ap_config.ap.ssid_hidden);
  1022. ESP_LOGD(TAG, "Max Connections: %d", ap_config.ap.max_connection);
  1023. ESP_LOGD(TAG, "Beacon interval: %d", ap_config.ap.beacon_interval);
  1024. ESP_LOGD(TAG, "");
  1025. if((err= esp_wifi_set_mode(WIFI_MODE_APSTA))!=ESP_OK) /* stop AP DHCP server */
  1026. {
  1027. ESP_LOGE(TAG, "Setting wifi mode as WIFI_MODE_APSTA failed. Error %s",esp_err_to_name(err));
  1028. return;
  1029. }
  1030. ESP_LOGD(TAG, "Setting wifi AP configuration for WIFI_IF_AP");
  1031. if((err= esp_wifi_set_config(WIFI_IF_AP, &ap_config))!=ESP_OK) /* stop AP DHCP server */
  1032. {
  1033. ESP_LOGE(TAG, "Setting wifi AP configuration for WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
  1034. return;
  1035. }
  1036. ESP_LOGD(TAG, "Setting wifi bandwidth (%d) for WIFI_IF_AP",DEFAULT_AP_BANDWIDTH);
  1037. if((err=esp_wifi_set_bandwidth(WIFI_IF_AP, DEFAULT_AP_BANDWIDTH))!=ESP_OK) /* stop AP DHCP server */
  1038. {
  1039. ESP_LOGE(TAG, "Setting wifi bandwidth for WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
  1040. return;
  1041. }
  1042. ESP_LOGD(TAG, "Setting wifi power save (%d) for WIFI_IF_AP",DEFAULT_STA_POWER_SAVE);
  1043. if((err=esp_wifi_set_ps(DEFAULT_STA_POWER_SAVE))!=ESP_OK) /* stop AP DHCP server */
  1044. {
  1045. ESP_LOGE(TAG, "Setting wifi power savefor WIFI_IF_AP failed. Error %s",esp_err_to_name(err));
  1046. return;
  1047. }
  1048. ESP_LOGD(TAG, "Starting dhcps on interface TCPIP_ADAPTER_IF_AP");
  1049. if((err=tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP))!=ESP_OK) /* stop AP DHCP server */
  1050. {
  1051. ESP_LOGE(TAG, "Starting dhcp on TCPIP_ADAPTER_IF_AP failed. Error %s",esp_err_to_name(err));
  1052. return;
  1053. }
  1054. ESP_LOGD(TAG, "Done configuring Soft Access Point");
  1055. dns_server_start();
  1056. }
  1057. void wifi_manager( void * pvParameters ){
  1058. queue_message msg;
  1059. BaseType_t xStatus;
  1060. EventBits_t uxBits;
  1061. uint8_t retries = 0;
  1062. esp_err_t err=ESP_OK;
  1063. TimerHandle_t STA_timer;
  1064. uint32_t STA_duration = STA_POLLING_MIN;
  1065. /* create timer for background STA connection */
  1066. STA_timer = xTimerCreate("background STA", pdMS_TO_TICKS(STA_duration), pdFALSE, NULL, polling_STA);
  1067. /* start http server */
  1068. http_server_start();
  1069. /* enqueue first event: load previous config and start AP or STA mode */
  1070. wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
  1071. /* main processing loop */
  1072. for(;;){
  1073. xStatus = xQueueReceive( wifi_manager_queue, &msg, portMAX_DELAY );
  1074. if( xStatus == pdPASS ){
  1075. switch(msg.code){
  1076. case EVENT_SCAN_DONE:
  1077. /* As input param, it stores max AP number ap_records can hold. As output param, it receives the actual AP number this API returns.
  1078. * As a consequence, ap_num MUST be reset to MAX_AP_NUM at every scan */
  1079. ESP_LOGD(TAG, "Getting AP list records");
  1080. if((err=esp_wifi_scan_get_ap_num(&ap_num))!=ESP_OK) {
  1081. ESP_LOGE(TAG, "Failed to retrieve scan results count. Error %s",esp_err_to_name(err));
  1082. break;
  1083. }
  1084. if(ap_num>0){
  1085. accessp_records = (wifi_ap_record_t*)malloc(sizeof(wifi_ap_record_t) * ap_num);
  1086. if((err=esp_wifi_scan_get_ap_records(&ap_num, accessp_records))!=ESP_OK) {
  1087. ESP_LOGE(TAG, "Failed to retrieve scan results list. Error %s",esp_err_to_name(err));
  1088. break;
  1089. }
  1090. /* make sure the http server isn't trying to access the list while it gets refreshed */
  1091. ESP_LOGD(TAG, "Preparing to build ap JSON list");
  1092. if(wifi_manager_lock_json_buffer( pdMS_TO_TICKS(1000) )){
  1093. /* Will remove the duplicate SSIDs from the list and update ap_num */
  1094. wifi_manager_filter_unique(accessp_records, &ap_num);
  1095. wifi_manager_generate_access_points_json(&accessp_cjson);
  1096. wifi_manager_unlock_json_buffer();
  1097. ESP_LOGD(TAG, "Done building ap JSON list");
  1098. }
  1099. else{
  1100. ESP_LOGE(TAG, "could not get access to json mutex in wifi_scan");
  1101. }
  1102. free(accessp_records);
  1103. }
  1104. else{
  1105. //
  1106. ESP_LOGD(TAG, "No AP Found. Emptying the list.");
  1107. accessp_cjson = wifi_manager_get_new_array_json(&accessp_cjson);
  1108. }
  1109. /* callback */
  1110. if(cb_ptr_arr[msg.code]) {
  1111. ESP_LOGD(TAG, "Invoking SCAN DONE callback");
  1112. (*cb_ptr_arr[msg.code])(NULL);
  1113. ESP_LOGD(TAG, "Done Invoking SCAN DONE callback");
  1114. }
  1115. break;
  1116. case ORDER_START_WIFI_SCAN:
  1117. ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN");
  1118. /* if a scan is already in progress this message is simply ignored thanks to the WIFI_MANAGER_SCAN_BIT uxBit */
  1119. if(! isGroupBitSet(WIFI_MANAGER_SCAN_BIT) ){
  1120. if(esp_wifi_scan_start(&scan_config, false)!=ESP_OK){
  1121. ESP_LOGW(TAG, "Unable to start scan; wifi is trying to connect");
  1122. // set_status_message(WARNING, "Wifi Connecting. Cannot start scan.");
  1123. messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi connecting. Cannot start scan.");
  1124. }
  1125. else {
  1126. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_SCAN_BIT);
  1127. }
  1128. }
  1129. else {
  1130. ESP_LOGW(TAG, "Scan already in progress!");
  1131. }
  1132. /* callback */
  1133. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1134. break;
  1135. case ORDER_LOAD_AND_RESTORE_STA:
  1136. ESP_LOGD(TAG, "MESSAGE: ORDER_LOAD_AND_RESTORE_STA. About to fetch wifi STA configuration");
  1137. if(wifi_manager_fetch_wifi_sta_config()){
  1138. ESP_LOGI(TAG, "Saved wifi found on startup. Will attempt to connect.");
  1139. wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_RESTORE_CONNECTION);
  1140. }
  1141. else{
  1142. /* no wifi saved: start soft AP! This is what should happen during a first run */
  1143. ESP_LOGD(TAG, "No saved wifi found on startup. Starting access point.");
  1144. wifi_manager_send_message(ORDER_START_AP, NULL);
  1145. }
  1146. /* callback */
  1147. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1148. break;
  1149. case ORDER_CONNECT_STA:
  1150. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - Begin");
  1151. /* very important: precise that this connection attempt is specifically requested.
  1152. * Param in that case is a boolean indicating if the request was made automatically
  1153. * by the wifi_manager.
  1154. * */
  1155. if((BaseType_t)msg.param == CONNECTION_REQUEST_USER) {
  1156. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - Connection request with no nvs connection saved yet");
  1157. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
  1158. xEventGroupClearBits(wifi_manager_event_group,WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT);
  1159. }
  1160. else if((BaseType_t)msg.param == CONNECTION_REQUEST_RESTORE_CONNECTION) {
  1161. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - Connection request after restoring the AP configuration");
  1162. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
  1163. /* STA - Wifi Station configuration setup */
  1164. //todo: support static ip address
  1165. // if(wifi_settings.sta_static_ip) {
  1166. // // There's a static ip address configured, so
  1167. // ESP_LOGD(TAG, "Assigning static ip to STA interface. IP: %s , GW: %s , Mask: %s",
  1168. // ip4addr_ntoa(&wifi_settings.sta_static_ip_config.ip),
  1169. // ip4addr_ntoa(&wifi_settings.sta_static_ip_config.gw),
  1170. // ip4addr_ntoa(&wifi_settings.sta_static_ip_config.netmask));
  1171. //
  1172. // /* stop DHCP client*/
  1173. // ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));
  1174. // /* assign a static IP to the STA network interface */
  1175. // ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &wifi_settings.sta_static_ip_config));
  1176. // }
  1177. // else {
  1178. /* start DHCP client if not started*/
  1179. tcpip_adapter_dhcp_status_t status;
  1180. ESP_LOGD(TAG, "wifi_manager: Checking if DHCP client for STA interface is running");
  1181. ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status));
  1182. if (status!=TCPIP_ADAPTER_DHCP_STARTED) {
  1183. ESP_LOGD(TAG, "wifi_manager: Start DHCP client for STA interface");
  1184. ESP_ERROR_CHECK_WITHOUT_ABORT(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
  1185. }
  1186. //}
  1187. }
  1188. uxBits = xEventGroupGetBits(wifi_manager_event_group);
  1189. if( uxBits & WIFI_MANAGER_WIFI_CONNECTED_BIT ){
  1190. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - Wifi connected bit set, ordering disconnect (WIFI_MANAGER_WIFI_CONNECTED_BIT)");
  1191. wifi_manager_send_message(ORDER_DISCONNECT_STA, NULL);
  1192. /* todo: reconnect */
  1193. }
  1194. else{
  1195. wifi_mode_t mode;
  1196. /* update config to latest and attempt connection */
  1197. esp_wifi_get_mode(&mode);
  1198. if( WIFI_MODE_APSTA != mode && WIFI_MODE_STA !=mode ){
  1199. // the soft ap is not started, so let's set the WiFi mode to STA
  1200. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - setting mode WIFI_MODE_STA");
  1201. if((err=esp_wifi_set_mode(WIFI_MODE_STA))!=ESP_OK) {
  1202. ESP_LOGE(TAG, "Failed to set wifi mode to STA. Error %s",esp_err_to_name(err));
  1203. break;
  1204. }
  1205. }
  1206. ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - setting config for WIFI_IF_STA");
  1207. wifi_config_t* cfg = wifi_manager_get_wifi_sta_config();
  1208. char * scan_mode = config_alloc_get_default(NVS_TYPE_STR, "wifi_smode", "f", 0);
  1209. if (scan_mode && strcasecmp(scan_mode,"a")==0) {
  1210. cfg->sta.scan_method=WIFI_ALL_CHANNEL_SCAN;
  1211. }
  1212. else {
  1213. cfg->sta.scan_method=WIFI_FAST_SCAN;
  1214. }
  1215. FREE_AND_NULL(scan_mode);
  1216. if((err=esp_wifi_set_config(WIFI_IF_STA, cfg))!=ESP_OK) {
  1217. ESP_LOGE(TAG, "Failed to set STA configuration. Error %s",esp_err_to_name(err));
  1218. break;
  1219. }
  1220. set_host_name();
  1221. ESP_LOGI(TAG, "Wifi Connecting...");
  1222. if((err=esp_wifi_connect())!=ESP_OK) {
  1223. ESP_LOGE(TAG, "Failed to initiate wifi connection. Error %s",esp_err_to_name(err));
  1224. break;
  1225. }
  1226. }
  1227. /* callback */
  1228. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1229. break;
  1230. case EVENT_STA_DISCONNECTED:{
  1231. wifi_event_sta_disconnected_t disc_event;
  1232. ESP_LOGD(TAG, "MESSAGE: EVENT_STA_DISCONNECTED");
  1233. if(msg.param == NULL){
  1234. ESP_LOGE(TAG, "MESSAGE: EVENT_STA_DISCONNECTED - expected parameter not found!");
  1235. }
  1236. else{
  1237. memcpy(&disc_event,(wifi_event_sta_disconnected_t*)msg.param,sizeof(disc_event));
  1238. free(msg.param);
  1239. ESP_LOGD(TAG, "MESSAGE: EVENT_STA_DISCONNECTED with Reason code: %d (%s)", disc_event.reason, get_disconnect_code_desc(disc_event.reason));
  1240. }
  1241. /* this even can be posted in numerous different conditions
  1242. *
  1243. * 1. SSID password is wrong
  1244. * 2. Manual disconnection ordered
  1245. * 3. Connection lost
  1246. *
  1247. * Having clear understand as to WHY the event was posted is key to having an efficient wifi manager
  1248. *
  1249. * With wifi_manager, we determine:
  1250. * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, We consider it's a client that requested the connection.
  1251. * When SYSTEM_EVENT_STA_DISCONNECTED is posted, it's probably a password/something went wrong with the handshake.
  1252. *
  1253. * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT is set, it's a disconnection that was ASKED by the client (clicking disconnect in the app)
  1254. * When SYSTEM_EVENT_STA_DISCONNECTED is posted, saved wifi is erased from the NVS memory.
  1255. *
  1256. * If WIFI_MANAGER_REQUEST_STA_CONNECT_BIT and WIFI_MANAGER_REQUEST_STA_CONNECT_BIT are NOT set, it's a lost connection
  1257. *
  1258. * In this version of the software, reason codes are not used. They are indicated here for potential future usage.
  1259. *
  1260. * REASON CODE:
  1261. * 1 UNSPECIFIED
  1262. * 2 AUTH_EXPIRE auth no longer valid, this smells like someone changed a password on the AP
  1263. * 3 AUTH_LEAVE
  1264. * 4 ASSOC_EXPIRE
  1265. * 5 ASSOC_TOOMANY too many devices already connected to the AP => AP fails to respond
  1266. * 6 NOT_AUTHED
  1267. * 7 NOT_ASSOCED
  1268. * 8 ASSOC_LEAVE
  1269. * 9 ASSOC_NOT_AUTHED
  1270. * 10 DISASSOC_PWRCAP_BAD
  1271. * 11 DISASSOC_SUPCHAN_BAD
  1272. * 12 <n/a>
  1273. * 13 IE_INVALID
  1274. * 14 MIC_FAILURE
  1275. * 15 4WAY_HANDSHAKE_TIMEOUT wrong password! This was personnaly tested on my home wifi with a wrong password.
  1276. * 16 GROUP_KEY_UPDATE_TIMEOUT
  1277. * 17 IE_IN_4WAY_DIFFERS
  1278. * 18 GROUP_CIPHER_INVALID
  1279. * 19 PAIRWISE_CIPHER_INVALID
  1280. * 20 AKMP_INVALID
  1281. * 21 UNSUPP_RSN_IE_VERSION
  1282. * 22 INVALID_RSN_IE_CAP
  1283. * 23 802_1X_AUTH_FAILED wrong password?
  1284. * 24 CIPHER_SUITE_REJECTED
  1285. * 200 BEACON_TIMEOUT
  1286. * 201 NO_AP_FOUND
  1287. * 202 AUTH_FAIL
  1288. * 203 ASSOC_FAIL
  1289. * 204 HANDSHAKE_TIMEOUT
  1290. *
  1291. * */
  1292. /* reset saved sta IP */
  1293. wifi_manager_safe_update_sta_ip_string((struct ip4_addr * )0);
  1294. uxBits = xEventGroupGetBits(wifi_manager_event_group);
  1295. if( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_BIT ){
  1296. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
  1297. ESP_LOGW(TAG, "WiFi Disconnected while processing user connect request. Wrong password?");
  1298. /* there are no retries when it's a user requested connection by design. This avoids a user hanging too much
  1299. * in case they typed a wrong password for instance. Here we simply clear the request bit and move on */
  1300. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  1301. wifi_manager_generate_ip_info_json( UPDATE_FAILED_ATTEMPT );
  1302. wifi_manager_unlock_json_buffer();
  1303. }
  1304. wifi_mode_t mode;
  1305. esp_wifi_get_mode(&mode);
  1306. if( WIFI_MODE_STA ==mode ){
  1307. xEventGroupSetBits(wifi_manager_event_group,WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT);
  1308. // if wifi was STA, attempt to reload the previous network connection
  1309. ESP_LOGW(TAG,"Attempting to restore previous network");
  1310. wifi_manager_send_message(ORDER_LOAD_AND_RESTORE_STA, NULL);
  1311. }
  1312. }
  1313. else if (uxBits & WIFI_MANAGER_REQUEST_DISCONNECT_BIT){
  1314. ESP_LOGD(TAG, "WiFi disconnected by user");
  1315. /* user manually requested a disconnect so the lost connection is a normal event. Clear the flag and restart the AP */
  1316. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
  1317. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  1318. wifi_manager_generate_ip_info_json( UPDATE_USER_DISCONNECT );
  1319. wifi_manager_unlock_json_buffer();
  1320. }
  1321. /* erase configuration */
  1322. if(wifi_manager_config_sta){
  1323. ESP_LOGI(TAG, "Erasing WiFi Configuration.");
  1324. memset(wifi_manager_config_sta, 0x00, sizeof(wifi_config_t));
  1325. /* save NVS memory */
  1326. wifi_manager_save_sta_config();
  1327. }
  1328. /* start SoftAP */
  1329. ESP_LOGD(TAG, "Disconnect processing complete. Ordering an AP start.");
  1330. wifi_manager_send_message(ORDER_START_AP, NULL);
  1331. }
  1332. else{
  1333. /* lost connection ? */
  1334. ESP_LOGE(TAG, "WiFi Connection lost.");
  1335. messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"WiFi Connection lost");
  1336. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  1337. wifi_manager_generate_ip_info_json( UPDATE_LOST_CONNECTION );
  1338. wifi_manager_unlock_json_buffer();
  1339. }
  1340. if(retries < WIFI_MANAGER_MAX_RETRY){
  1341. ESP_LOGD(TAG, "Issuing ORDER_CONNECT_STA to retry connection.");
  1342. retries++;
  1343. wifi_manager_send_message(ORDER_CONNECT_STA, (void*)CONNECTION_REQUEST_AUTO_RECONNECT);
  1344. }
  1345. else{
  1346. /* In this scenario the connection was lost beyond repair: kick start the AP! */
  1347. retries = 0;
  1348. wifi_mode_t mode;
  1349. ESP_LOGW(TAG, "All connect retry attempts failed.");
  1350. /* put us in softAP mode first */
  1351. esp_wifi_get_mode(&mode);
  1352. /* if it was a restore attempt connection, we clear the bit */
  1353. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
  1354. if(WIFI_MODE_APSTA != mode){
  1355. /* call directly config_ap because we don't want to scan so the message has no benefit */
  1356. ESP_LOGD(TAG, "Starting AP directly.");
  1357. wifi_manager_config_ap();
  1358. STA_duration = STA_POLLING_MIN;
  1359. /* manual callback if needed */
  1360. if(cb_ptr_arr[ORDER_START_AP]) (*cb_ptr_arr[ORDER_START_AP])(NULL);
  1361. }
  1362. else if(STA_duration < STA_POLLING_MAX) {
  1363. STA_duration *= 1.25;
  1364. }
  1365. xTimerChangePeriod(STA_timer, pdMS_TO_TICKS(STA_duration), portMAX_DELAY);
  1366. xTimerStart(STA_timer, portMAX_DELAY);
  1367. ESP_LOGD(TAG, "STA search slow polling of %d", STA_duration);
  1368. }
  1369. }
  1370. /* callback */
  1371. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1372. }
  1373. break;
  1374. case ORDER_START_AP:
  1375. ESP_LOGD(TAG, "MESSAGE: ORDER_START_AP");
  1376. wifi_manager_config_ap();
  1377. ESP_LOGD(TAG, "AP Starting, requesting wifi scan.");
  1378. wifi_manager_scan_async();
  1379. /* callback */
  1380. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1381. break;
  1382. case EVENT_STA_GOT_IP:
  1383. ESP_LOGD(TAG, "MESSAGE: EVENT_STA_GOT_IP");
  1384. uxBits = xEventGroupGetBits(wifi_manager_event_group);
  1385. /* reset connection requests bits -- doesn't matter if it was set or not */
  1386. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_STA_CONNECT_BIT);
  1387. /* save IP as a string for the HTTP server host */
  1388. //s->ip_info.ip.addr
  1389. ip_event_got_ip_t * event =(ip_event_got_ip_t*)msg.param;
  1390. wifi_manager_safe_update_sta_ip_string(&(event->ip_info.ip));
  1391. free(msg.param);
  1392. /* save wifi config in NVS if it wasn't a restored of a connection */
  1393. if(uxBits & WIFI_MANAGER_REQUEST_RESTORE_STA_BIT){
  1394. ESP_LOGD(TAG, "Configuration came from nvs, no need to save.");
  1395. xEventGroupClearBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_RESTORE_STA_BIT);
  1396. }
  1397. else{
  1398. ESP_LOGD(TAG, "Connection was initiated by user, storing config to nvs.");
  1399. wifi_manager_save_sta_config();
  1400. }
  1401. /* refresh JSON with the new IP */
  1402. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  1403. /* generate the connection info with success */
  1404. wifi_manager_generate_ip_info_json( uxBits & WIFI_MANAGER_REQUEST_STA_CONNECT_FAILED_BIT?UPDATE_FAILED_ATTEMPT_AND_RESTORE:UPDATE_CONNECTION_OK );
  1405. wifi_manager_unlock_json_buffer();
  1406. }
  1407. else {
  1408. ESP_LOGW(TAG, "Unable to lock status json buffer. ");
  1409. }
  1410. /* bring down DNS hijack */
  1411. ESP_LOGD(TAG, "Stopping dns server.");
  1412. dns_server_stop();
  1413. /* stop AP mode */
  1414. esp_wifi_set_mode(WIFI_MODE_STA);
  1415. /* callback */
  1416. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1417. break;
  1418. case UPDATE_CONNECTION_OK:
  1419. /* refresh JSON */
  1420. if(wifi_manager_lock_json_buffer( portMAX_DELAY )){
  1421. /* generate the connection info with success */
  1422. wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK );
  1423. wifi_manager_unlock_json_buffer();
  1424. }
  1425. break;
  1426. case ORDER_DISCONNECT_STA:
  1427. ESP_LOGD(TAG, "MESSAGE: ORDER_DISCONNECT_STA. Calling esp_wifi_disconnect()");
  1428. /* precise this is coming from a user request */
  1429. xEventGroupSetBits(wifi_manager_event_group, WIFI_MANAGER_REQUEST_DISCONNECT_BIT);
  1430. /* order wifi discconect */
  1431. ESP_ERROR_CHECK(esp_wifi_disconnect());
  1432. /* callback */
  1433. if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL);
  1434. break;
  1435. case ORDER_RESTART_OTA:
  1436. ESP_LOGD(TAG, "Calling guided_restart_ota.");
  1437. guided_restart_ota();
  1438. break;
  1439. case ORDER_RESTART_OTA_URL:
  1440. ESP_LOGD(TAG, "Calling start_ota.");
  1441. start_ota(msg.param, NULL, 0);
  1442. free(msg.param);
  1443. break;
  1444. case ORDER_RESTART_RECOVERY:
  1445. ESP_LOGD(TAG, "Calling guided_factory.");
  1446. guided_factory();
  1447. break;
  1448. case ORDER_RESTART:
  1449. ESP_LOGD(TAG, "Calling simple_restart.");
  1450. simple_restart();
  1451. break;
  1452. case ORDER_UPDATE_STATUS:
  1453. wifi_manager_update_basic_info();
  1454. break;
  1455. default:
  1456. break;
  1457. } /* end of switch/case */
  1458. } /* end of if status=pdPASS */
  1459. } /* end of for loop */
  1460. vTaskDelete( NULL );
  1461. }