You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

707 lines
27 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #include "ble_spp_client_demo.h"
  2. #include "driver/uart.h"
  3. #include "esp_bt.h"
  4. #include "nvs_flash.h"
  5. #include "esp_bt_device.h"
  6. #include "esp_gap_ble_api.h"
  7. #include "esp_gattc_api.h"
  8. #include "esp_gatt_defs.h"
  9. #include "esp_bt_main.h"
  10. #include "esp_system.h"
  11. #include "esp_gatt_common_api.h"
  12. #include "esp_log.h"
  13. #include "freertos/FreeRTOS.h"
  14. #include "driver/gpio.h"
  15. #define GATTC_TAG "GATTC_SPP_CLIENT"
  16. struct gattc_profile_inst
  17. {
  18. esp_gattc_cb_t gattc_cb;
  19. uint16_t gattc_if;
  20. uint16_t app_id;
  21. uint16_t conn_id;
  22. uint16_t service_start_handle;
  23. uint16_t service_end_handle;
  24. uint16_t char_handle;
  25. esp_bd_addr_t remote_bda;
  26. };
  27. /// Declare static functions
  28. static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
  29. static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
  30. static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
  31. /* One gatt-based profile one app_id and one gattc_if, this array will store the gattc_if returned by ESP_GATTS_REG_EVT */
  32. static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {
  33. [PROFILE_APP_ID] = {
  34. .gattc_cb = gattc_profile_event_handler,
  35. .gattc_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
  36. },
  37. };
  38. static esp_ble_scan_params_t ble_scan_params = {
  39. .scan_type = BLE_SCAN_TYPE_ACTIVE,
  40. .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
  41. .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
  42. .scan_interval = 0x50,
  43. .scan_window = 0x30,
  44. .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE};
  45. static const char device_name[] = "yimei_ble";
  46. static bool is_connect = false;
  47. static uint16_t spp_conn_id = 0;
  48. static uint16_t spp_mtu_size = 23;
  49. static uint16_t cmd = 0;
  50. static uint16_t spp_srv_start_handle = 0;
  51. static uint16_t spp_srv_end_handle = 0;
  52. static uint16_t spp_gattc_if = 0xff;
  53. static char *notify_value_p = NULL;
  54. static int notify_value_offset = 0;
  55. static int notify_value_count = 0;
  56. static uint16_t count = SPP_IDX_NB;
  57. static esp_gattc_db_elem_t *db = NULL;
  58. static esp_ble_gap_cb_param_t scan_rst;
  59. static xQueueHandle cmd_reg_queue = NULL;
  60. QueueHandle_t spp_uart_queue = NULL;
  61. #ifdef SUPPORT_HEARTBEAT
  62. static uint8_t heartbeat_s[9] = {'E', 's', 'p', 'r', 'e', 's', 's', 'i', 'f'};
  63. static xQueueHandle cmd_heartbeat_queue = NULL;
  64. #endif
  65. static esp_bt_uuid_t spp_service_uuid = {
  66. .len = ESP_UUID_LEN_128,
  67. .uuid = {
  68. .uuid128 = ESP_GATT_SPP_SERVICE_UUID,
  69. },
  70. };
  71. static void notify_event_handler(esp_ble_gattc_cb_param_t *p_data)
  72. {
  73. uint8_t handle = 0;
  74. if (p_data->notify.is_notify == true)
  75. {
  76. ESP_LOGI(GATTC_TAG, "+NOTIFY:handle = %d,length = %d ", p_data->notify.handle, p_data->notify.value_len);
  77. }
  78. else
  79. {
  80. ESP_LOGI(GATTC_TAG, "+INDICATE:handle = %d,length = %d ", p_data->notify.handle, p_data->notify.value_len);
  81. }
  82. handle = p_data->notify.handle;
  83. if (db == NULL)
  84. {
  85. ESP_LOGE(GATTC_TAG, " %s db is NULL\n", __func__);
  86. return;
  87. }
  88. if (handle == db[SPP_IDX_SPP_DATA_NTY_VAL].attribute_handle)
  89. {
  90. #ifdef SPP_DEBUG_MODE
  91. esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
  92. #else
  93. if ((p_data->notify.value[0] == '#') && (p_data->notify.value[1] == '#'))
  94. {
  95. if ((++notify_value_count) != p_data->notify.value[3])
  96. {
  97. if (notify_value_p != NULL)
  98. {
  99. free(notify_value_p);
  100. }
  101. notify_value_count = 0;
  102. notify_value_p = NULL;
  103. notify_value_offset = 0;
  104. ESP_LOGE(GATTC_TAG, "notify value count is not continuous,%s\n", __func__);
  105. return;
  106. }
  107. if (p_data->notify.value[3] == 1)
  108. {
  109. notify_value_p = (char *)malloc(((spp_mtu_size - 7) * (p_data->notify.value[2])) * sizeof(char));
  110. if (notify_value_p == NULL)
  111. {
  112. ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n", __func__, __LINE__);
  113. notify_value_count = 0;
  114. return;
  115. }
  116. memcpy((notify_value_p + notify_value_offset), (p_data->notify.value + 4), (p_data->notify.value_len - 4));
  117. if (p_data->notify.value[2] == p_data->notify.value[3])
  118. {
  119. uart_write_bytes(UART_NUM_0, (char *)(notify_value_p), (p_data->notify.value_len - 4 + notify_value_offset));
  120. free(notify_value_p);
  121. notify_value_p = NULL;
  122. notify_value_offset = 0;
  123. return;
  124. }
  125. notify_value_offset += (p_data->notify.value_len - 4);
  126. }
  127. else if (p_data->notify.value[3] <= p_data->notify.value[2])
  128. {
  129. memcpy((notify_value_p + notify_value_offset), (p_data->notify.value + 4), (p_data->notify.value_len - 4));
  130. if (p_data->notify.value[3] == p_data->notify.value[2])
  131. {
  132. uart_write_bytes(UART_NUM_0, (char *)(notify_value_p), (p_data->notify.value_len - 4 + notify_value_offset));
  133. free(notify_value_p);
  134. notify_value_count = 0;
  135. notify_value_p = NULL;
  136. notify_value_offset = 0;
  137. return;
  138. }
  139. notify_value_offset += (p_data->notify.value_len - 4);
  140. }
  141. }
  142. else
  143. {
  144. uart_write_bytes(UART_NUM_0, (char *)(p_data->notify.value), p_data->notify.value_len);
  145. }
  146. #endif
  147. }
  148. // else if (handle == ((db + SPP_IDX_SPP_STATUS_VAL)->attribute_handle))
  149. // {
  150. // esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
  151. // // TODO:server notify status characteristic
  152. // }
  153. else
  154. {
  155. esp_log_buffer_char(GATTC_TAG, (char *)p_data->notify.value, p_data->notify.value_len);
  156. }
  157. }
  158. static void free_gattc_srv_db(void)
  159. {
  160. is_connect = false;
  161. spp_gattc_if = 0xff;
  162. spp_conn_id = 0;
  163. spp_mtu_size = 23;
  164. cmd = 0;
  165. spp_srv_start_handle = 0;
  166. spp_srv_end_handle = 0;
  167. notify_value_p = NULL;
  168. notify_value_offset = 0;
  169. notify_value_count = 0;
  170. if (db)
  171. {
  172. free(db);
  173. db = NULL;
  174. }
  175. }
  176. static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
  177. {
  178. uint8_t *adv_name = NULL;
  179. uint8_t adv_name_len = 0;
  180. esp_err_t err;
  181. switch (event)
  182. {
  183. case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
  184. {
  185. if ((err = param->scan_param_cmpl.status) != ESP_BT_STATUS_SUCCESS)
  186. {
  187. ESP_LOGE(GATTC_TAG, "Scan param set failed: %s", esp_err_to_name(err));
  188. break;
  189. }
  190. // the unit of the duration is second
  191. uint32_t duration = 0xFFFF;
  192. ESP_LOGI(GATTC_TAG, "Enable Ble Scan:during time 0x%04X minutes.", duration);
  193. esp_ble_gap_start_scanning(duration);
  194. break;
  195. }
  196. case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
  197. // scan start complete event to indicate scan start successfully or failed
  198. if ((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS)
  199. {
  200. ESP_LOGE(GATTC_TAG, "Scan start failed: %s", esp_err_to_name(err));
  201. break;
  202. }
  203. ESP_LOGI(GATTC_TAG, "Scan start successed");
  204. break;
  205. case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
  206. if ((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS)
  207. {
  208. ESP_LOGE(GATTC_TAG, "Scan stop failed: %s", esp_err_to_name(err));
  209. break;
  210. }
  211. ESP_LOGI(GATTC_TAG, "Scan stop successed");
  212. if (is_connect == false)
  213. {
  214. ESP_LOGI(GATTC_TAG, "Connect to the remote device.");
  215. esp_ble_gattc_open(gl_profile_tab[PROFILE_APP_ID].gattc_if, scan_rst.scan_rst.bda, scan_rst.scan_rst.ble_addr_type, true);
  216. }
  217. break;
  218. case ESP_GAP_BLE_SCAN_RESULT_EVT:
  219. {
  220. esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
  221. switch (scan_result->scan_rst.search_evt)
  222. {
  223. case ESP_GAP_SEARCH_INQ_RES_EVT:
  224. esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
  225. ESP_LOGI(GATTC_TAG, "Searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
  226. adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
  227. ESP_LOGI(GATTC_TAG, "Searched Device Name Len %d", adv_name_len);
  228. esp_log_buffer_char(GATTC_TAG, adv_name, adv_name_len);
  229. ESP_LOGI(GATTC_TAG, "\n");
  230. if (adv_name != NULL)
  231. {
  232. if (strncmp((char *)adv_name, device_name, adv_name_len) == 0)
  233. {
  234. memcpy(&(scan_rst), scan_result, sizeof(esp_ble_gap_cb_param_t));
  235. esp_ble_gap_stop_scanning();
  236. }
  237. }
  238. break;
  239. case ESP_GAP_SEARCH_INQ_CMPL_EVT:
  240. break;
  241. default:
  242. break;
  243. }
  244. break;
  245. }
  246. case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
  247. if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS)
  248. {
  249. ESP_LOGE(GATTC_TAG, "Adv stop failed: %s", esp_err_to_name(err));
  250. }
  251. else
  252. {
  253. ESP_LOGI(GATTC_TAG, "Stop adv successfully");
  254. }
  255. break;
  256. default:
  257. break;
  258. }
  259. }
  260. static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
  261. {
  262. ESP_LOGI(GATTC_TAG, "EVT %d, gattc if %d", event, gattc_if);
  263. /* If event is register event, store the gattc_if for each profile */
  264. if (event == ESP_GATTC_REG_EVT)
  265. {
  266. if (param->reg.status == ESP_GATT_OK)
  267. {
  268. gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;
  269. }
  270. else
  271. {
  272. ESP_LOGI(GATTC_TAG, "Reg app failed, app_id %04x, status %d", param->reg.app_id, param->reg.status);
  273. return;
  274. }
  275. }
  276. /* If the gattc_if equal to profile A, call profile A cb handler,
  277. * so here call each profile's callback */
  278. do
  279. {
  280. int idx;
  281. for (idx = 0; idx < PROFILE_NUM; idx++)
  282. {
  283. if (gattc_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
  284. gattc_if == gl_profile_tab[idx].gattc_if)
  285. {
  286. if (gl_profile_tab[idx].gattc_cb)
  287. {
  288. gl_profile_tab[idx].gattc_cb(event, gattc_if, param);
  289. }
  290. }
  291. }
  292. } while (0);
  293. }
  294. static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
  295. {
  296. esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
  297. switch (event)
  298. {
  299. case ESP_GATTC_REG_EVT:
  300. ESP_LOGI(GATTC_TAG, "REG EVT, set scan params");
  301. esp_ble_gap_set_scan_params(&ble_scan_params);
  302. break;
  303. case ESP_GATTC_CONNECT_EVT:
  304. ESP_LOGI(GATTC_TAG, "ESP_GATTC_CONNECT_EVT: conn_id=%d, gatt_if = %d", spp_conn_id, gattc_if);
  305. ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
  306. esp_log_buffer_hex(GATTC_TAG, gl_profile_tab[PROFILE_APP_ID].remote_bda, sizeof(esp_bd_addr_t));
  307. spp_gattc_if = gattc_if;
  308. is_connect = true;
  309. spp_conn_id = p_data->connect.conn_id;
  310. memcpy(gl_profile_tab[PROFILE_APP_ID].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
  311. esp_ble_gattc_search_service(spp_gattc_if, spp_conn_id, &spp_service_uuid);
  312. break;
  313. case ESP_GATTC_DISCONNECT_EVT:
  314. ESP_LOGI(GATTC_TAG, "disconnect");
  315. free_gattc_srv_db();
  316. esp_ble_gap_start_scanning(SCAN_ALL_THE_TIME);
  317. break;
  318. case ESP_GATTC_SEARCH_RES_EVT:
  319. ESP_LOGI(GATTC_TAG, "ESP_GATTC_SEARCH_RES_EVT: start_handle = %d, end_handle = %d", p_data->search_res.start_handle, p_data->search_res.end_handle);
  320. for (int i = 15; i >= 0; i--)
  321. {
  322. ESP_LOGI("uuid", "UUID[%d] = %d", i, p_data->search_res.srvc_id.uuid.uuid.uuid128[i]);
  323. }
  324. spp_srv_start_handle = p_data->search_res.start_handle;
  325. spp_srv_end_handle = p_data->search_res.end_handle;
  326. break;
  327. case ESP_GATTC_SEARCH_CMPL_EVT:
  328. ESP_LOGI(GATTC_TAG, "SEARCH_CMPL: conn_id = %x, status %d", spp_conn_id, p_data->search_cmpl.status);
  329. esp_ble_gattc_send_mtu_req(gattc_if, spp_conn_id);
  330. break;
  331. case ESP_GATTC_REG_FOR_NOTIFY_EVT:
  332. {
  333. ESP_LOGI(GATTC_TAG, "Index = %d,status = %d,handle = %d\n", cmd, p_data->reg_for_notify.status, p_data->reg_for_notify.handle);
  334. if (p_data->reg_for_notify.status != ESP_GATT_OK)
  335. {
  336. ESP_LOGE(GATTC_TAG, "ESP_GATTC_REG_FOR_NOTIFY_EVT, status = %d", p_data->reg_for_notify.status);
  337. break;
  338. }
  339. uint16_t notify_en = 1;
  340. esp_ble_gattc_write_char_descr(
  341. spp_gattc_if,
  342. spp_conn_id,
  343. (db + cmd + 1)->attribute_handle,
  344. sizeof(notify_en),
  345. (uint8_t *)&notify_en,
  346. ESP_GATT_WRITE_TYPE_RSP,
  347. ESP_GATT_AUTH_REQ_NONE);
  348. break;
  349. }
  350. case ESP_GATTC_NOTIFY_EVT:
  351. ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT\n");
  352. notify_event_handler(p_data);
  353. break;
  354. case ESP_GATTC_READ_CHAR_EVT:
  355. ESP_LOGI(GATTC_TAG, "ESP_GATTC_READ_CHAR_EVT\n");
  356. break;
  357. case ESP_GATTC_WRITE_CHAR_EVT:
  358. ESP_LOGI(GATTC_TAG, "ESP_GATTC_WRITE_CHAR_EVT:status = %d,handle = %d", param->write.status, param->write.handle);
  359. if (param->write.status != ESP_GATT_OK)
  360. {
  361. ESP_LOGE(GATTC_TAG, "ESP_GATTC_WRITE_CHAR_EVT, error status = %d", p_data->write.status);
  362. break;
  363. }
  364. break;
  365. case ESP_GATTC_PREP_WRITE_EVT:
  366. break;
  367. case ESP_GATTC_EXEC_EVT:
  368. break;
  369. case ESP_GATTC_WRITE_DESCR_EVT:
  370. ESP_LOGI(GATTC_TAG, "ESP_GATTC_WRITE_DESCR_EVT: status =%d,handle = %d \n", p_data->write.status, p_data->write.handle);
  371. if (p_data->write.status != ESP_GATT_OK)
  372. {
  373. ESP_LOGE(GATTC_TAG, "ESP_GATTC_WRITE_DESCR_EVT, error status = %d", p_data->write.status);
  374. break;
  375. }
  376. switch (cmd)
  377. {
  378. case SPP_IDX_SPP_DATA_NTY_VAL:
  379. // cmd = SPP_IDX_SPP_STATUS_VAL;
  380. // ESP_LOGI("test","============cmd = %d========",cmd);
  381. // xQueueSend(cmd_reg_queue, &cmd,10/portTICK_PERIOD_MS);
  382. break;
  383. // case SPP_IDX_SPP_STATUS_VAL:
  384. // #ifdef SUPPORT_HEARTBEAT
  385. // cmd = SPP_IDX_SPP_HEARTBEAT_VAL;
  386. // xQueueSend(cmd_reg_queue, &cmd, 10 / portTICK_PERIOD_MS);
  387. // #endif
  388. // break;
  389. #ifdef SUPPORT_HEARTBEAT
  390. case SPP_IDX_SPP_HEARTBEAT_VAL:
  391. xQueueSend(cmd_heartbeat_queue, &cmd, 10 / portTICK_PERIOD_MS);
  392. break;
  393. #endif
  394. default:
  395. break;
  396. };
  397. break;
  398. case ESP_GATTC_CFG_MTU_EVT:
  399. if (p_data->cfg_mtu.status != ESP_OK)
  400. {
  401. break;
  402. }
  403. ESP_LOGI(GATTC_TAG, "+MTU:%d\n", p_data->cfg_mtu.mtu);
  404. spp_mtu_size = p_data->cfg_mtu.mtu;
  405. db = (esp_gattc_db_elem_t *)malloc(count * sizeof(esp_gattc_db_elem_t));
  406. if (db == NULL)
  407. {
  408. ESP_LOGE(GATTC_TAG, "%s:malloc db falied\n", __func__);
  409. break;
  410. }
  411. if (esp_ble_gattc_get_db(spp_gattc_if, spp_conn_id, spp_srv_start_handle, spp_srv_end_handle, db, &count) != ESP_GATT_OK)
  412. {
  413. ESP_LOGE(GATTC_TAG, "%s:get db falied\n", __func__);
  414. break;
  415. }
  416. if (count != SPP_IDX_NB)
  417. {
  418. ESP_LOGE(GATTC_TAG, "%s:get db count != SPP_IDX_NB, count = %d, SPP_IDX_NB = %d\n", __func__, count, SPP_IDX_NB);
  419. break;
  420. }
  421. uint8_t strbuffer[38] = {0};
  422. for (int i = 0; i < SPP_IDX_NB; i++)
  423. {
  424. ESP_LOGI("==test==", "%d", (db + i)->type);
  425. switch ((db + i)->type)
  426. {
  427. case ESP_GATT_DB_PRIMARY_SERVICE:
  428. // motor_drive_hex_to_str((char *)&(db + i)->uuid.uuid.uuid128, 16, (char *)&strbuffer);
  429. ESP_LOGI(GATTC_TAG, "attr_type = PRIMARY_SERVICE,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%s\n",
  430. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, strbuffer);
  431. break;
  432. case ESP_GATT_DB_SECONDARY_SERVICE:
  433. ESP_LOGI(GATTC_TAG, "attr_type = SECONDARY_SERVICE,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%04x\n",
  434. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, (db + i)->uuid.uuid.uuid16);
  435. break;
  436. case ESP_GATT_DB_CHARACTERISTIC:
  437. // motor_drive_hex_to_str((char *)&(db + i)->uuid.uuid.uuid128, 16, (char *)&strbuffer);
  438. ESP_LOGI(GATTC_TAG, "attr_type = CHARACTERISTIC,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%s\n",
  439. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, strbuffer);
  440. break;
  441. case ESP_GATT_DB_DESCRIPTOR:
  442. ESP_LOGI(GATTC_TAG, "attr_type = DESCRIPTOR,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%04x\n",
  443. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, (db + i)->uuid.uuid.uuid16);
  444. break;
  445. case ESP_GATT_DB_INCLUDED_SERVICE:
  446. ESP_LOGI(GATTC_TAG, "attr_type = INCLUDED_SERVICE,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%04x\n",
  447. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, (db + i)->uuid.uuid.uuid16);
  448. break;
  449. case ESP_GATT_DB_ALL:
  450. ESP_LOGI(GATTC_TAG, "attr_type = ESP_GATT_DB_ALL,attribute_handle=%d,start_handle=%d,end_handle=%d,properties=0x%x,uuid=0x%04x\n",
  451. (db + i)->attribute_handle, (db + i)->start_handle, (db + i)->end_handle, (db + i)->properties, (db + i)->uuid.uuid.uuid16);
  452. break;
  453. default:
  454. break;
  455. }
  456. }
  457. // cmd = SPP_IDX_SPP_DATA_NTY_VAL;
  458. // ESP_LOGI("test","============cmd = %d========",cmd);
  459. // xQueueSend(cmd_reg_queue, &cmd, 10/portTICK_PERIOD_MS);
  460. break;
  461. case ESP_GATTC_SRVC_CHG_EVT:
  462. break;
  463. default:
  464. break;
  465. }
  466. }
  467. void spp_client_reg_task(void *arg)
  468. {
  469. uint16_t cmd_id;
  470. for (;;)
  471. {
  472. vTaskDelay(100 / portTICK_PERIOD_MS);
  473. if (xQueueReceive(cmd_reg_queue, &cmd_id, portMAX_DELAY))
  474. {
  475. if (db != NULL)
  476. {
  477. if (cmd_id == SPP_IDX_SPP_DATA_NTY_VAL)
  478. {
  479. ESP_LOGI(GATTC_TAG, "Index = %d,UUID = 0x%04x, handle = %d \n", cmd_id, (db + SPP_IDX_SPP_DATA_NTY_VAL)->uuid.uuid.uuid16, (db + SPP_IDX_SPP_DATA_NTY_VAL)->attribute_handle);
  480. esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda, (db + SPP_IDX_SPP_DATA_NTY_VAL)->attribute_handle);
  481. }
  482. // else if (cmd_id == SPP_IDX_SPP_STATUS_VAL)
  483. // {
  484. // ESP_LOGI(GATTC_TAG, "Index = %d,UUID = 0x%04x, handle = %d \n", cmd_id, (db + SPP_IDX_SPP_STATUS_VAL)->uuid.uuid.uuid16, (db + SPP_IDX_SPP_STATUS_VAL)->attribute_handle);
  485. // esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda, (db + SPP_IDX_SPP_STATUS_VAL)->attribute_handle);
  486. // }
  487. #ifdef SUPPORT_HEARTBEAT
  488. else if (cmd_id == SPP_IDX_SPP_HEARTBEAT_VAL)
  489. {
  490. ESP_LOGI(GATTC_TAG, "Index = %d,UUID = 0x%04x, handle = %d \n", cmd_id, (db + SPP_IDX_SPP_HEARTBEAT_VAL)->uuid.uuid.uuid16, (db + SPP_IDX_SPP_HEARTBEAT_VAL)->attribute_handle);
  491. esp_ble_gattc_register_for_notify(spp_gattc_if, gl_profile_tab[PROFILE_APP_ID].remote_bda, (db + SPP_IDX_SPP_HEARTBEAT_VAL)->attribute_handle);
  492. }
  493. #endif
  494. }
  495. }
  496. }
  497. }
  498. #ifdef SUPPORT_HEARTBEAT
  499. void spp_heart_beat_task(void *arg)
  500. {
  501. uint16_t cmd_id;
  502. for (;;)
  503. {
  504. vTaskDelay(50 / portTICK_PERIOD_MS);
  505. if (xQueueReceive(cmd_heartbeat_queue, &cmd_id, portMAX_DELAY))
  506. {
  507. while (1)
  508. {
  509. if ((is_connect == true) && (db != NULL) && ((db + SPP_IDX_SPP_HEARTBEAT_VAL)->properties & (ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_WRITE)))
  510. {
  511. esp_ble_gattc_write_char(spp_gattc_if,
  512. spp_conn_id,
  513. (db + SPP_IDX_SPP_HEARTBEAT_VAL)->attribute_handle,
  514. sizeof(heartbeat_s),
  515. (uint8_t *)heartbeat_s,
  516. ESP_GATT_WRITE_TYPE_RSP,
  517. ESP_GATT_AUTH_REQ_NONE);
  518. vTaskDelay(5000 / portTICK_PERIOD_MS);
  519. }
  520. else
  521. {
  522. ESP_LOGI(GATTC_TAG, "disconnect\n");
  523. break;
  524. }
  525. }
  526. }
  527. }
  528. }
  529. #endif
  530. void ble_client_appRegister(void)
  531. {
  532. esp_err_t status;
  533. char err_msg[20];
  534. ESP_LOGI(GATTC_TAG, "register callback");
  535. // register the scan callback function to the gap module
  536. if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK)
  537. {
  538. ESP_LOGE(GATTC_TAG, "gap register error: %s", esp_err_to_name_r(status, err_msg, sizeof(err_msg)));
  539. return;
  540. }
  541. // register the callback function to the gattc module
  542. if ((status = esp_ble_gattc_register_callback(esp_gattc_cb)) != ESP_OK)
  543. {
  544. ESP_LOGE(GATTC_TAG, "gattc register error: %s", esp_err_to_name_r(status, err_msg, sizeof(err_msg)));
  545. return;
  546. }
  547. esp_ble_gattc_app_register(PROFILE_APP_ID);
  548. esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(200);
  549. if (local_mtu_ret)
  550. {
  551. ESP_LOGE(GATTC_TAG, "set local MTU failed: %s", esp_err_to_name_r(local_mtu_ret, err_msg, sizeof(err_msg)));
  552. }
  553. cmd_reg_queue = xQueueCreate(10, sizeof(uint32_t));
  554. xTaskCreate(spp_client_reg_task, "spp_client_reg_task", 2048, NULL, 10, NULL);
  555. #ifdef SUPPORT_HEARTBEAT
  556. cmd_heartbeat_queue = xQueueCreate(10, sizeof(uint32_t));
  557. xTaskCreate(spp_heart_beat_task, "spp_heart_beat_task", 2048, NULL, 10, NULL);
  558. #endif
  559. }
  560. void uart_task(void *pvParameters)
  561. {
  562. uart_event_t event;
  563. for (;;)
  564. {
  565. // Waiting for UART event.
  566. if (xQueueReceive(spp_uart_queue, (void *)&event, (portTickType)portMAX_DELAY))
  567. {
  568. switch (event.type)
  569. {
  570. // Event of UART receving data
  571. case UART_DATA:
  572. if (event.size && (is_connect == true) && (db != NULL) && ((db + SPP_IDX_SPP_DATA_RECV_VAL)->properties & (ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_WRITE)))
  573. {
  574. uint8_t *temp = NULL;
  575. temp = (uint8_t *)malloc(sizeof(uint8_t) * event.size);
  576. if (temp == NULL)
  577. {
  578. ESP_LOGE(GATTC_TAG, "malloc failed,%s L#%d\n", __func__, __LINE__);
  579. break;
  580. }
  581. memset(temp, 0x0, event.size);
  582. uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY);
  583. esp_ble_gattc_write_char(spp_gattc_if,
  584. spp_conn_id,
  585. (db + SPP_IDX_SPP_DATA_RECV_VAL)->attribute_handle,
  586. event.size,
  587. temp,
  588. ESP_GATT_WRITE_TYPE_RSP,
  589. ESP_GATT_AUTH_REQ_NONE);
  590. free(temp);
  591. }
  592. break;
  593. default:
  594. break;
  595. }
  596. }
  597. }
  598. vTaskDelete(NULL);
  599. }
  600. static void spp_uart_init(void)
  601. {
  602. uart_config_t uart_config = {
  603. .baud_rate = 115200,
  604. .data_bits = UART_DATA_8_BITS,
  605. .parity = UART_PARITY_DISABLE,
  606. .stop_bits = UART_STOP_BITS_1,
  607. .flow_ctrl = UART_HW_FLOWCTRL_RTS,
  608. .rx_flow_ctrl_thresh = 122,
  609. .source_clk = UART_SCLK_APB,
  610. };
  611. // Install UART driver, and get the queue.
  612. uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_uart_queue, 0);
  613. // Set UART parameters
  614. uart_param_config(UART_NUM_0, &uart_config);
  615. // Set UART pins
  616. uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  617. xTaskCreate(uart_task, "uTask", 2048, (void *)UART_NUM_0, 8, NULL);
  618. }
  619. void ble_init()
  620. {
  621. esp_err_t ret;
  622. ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
  623. esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
  624. nvs_flash_init();
  625. ret = esp_bt_controller_init(&bt_cfg);
  626. if (ret)
  627. {
  628. ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
  629. return;
  630. }
  631. ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
  632. if (ret)
  633. {
  634. ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
  635. return;
  636. }
  637. ESP_LOGI(GATTC_TAG, "%s init bluetooth\n", __func__);
  638. ret = esp_bluedroid_init();
  639. if (ret)
  640. {
  641. ESP_LOGE(GATTC_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
  642. return;
  643. }
  644. ret = esp_bluedroid_enable();
  645. if (ret)
  646. {
  647. ESP_LOGE(GATTC_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
  648. return;
  649. }
  650. ble_client_appRegister();
  651. spp_uart_init();
  652. }
  653. void ble_gattc_write_char_cb(char* string)
  654. {
  655. if ((is_connect == true) && (db != NULL) && ((db + SPP_IDX_SPP_DATA_RECV_VAL)->properties & (ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_WRITE)))
  656. {
  657. esp_ble_gattc_write_char(spp_gattc_if,
  658. spp_conn_id,
  659. (db + SPP_IDX_SPP_DATA_RECV_VAL)->attribute_handle,
  660. strlen(string),
  661. (uint8_t *)string,
  662. ESP_GATT_WRITE_TYPE_RSP,
  663. ESP_GATT_AUTH_REQ_NONE);
  664. }
  665. }