wifi_connect.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* wifi_connect.c
  2. *
  3. * Copyright (C) 2006-2024 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #include "wifi_connect.h"
  22. /* FreeRTOS */
  23. #include <freertos/FreeRTOS.h>
  24. #include <freertos/task.h>
  25. #include <freertos/event_groups.h>
  26. /* Espressif */
  27. #include <esp_log.h>
  28. #include <esp_idf_version.h>
  29. #include <esp_wifi.h>
  30. /* wolfSSL */
  31. #include <wolfssl/wolfcrypt/settings.h>
  32. #include <wolfssl/version.h>
  33. #include <wolfssl/wolfcrypt/types.h>
  34. #ifndef WOLFSSL_ESPIDF
  35. #warning "Problem with wolfSSL user_settings."
  36. #warning "Check components/wolfssl/include"
  37. #endif
  38. /* When there's too little heap, WiFi quietly refuses to connect */
  39. #define WIFI_LOW_HEAP_WARNING 21132
  40. #if defined(CONFIG_IDF_TARGET_ESP8266)
  41. #elif ESP_IDF_VERSION_MAJOR >= 5
  42. /* example path set in cmake file */
  43. #elif ESP_IDF_VERSION_MAJOR >= 4
  44. #include "protocol_examples_common.h"
  45. #else
  46. const static int CONNECTED_BIT = BIT0;
  47. static EventGroupHandle_t wifi_event_group;
  48. #endif
  49. #if defined(CONFIG_IDF_TARGET_ESP8266)
  50. #elif defined(ESP_IDF_VERSION_MAJOR) && defined(ESP_IDF_VERSION_MINOR)
  51. #if ESP_IDF_VERSION_MAJOR >= 4
  52. /* likely using examples, see wifi_connect.h */
  53. #else
  54. /* TODO - still supporting pre V4 ? */
  55. const static int CONNECTED_BIT = BIT0;
  56. static EventGroupHandle_t wifi_event_group;
  57. #endif
  58. #if (ESP_IDF_VERSION_MAJOR == 5)
  59. #define HAS_WPA3_FEATURES
  60. #else
  61. #undef HAS_WPA3_FEATURES
  62. #endif
  63. #else
  64. /* TODO Consider pre IDF v5? */
  65. #endif
  66. /* breadcrumb prefix for logging */
  67. const static char *TAG = "wifi_connect";
  68. #if defined(CONFIG_IDF_TARGET_ESP8266)
  69. #ifndef CONFIG_ESP_MAX_STA_CONN
  70. #define CONFIG_ESP_MAX_STA_CONN 4
  71. #endif
  72. #define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
  73. #define WIFI_CONNECTED_BIT BIT0
  74. #define WIFI_FAIL_BIT BIT1
  75. #ifndef CONFIG_ESP_MAXIMUM_RETRY
  76. #define CONFIG_ESP_MAXIMUM_RETRY 5
  77. #endif
  78. /* FreeRTOS event group to signal when we are connected*/
  79. static EventGroupHandle_t s_wifi_event_group;
  80. static int s_retry_num = 0;
  81. #define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
  82. static void event_handler(void* arg, esp_event_base_t event_base,
  83. int32_t event_id, void* event_data)
  84. {
  85. if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
  86. esp_wifi_connect();
  87. } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
  88. if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
  89. esp_wifi_connect();
  90. s_retry_num++;
  91. ESP_LOGI(TAG, "retry to connect to the AP");
  92. } else {
  93. xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
  94. }
  95. ESP_LOGI(TAG,"connect to the AP fail");
  96. } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
  97. ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
  98. ESP_LOGI(TAG, "got ip:%s",
  99. ip4addr_ntoa(&event->ip_info.ip));
  100. s_retry_num = 0;
  101. xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
  102. }
  103. }
  104. int wifi_init_sta(void)
  105. {
  106. word32 this_heap;
  107. s_wifi_event_group = xEventGroupCreate();
  108. tcpip_adapter_init();
  109. ESP_ERROR_CHECK(esp_event_loop_create_default());
  110. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  111. ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  112. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
  113. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
  114. wifi_config_t wifi_config = {
  115. .sta = {
  116. .ssid = EXAMPLE_ESP_WIFI_SSID,
  117. .password = EXAMPLE_ESP_WIFI_PASS
  118. },
  119. };
  120. /* Setting a password implies station will connect to all security modes including WEP/WPA.
  121. * However these modes are deprecated and not advisable to be used. Incase your Access point
  122. * doesn't support WPA2, these mode can be enabled by commenting below line */
  123. if (strlen((char *)wifi_config.sta.password)) {
  124. wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
  125. }
  126. ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
  127. ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
  128. ESP_ERROR_CHECK(esp_wifi_start() );
  129. ESP_LOGI(TAG, "wifi_init_sta finished. Connecting...");
  130. this_heap = esp_get_free_heap_size();
  131. ESP_LOGI(TAG, "this heap = %d", this_heap);
  132. if (this_heap < WIFI_LOW_HEAP_WARNING) {
  133. ESP_LOGW(TAG, "Warning: WiFi low heap: %d", WIFI_LOW_HEAP_WARNING);
  134. }
  135. /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
  136. * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
  137. EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
  138. WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
  139. pdFALSE,
  140. pdFALSE,
  141. portMAX_DELAY);
  142. ESP_LOGI(TAG, "xEventGroupWaitBits finished.");
  143. /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
  144. * happened. */
  145. if (bits & WIFI_CONNECTED_BIT) {
  146. ESP_LOGI(TAG, "connected to ap SSID:%s",
  147. EXAMPLE_ESP_WIFI_SSID);
  148. } else if (bits & WIFI_FAIL_BIT) {
  149. ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
  150. EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
  151. } else {
  152. ESP_LOGE(TAG, "UNEXPECTED EVENT");
  153. }
  154. ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler));
  155. ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler));
  156. vEventGroupDelete(s_wifi_event_group);
  157. return ESP_OK;
  158. }
  159. #elif ESP_IDF_VERSION_MAJOR < 4
  160. /* event handler for wifi events */
  161. static esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
  162. {
  163. switch (event->event_id)
  164. {
  165. case SYSTEM_EVENT_STA_START:
  166. esp_wifi_connect();
  167. break;
  168. case SYSTEM_EVENT_STA_GOT_IP:
  169. #if ESP_IDF_VERSION_MAJOR >= 4
  170. ESP_LOGI(TAG, "got ip:" IPSTR "\n",
  171. IP2STR(&event->event_info.got_ip.ip_info.ip));
  172. #else
  173. ESP_LOGI(TAG, "got ip:%s",
  174. ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
  175. #endif
  176. /* see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html */
  177. xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
  178. break;
  179. case SYSTEM_EVENT_STA_DISCONNECTED:
  180. esp_wifi_connect();
  181. xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
  182. break;
  183. default:
  184. break;
  185. }
  186. return ESP_OK;
  187. }
  188. #else
  189. #ifdef CONFIG_ESP_MAXIMUM_RETRY
  190. #define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
  191. #else
  192. #define CONFIG_ESP_MAXIMUM_RETRY 5
  193. #endif
  194. #if CONFIG_ESP_WIFI_AUTH_OPEN
  195. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
  196. #elif CONFIG_ESP_WIFI_AUTH_WEP
  197. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
  198. #elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
  199. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
  200. #elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
  201. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
  202. #elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
  203. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
  204. #elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
  205. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
  206. #elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
  207. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
  208. #elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
  209. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
  210. #endif
  211. #ifndef ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD
  212. #define CONFIG_ESP_WIFI_AUTH_WPA2_PSK 1
  213. #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD CONFIG_ESP_WIFI_AUTH_WPA2_PSK
  214. #endif
  215. /* FreeRTOS event group to signal when we are connected*/
  216. static EventGroupHandle_t s_wifi_event_group;
  217. /* The event group allows multiple bits for each event, but we only care about two events:
  218. * - we are connected to the AP with an IP
  219. * - we failed to connect after the maximum amount of retries */
  220. #define WIFI_CONNECTED_BIT BIT0
  221. #define WIFI_FAIL_BIT BIT1
  222. static int s_retry_num = 0;
  223. ip_event_got_ip_t* event;
  224. static void event_handler(void* arg,
  225. esp_event_base_t event_base,
  226. int32_t event_id,
  227. void* event_data)
  228. {
  229. if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
  230. esp_wifi_connect();
  231. }
  232. else if (event_base == WIFI_EVENT &&
  233. event_id == WIFI_EVENT_STA_DISCONNECTED) {
  234. if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
  235. esp_wifi_connect();
  236. s_retry_num++;
  237. ESP_LOGI(TAG, "retry to connect to the AP");
  238. }
  239. else {
  240. xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
  241. }
  242. ESP_LOGI(TAG, "connect to the AP fail");
  243. }
  244. else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
  245. event = (ip_event_got_ip_t*) event_data;
  246. wifi_show_ip();
  247. s_retry_num = 0;
  248. xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
  249. }
  250. }
  251. int wifi_init_sta(void)
  252. {
  253. int ret = ESP_OK;
  254. s_wifi_event_group = xEventGroupCreate();
  255. ESP_ERROR_CHECK(esp_netif_init());
  256. ESP_ERROR_CHECK(esp_event_loop_create_default());
  257. esp_netif_create_default_wifi_sta();
  258. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  259. ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  260. esp_event_handler_instance_t instance_any_id;
  261. esp_event_handler_instance_t instance_got_ip;
  262. ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
  263. ESP_EVENT_ANY_ID,
  264. &event_handler,
  265. NULL,
  266. &instance_any_id));
  267. ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
  268. IP_EVENT_STA_GOT_IP,
  269. &event_handler,
  270. NULL,
  271. &instance_got_ip));
  272. wifi_config_t wifi_config = {
  273. .sta = {
  274. .ssid = EXAMPLE_ESP_WIFI_SSID,
  275. .password = EXAMPLE_ESP_WIFI_PASS,
  276. /* Authmode threshold resets to WPA2 as default if password matches
  277. * WPA2 standards (pasword len => 8). If you want to connect the
  278. * device to deprecated WEP/WPA networks, Please set the threshold
  279. * value WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with
  280. * length and format matching to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK
  281. * standards. */
  282. .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
  283. #ifdef HAS_WPA3_FEATURES
  284. .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
  285. #endif
  286. },
  287. };
  288. ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
  289. ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
  290. #ifdef CONFIG_EXAMPLE_WIFI_SSID
  291. if (XSTRCMP(CONFIG_EXAMPLE_WIFI_SSID, "myssid") == 0) {
  292. ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID is \"myssid\".");
  293. ESP_LOGW(TAG, " Do you have a WiFi AP called \"myssid\", ");
  294. ESP_LOGW(TAG, " or did you forget the ESP-IDF configuration?");
  295. }
  296. #else
  297. ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID not defined.");
  298. #endif
  299. ESP_ERROR_CHECK(esp_wifi_start() );
  300. ESP_LOGI(TAG, "wifi_init_sta finished.");
  301. /* Waiting until either the connection is established (WIFI_CONNECTED_BIT)
  302. * or connection failed for the maximum number of re-tries (WIFI_FAIL_BIT).
  303. * The bits are set by event_handler() (see above) */
  304. EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
  305. WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
  306. pdFALSE,
  307. pdFALSE,
  308. portMAX_DELAY);
  309. /* xEventGroupWaitBits() returns the bits before the call returned,
  310. * hence we can test which event actually happened. */
  311. #if defined(SHOW_SSID_AND_PASSWORD)
  312. ESP_LOGW(TAG, "Undefine SHOW_SSID_AND_PASSWORD to not show SSID/password");
  313. if (bits & WIFI_CONNECTED_BIT) {
  314. ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
  315. EXAMPLE_ESP_WIFI_SSID,
  316. EXAMPLE_ESP_WIFI_PASS);
  317. }
  318. else if (bits & WIFI_FAIL_BIT) {
  319. ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
  320. EXAMPLE_ESP_WIFI_SSID,
  321. EXAMPLE_ESP_WIFI_PASS);
  322. }
  323. else {
  324. ESP_LOGE(TAG, "UNEXPECTED EVENT");
  325. }
  326. #else
  327. if (bits & WIFI_CONNECTED_BIT) {
  328. ESP_LOGI(TAG, "Connected to AP");
  329. }
  330. else if (bits & WIFI_FAIL_BIT) {
  331. ESP_LOGI(TAG, "Failed to connect to AP");
  332. ret = -1;
  333. }
  334. else {
  335. ESP_LOGE(TAG, "AP UNEXPECTED EVENT");
  336. ret = -2;
  337. }
  338. #endif
  339. return ret;
  340. }
  341. int wifi_show_ip(void)
  342. {
  343. /* TODO Causes panic: ESP_LOGI(TAG, "got ip:" IPSTR,
  344. * IP2STR(&event->ip_info.ip)); */
  345. return ESP_OK;
  346. }
  347. #endif