wifi_connect.c 14 KB

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