blufi_example_main.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. /****************************************************************************
  7. * This is a demo for bluetooth config wifi connection to ap. You can config ESP32 to connect a softap
  8. * or config ESP32 as a softap to be connected by other device. APP can be downloaded from github
  9. * android source code: https://github.com/EspressifApp/EspBlufi
  10. * iOS source code: https://github.com/EspressifApp/EspBlufiForiOS
  11. ****************************************************************************/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #include "freertos/event_groups.h"
  18. #include "esp_system.h"
  19. #include "esp_mac.h"
  20. #include "esp_wifi.h"
  21. #include "esp_event.h"
  22. #include "esp_log.h"
  23. #include "nvs_flash.h"
  24. #include "esp_bt.h"
  25. #include "esp_blufi_api.h"
  26. #include "blufi_example.h"
  27. #include "esp_blufi.h"
  28. #define EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY CONFIG_EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY
  29. #define EXAMPLE_INVALID_REASON 255
  30. #define EXAMPLE_INVALID_RSSI -128
  31. static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param);
  32. #define WIFI_LIST_NUM 10
  33. static wifi_config_t sta_config;
  34. static wifi_config_t ap_config;
  35. /* FreeRTOS event group to signal when we are connected & ready to make a request */
  36. static EventGroupHandle_t wifi_event_group;
  37. /* The event group allows multiple bits for each event,
  38. but we only care about one event - are we connected
  39. to the AP with an IP? */
  40. const int CONNECTED_BIT = BIT0;
  41. static uint8_t example_wifi_retry = 0;
  42. /* store the station info for send back to phone */
  43. static bool gl_sta_connected = false;
  44. static bool gl_sta_got_ip = false;
  45. static bool ble_is_connected = false;
  46. static uint8_t gl_sta_bssid[6];
  47. static uint8_t gl_sta_ssid[32];
  48. static int gl_sta_ssid_len;
  49. static wifi_sta_list_t gl_sta_list;
  50. static bool gl_sta_is_connecting = false;
  51. static esp_blufi_extra_info_t gl_sta_conn_info;
  52. static void example_record_wifi_conn_info(int rssi, uint8_t reason)
  53. {
  54. memset(&gl_sta_conn_info, 0, sizeof(esp_blufi_extra_info_t));
  55. if (gl_sta_is_connecting) {
  56. gl_sta_conn_info.sta_max_conn_retry_set = true;
  57. gl_sta_conn_info.sta_max_conn_retry = EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY;
  58. } else {
  59. gl_sta_conn_info.sta_conn_rssi_set = true;
  60. gl_sta_conn_info.sta_conn_rssi = rssi;
  61. gl_sta_conn_info.sta_conn_end_reason_set = true;
  62. gl_sta_conn_info.sta_conn_end_reason = reason;
  63. }
  64. }
  65. static void example_wifi_connect(void)
  66. {
  67. example_wifi_retry = 0;
  68. gl_sta_is_connecting = (esp_wifi_connect() == ESP_OK);
  69. example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON);
  70. }
  71. static bool example_wifi_reconnect(void)
  72. {
  73. bool ret;
  74. if (gl_sta_is_connecting && example_wifi_retry++ < EXAMPLE_WIFI_CONNECTION_MAXIMUM_RETRY) {
  75. BLUFI_INFO("BLUFI WiFi starts reconnection\n");
  76. gl_sta_is_connecting = (esp_wifi_connect() == ESP_OK);
  77. example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON);
  78. ret = true;
  79. } else {
  80. ret = false;
  81. }
  82. return ret;
  83. }
  84. static int softap_get_current_connection_number(void)
  85. {
  86. esp_err_t ret;
  87. ret = esp_wifi_ap_get_sta_list(&gl_sta_list);
  88. if (ret == ESP_OK)
  89. {
  90. return gl_sta_list.num;
  91. }
  92. return 0;
  93. }
  94. static void ip_event_handler(void* arg, esp_event_base_t event_base,
  95. int32_t event_id, void* event_data)
  96. {
  97. wifi_mode_t mode;
  98. switch (event_id) {
  99. case IP_EVENT_STA_GOT_IP: {
  100. esp_blufi_extra_info_t info;
  101. xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
  102. esp_wifi_get_mode(&mode);
  103. memset(&info, 0, sizeof(esp_blufi_extra_info_t));
  104. memcpy(info.sta_bssid, gl_sta_bssid, 6);
  105. info.sta_bssid_set = true;
  106. info.sta_ssid = gl_sta_ssid;
  107. info.sta_ssid_len = gl_sta_ssid_len;
  108. gl_sta_got_ip = true;
  109. if (ble_is_connected == true) {
  110. esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, softap_get_current_connection_number(), &info);
  111. } else {
  112. BLUFI_INFO("BLUFI BLE is not connected yet\n");
  113. }
  114. break;
  115. }
  116. default:
  117. break;
  118. }
  119. return;
  120. }
  121. static void wifi_event_handler(void* arg, esp_event_base_t event_base,
  122. int32_t event_id, void* event_data)
  123. {
  124. wifi_event_sta_connected_t *event;
  125. wifi_event_sta_disconnected_t *disconnected_event;
  126. wifi_mode_t mode;
  127. switch (event_id) {
  128. case WIFI_EVENT_STA_START:
  129. example_wifi_connect();
  130. break;
  131. case WIFI_EVENT_STA_CONNECTED:
  132. gl_sta_connected = true;
  133. gl_sta_is_connecting = false;
  134. event = (wifi_event_sta_connected_t*) event_data;
  135. memcpy(gl_sta_bssid, event->bssid, 6);
  136. memcpy(gl_sta_ssid, event->ssid, event->ssid_len);
  137. gl_sta_ssid_len = event->ssid_len;
  138. break;
  139. case WIFI_EVENT_STA_DISCONNECTED:
  140. /* Only handle reconnection during connecting */
  141. if (gl_sta_connected == false && example_wifi_reconnect() == false) {
  142. gl_sta_is_connecting = false;
  143. disconnected_event = (wifi_event_sta_disconnected_t*) event_data;
  144. example_record_wifi_conn_info(disconnected_event->rssi, disconnected_event->reason);
  145. }
  146. /* This is a workaround as ESP32 WiFi libs don't currently
  147. auto-reassociate. */
  148. gl_sta_connected = false;
  149. gl_sta_got_ip = false;
  150. memset(gl_sta_ssid, 0, 32);
  151. memset(gl_sta_bssid, 0, 6);
  152. gl_sta_ssid_len = 0;
  153. xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
  154. break;
  155. case WIFI_EVENT_AP_START:
  156. esp_wifi_get_mode(&mode);
  157. /* TODO: get config or information of softap, then set to report extra_info */
  158. if (ble_is_connected == true) {
  159. if (gl_sta_connected) {
  160. esp_blufi_extra_info_t info;
  161. memset(&info, 0, sizeof(esp_blufi_extra_info_t));
  162. memcpy(info.sta_bssid, gl_sta_bssid, 6);
  163. info.sta_bssid_set = true;
  164. info.sta_ssid = gl_sta_ssid;
  165. info.sta_ssid_len = gl_sta_ssid_len;
  166. esp_blufi_send_wifi_conn_report(mode, gl_sta_got_ip ? ESP_BLUFI_STA_CONN_SUCCESS : ESP_BLUFI_STA_NO_IP, softap_get_current_connection_number(), &info);
  167. } else if (gl_sta_is_connecting) {
  168. esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONNECTING, softap_get_current_connection_number(), &gl_sta_conn_info);
  169. } else {
  170. esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap_get_current_connection_number(), &gl_sta_conn_info);
  171. }
  172. } else {
  173. BLUFI_INFO("BLUFI BLE is not connected yet\n");
  174. }
  175. break;
  176. case WIFI_EVENT_SCAN_DONE: {
  177. uint16_t apCount = 0;
  178. esp_wifi_scan_get_ap_num(&apCount);
  179. if (apCount == 0) {
  180. BLUFI_INFO("Nothing AP found");
  181. break;
  182. }
  183. wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);
  184. if (!ap_list) {
  185. BLUFI_ERROR("malloc error, ap_list is NULL");
  186. break;
  187. }
  188. ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, ap_list));
  189. esp_blufi_ap_record_t * blufi_ap_list = (esp_blufi_ap_record_t *)malloc(apCount * sizeof(esp_blufi_ap_record_t));
  190. if (!blufi_ap_list) {
  191. if (ap_list) {
  192. free(ap_list);
  193. }
  194. BLUFI_ERROR("malloc error, blufi_ap_list is NULL");
  195. break;
  196. }
  197. for (int i = 0; i < apCount; ++i)
  198. {
  199. blufi_ap_list[i].rssi = ap_list[i].rssi;
  200. memcpy(blufi_ap_list[i].ssid, ap_list[i].ssid, sizeof(ap_list[i].ssid));
  201. }
  202. if (ble_is_connected == true) {
  203. esp_blufi_send_wifi_list(apCount, blufi_ap_list);
  204. } else {
  205. BLUFI_INFO("BLUFI BLE is not connected yet\n");
  206. }
  207. esp_wifi_scan_stop();
  208. free(ap_list);
  209. free(blufi_ap_list);
  210. break;
  211. }
  212. case WIFI_EVENT_AP_STACONNECTED: {
  213. wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
  214. BLUFI_INFO("station "MACSTR" join, AID=%d", MAC2STR(event->mac), event->aid);
  215. break;
  216. }
  217. case WIFI_EVENT_AP_STADISCONNECTED: {
  218. wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
  219. BLUFI_INFO("station "MACSTR" leave, AID=%d", MAC2STR(event->mac), event->aid);
  220. break;
  221. }
  222. default:
  223. break;
  224. }
  225. return;
  226. }
  227. static void initialise_wifi(void)
  228. {
  229. ESP_ERROR_CHECK(esp_netif_init());
  230. wifi_event_group = xEventGroupCreate();
  231. ESP_ERROR_CHECK(esp_event_loop_create_default());
  232. esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
  233. assert(sta_netif);
  234. esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
  235. assert(ap_netif);
  236. ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
  237. ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
  238. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  239. ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
  240. ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
  241. example_record_wifi_conn_info(EXAMPLE_INVALID_RSSI, EXAMPLE_INVALID_REASON);
  242. ESP_ERROR_CHECK( esp_wifi_start() );
  243. }
  244. static esp_blufi_callbacks_t example_callbacks = {
  245. .event_cb = example_event_callback,
  246. .negotiate_data_handler = blufi_dh_negotiate_data_handler,
  247. .encrypt_func = blufi_aes_encrypt,
  248. .decrypt_func = blufi_aes_decrypt,
  249. .checksum_func = blufi_crc_checksum,
  250. };
  251. static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param)
  252. {
  253. /* actually, should post to blufi_task handle the procedure,
  254. * now, as a example, we do it more simply */
  255. switch (event) {
  256. case ESP_BLUFI_EVENT_INIT_FINISH:
  257. BLUFI_INFO("BLUFI init finish\n");
  258. esp_blufi_adv_start();
  259. break;
  260. case ESP_BLUFI_EVENT_DEINIT_FINISH:
  261. BLUFI_INFO("BLUFI deinit finish\n");
  262. break;
  263. case ESP_BLUFI_EVENT_BLE_CONNECT:
  264. BLUFI_INFO("BLUFI ble connect\n");
  265. ble_is_connected = true;
  266. esp_blufi_adv_stop();
  267. blufi_security_init();
  268. break;
  269. case ESP_BLUFI_EVENT_BLE_DISCONNECT:
  270. BLUFI_INFO("BLUFI ble disconnect\n");
  271. ble_is_connected = false;
  272. blufi_security_deinit();
  273. esp_blufi_adv_start();
  274. break;
  275. case ESP_BLUFI_EVENT_SET_WIFI_OPMODE:
  276. BLUFI_INFO("BLUFI Set WIFI opmode %d\n", param->wifi_mode.op_mode);
  277. ESP_ERROR_CHECK( esp_wifi_set_mode(param->wifi_mode.op_mode) );
  278. break;
  279. case ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP:
  280. BLUFI_INFO("BLUFI requset wifi connect to AP\n");
  281. /* there is no wifi callback when the device has already connected to this wifi
  282. so disconnect wifi before connection.
  283. */
  284. esp_wifi_disconnect();
  285. example_wifi_connect();
  286. break;
  287. case ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP:
  288. BLUFI_INFO("BLUFI requset wifi disconnect from AP\n");
  289. esp_wifi_disconnect();
  290. break;
  291. case ESP_BLUFI_EVENT_REPORT_ERROR:
  292. BLUFI_ERROR("BLUFI report error, error code %d\n", param->report_error.state);
  293. esp_blufi_send_error_info(param->report_error.state);
  294. break;
  295. case ESP_BLUFI_EVENT_GET_WIFI_STATUS: {
  296. wifi_mode_t mode;
  297. esp_blufi_extra_info_t info;
  298. esp_wifi_get_mode(&mode);
  299. if (gl_sta_connected) {
  300. memset(&info, 0, sizeof(esp_blufi_extra_info_t));
  301. memcpy(info.sta_bssid, gl_sta_bssid, 6);
  302. info.sta_bssid_set = true;
  303. info.sta_ssid = gl_sta_ssid;
  304. info.sta_ssid_len = gl_sta_ssid_len;
  305. esp_blufi_send_wifi_conn_report(mode, gl_sta_got_ip ? ESP_BLUFI_STA_CONN_SUCCESS : ESP_BLUFI_STA_NO_IP, softap_get_current_connection_number(), &info);
  306. } else if (gl_sta_is_connecting) {
  307. esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONNECTING, softap_get_current_connection_number(), &gl_sta_conn_info);
  308. } else {
  309. esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap_get_current_connection_number(), &gl_sta_conn_info);
  310. }
  311. BLUFI_INFO("BLUFI get wifi status from AP\n");
  312. break;
  313. }
  314. case ESP_BLUFI_EVENT_RECV_SLAVE_DISCONNECT_BLE:
  315. BLUFI_INFO("blufi close a gatt connection");
  316. esp_blufi_disconnect();
  317. break;
  318. case ESP_BLUFI_EVENT_DEAUTHENTICATE_STA:
  319. /* TODO */
  320. break;
  321. case ESP_BLUFI_EVENT_RECV_STA_BSSID:
  322. memcpy(sta_config.sta.bssid, param->sta_bssid.bssid, 6);
  323. sta_config.sta.bssid_set = 1;
  324. esp_wifi_set_config(WIFI_IF_STA, &sta_config);
  325. BLUFI_INFO("Recv STA BSSID %s\n", sta_config.sta.ssid);
  326. break;
  327. case ESP_BLUFI_EVENT_RECV_STA_SSID:
  328. strncpy((char *)sta_config.sta.ssid, (char *)param->sta_ssid.ssid, param->sta_ssid.ssid_len);
  329. sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0';
  330. esp_wifi_set_config(WIFI_IF_STA, &sta_config);
  331. BLUFI_INFO("Recv STA SSID %s\n", sta_config.sta.ssid);
  332. break;
  333. case ESP_BLUFI_EVENT_RECV_STA_PASSWD:
  334. strncpy((char *)sta_config.sta.password, (char *)param->sta_passwd.passwd, param->sta_passwd.passwd_len);
  335. sta_config.sta.password[param->sta_passwd.passwd_len] = '\0';
  336. esp_wifi_set_config(WIFI_IF_STA, &sta_config);
  337. BLUFI_INFO("Recv STA PASSWORD %s\n", sta_config.sta.password);
  338. break;
  339. case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID:
  340. strncpy((char *)ap_config.ap.ssid, (char *)param->softap_ssid.ssid, param->softap_ssid.ssid_len);
  341. ap_config.ap.ssid[param->softap_ssid.ssid_len] = '\0';
  342. ap_config.ap.ssid_len = param->softap_ssid.ssid_len;
  343. esp_wifi_set_config(WIFI_IF_AP, &ap_config);
  344. BLUFI_INFO("Recv SOFTAP SSID %s, ssid len %d\n", ap_config.ap.ssid, ap_config.ap.ssid_len);
  345. break;
  346. case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD:
  347. strncpy((char *)ap_config.ap.password, (char *)param->softap_passwd.passwd, param->softap_passwd.passwd_len);
  348. ap_config.ap.password[param->softap_passwd.passwd_len] = '\0';
  349. esp_wifi_set_config(WIFI_IF_AP, &ap_config);
  350. BLUFI_INFO("Recv SOFTAP PASSWORD %s len = %d\n", ap_config.ap.password, param->softap_passwd.passwd_len);
  351. break;
  352. case ESP_BLUFI_EVENT_RECV_SOFTAP_MAX_CONN_NUM:
  353. if (param->softap_max_conn_num.max_conn_num > 4) {
  354. return;
  355. }
  356. ap_config.ap.max_connection = param->softap_max_conn_num.max_conn_num;
  357. esp_wifi_set_config(WIFI_IF_AP, &ap_config);
  358. BLUFI_INFO("Recv SOFTAP MAX CONN NUM %d\n", ap_config.ap.max_connection);
  359. break;
  360. case ESP_BLUFI_EVENT_RECV_SOFTAP_AUTH_MODE:
  361. if (param->softap_auth_mode.auth_mode >= WIFI_AUTH_MAX) {
  362. return;
  363. }
  364. ap_config.ap.authmode = param->softap_auth_mode.auth_mode;
  365. esp_wifi_set_config(WIFI_IF_AP, &ap_config);
  366. BLUFI_INFO("Recv SOFTAP AUTH MODE %d\n", ap_config.ap.authmode);
  367. break;
  368. case ESP_BLUFI_EVENT_RECV_SOFTAP_CHANNEL:
  369. if (param->softap_channel.channel > 13) {
  370. return;
  371. }
  372. ap_config.ap.channel = param->softap_channel.channel;
  373. esp_wifi_set_config(WIFI_IF_AP, &ap_config);
  374. BLUFI_INFO("Recv SOFTAP CHANNEL %d\n", ap_config.ap.channel);
  375. break;
  376. case ESP_BLUFI_EVENT_GET_WIFI_LIST:{
  377. wifi_scan_config_t scanConf = {
  378. .ssid = NULL,
  379. .bssid = NULL,
  380. .channel = 0,
  381. .show_hidden = false
  382. };
  383. esp_err_t ret = esp_wifi_scan_start(&scanConf, true);
  384. if (ret != ESP_OK) {
  385. esp_blufi_send_error_info(ESP_BLUFI_WIFI_SCAN_FAIL);
  386. }
  387. break;
  388. }
  389. case ESP_BLUFI_EVENT_RECV_CUSTOM_DATA:
  390. BLUFI_INFO("Recv Custom Data %" PRIu32 "\n", param->custom_data.data_len);
  391. esp_log_buffer_hex("Custom Data", param->custom_data.data, param->custom_data.data_len);
  392. break;
  393. case ESP_BLUFI_EVENT_RECV_USERNAME:
  394. /* Not handle currently */
  395. break;
  396. case ESP_BLUFI_EVENT_RECV_CA_CERT:
  397. /* Not handle currently */
  398. break;
  399. case ESP_BLUFI_EVENT_RECV_CLIENT_CERT:
  400. /* Not handle currently */
  401. break;
  402. case ESP_BLUFI_EVENT_RECV_SERVER_CERT:
  403. /* Not handle currently */
  404. break;
  405. case ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY:
  406. /* Not handle currently */
  407. break;;
  408. case ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY:
  409. /* Not handle currently */
  410. break;
  411. default:
  412. break;
  413. }
  414. }
  415. void app_main(void)
  416. {
  417. esp_err_t ret;
  418. // Initialize NVS
  419. ret = nvs_flash_init();
  420. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  421. ESP_ERROR_CHECK(nvs_flash_erase());
  422. ret = nvs_flash_init();
  423. }
  424. ESP_ERROR_CHECK( ret );
  425. initialise_wifi();
  426. ret = esp_blufi_controller_init();
  427. if (ret) {
  428. BLUFI_ERROR("%s BLUFI controller init failed: %s\n", __func__, esp_err_to_name(ret));
  429. return;
  430. }
  431. ret = esp_blufi_host_and_cb_init(&example_callbacks);
  432. if (ret) {
  433. BLUFI_ERROR("%s initialise failed: %s\n", __func__, esp_err_to_name(ret));
  434. return;
  435. }
  436. BLUFI_INFO("BLUFI VERSION %04x\n", esp_blufi_get_version());
  437. }