wifi_connect.c 14 KB

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