医美代码重构
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.

743 lines
28 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /*
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include "ble_spp_server_demo.h"
  8. #include "driver/uart.h"
  9. #include "esp_bt.h"
  10. #include "esp_bt_defs.h"
  11. #include "esp_bt_main.h"
  12. #include "esp_gap_ble_api.h"
  13. #include "esp_gatts_api.h"
  14. #include "esp_log.h"
  15. #include "esp_system.h"
  16. #include "freertos/FreeRTOS.h"
  17. #include "freertos/event_groups.h"
  18. #include "freertos/task.h"
  19. #include "nvs_flash.h"
  20. #include "port.h"
  21. #include "string.h"
  22. static bleuart_t *s_module;
  23. static blerxcb_t s_cb;
  24. static uint16_t table_conn_id_m;
  25. static esp_gatt_if_t table_gatts_if_m;
  26. static uint16_t table_handle_m;
  27. #define GATTS_TABLE_TAG "GATTS_SPP_DEMO"
  28. #define SPP_PROFILE_NUM 1
  29. #define SPP_PROFILE_APP_IDX 0
  30. #define ESP_SPP_APP_ID 0x56
  31. #define SAMPLE_DEVICE_NAME s_module->bleName // The Device Name Characteristics in GAP
  32. #define SPP_SVC_INST_ID 0
  33. /// SPP Service
  34. static const uint16_t spp_service_uuid = 0xABF0;
  35. /// Characteristic UUID
  36. #define ESP_GATT_UUID_SPP_DATA_RECEIVE 0xABF1
  37. #define ESP_GATT_UUID_SPP_DATA_NOTIFY 0xABF2
  38. #define ESP_GATT_UUID_SPP_COMMAND_RECEIVE 0xABF3
  39. #define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF4
  40. #ifdef SUPPORT_HEARTBEAT
  41. #define ESP_GATT_UUID_SPP_HEARTBEAT 0xABF5
  42. #endif
  43. static const uint8_t spp_adv_data[23] = {
  44. /* Flags */
  45. 0x02, 0x01, 0x06,
  46. /* Complete List of 16-bit Service Class UUIDs */
  47. 0x03, 0x03, 0xF0, 0xAB,
  48. /* Complete Local Name in advertising */
  49. 0x0B, 0x09, 'y', 'i', 'm', 'e', 'i', '_', 'b', 'l', 'e'};
  50. static uint16_t spp_mtu_size = 23;
  51. static uint16_t spp_conn_id = 0xffff;
  52. static esp_gatt_if_t spp_gatts_if = 0xff;
  53. QueueHandle_t spp_uart_queue = NULL;
  54. static xQueueHandle cmd_cmd_queue = NULL;
  55. #ifdef SUPPORT_HEARTBEAT
  56. static xQueueHandle cmd_heartbeat_queue = NULL;
  57. static uint8_t heartbeat_s[9] = {'E', 's', 'p', 'r', 'e', 's', 's', 'i', 'f'};
  58. static bool enable_heart_ntf = false;
  59. static uint8_t heartbeat_count_num = 0;
  60. #endif
  61. static bool enable_data_ntf = false;
  62. static bool is_connected = false;
  63. static esp_bd_addr_t spp_remote_bda = {
  64. 0x0,
  65. };
  66. static uint16_t spp_handle_table[SPP_IDX_NB];
  67. static esp_ble_adv_params_t spp_adv_params = {
  68. .adv_int_min = 0x20,
  69. .adv_int_max = 0x40,
  70. .adv_type = ADV_TYPE_IND,
  71. .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
  72. .channel_map = ADV_CHNL_ALL,
  73. .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
  74. };
  75. struct gatts_profile_inst {
  76. esp_gatts_cb_t gatts_cb;
  77. uint16_t gatts_if;
  78. uint16_t app_id;
  79. uint16_t conn_id;
  80. uint16_t service_handle;
  81. esp_gatt_srvc_id_t service_id;
  82. uint16_t char_handle;
  83. esp_bt_uuid_t char_uuid;
  84. esp_gatt_perm_t perm;
  85. esp_gatt_char_prop_t property;
  86. uint16_t descr_handle;
  87. esp_bt_uuid_t descr_uuid;
  88. };
  89. typedef struct spp_receive_data_node {
  90. int32_t len;
  91. uint8_t *node_buff;
  92. struct spp_receive_data_node *next_node;
  93. } spp_receive_data_node_t;
  94. static spp_receive_data_node_t *temp_spp_recv_data_node_p1 = NULL;
  95. static spp_receive_data_node_t *temp_spp_recv_data_node_p2 = NULL;
  96. typedef struct spp_receive_data_buff {
  97. int32_t node_num;
  98. int32_t buff_size;
  99. spp_receive_data_node_t *first_node;
  100. } spp_receive_data_buff_t;
  101. static spp_receive_data_buff_t SppRecvDataBuff = {.node_num = 0, .buff_size = 0, .first_node = NULL};
  102. static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
  103. /* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
  104. static struct gatts_profile_inst spp_profile_tab[SPP_PROFILE_NUM] = {
  105. [SPP_PROFILE_APP_IDX] =
  106. {
  107. .gatts_cb = gatts_profile_event_handler, .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
  108. },
  109. };
  110. /*
  111. * SPP PROFILE ATTRIBUTES
  112. ****************************************************************************************
  113. */
  114. #define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
  115. static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
  116. static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
  117. static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
  118. static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
  119. static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_READ;
  120. #ifdef SUPPORT_HEARTBEAT
  121. static const uint8_t char_prop_read_write_notify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
  122. #endif
  123. /// SPP Service - data receive characteristic, read&write without response
  124. static const uint16_t spp_data_receive_uuid = ESP_GATT_UUID_SPP_DATA_RECEIVE;
  125. static const uint8_t spp_data_receive_val[20] = {0x00};
  126. /// SPP Service - data notify characteristic, notify&read
  127. static const uint16_t spp_data_notify_uuid = ESP_GATT_UUID_SPP_DATA_NOTIFY;
  128. static const uint8_t spp_data_notify_val[20] = {0x00};
  129. static const uint8_t spp_data_notify_ccc[2] = {0x00, 0x00};
  130. /// SPP Service - command characteristic, read&write without response
  131. static const uint16_t spp_command_uuid = ESP_GATT_UUID_SPP_COMMAND_RECEIVE;
  132. static const uint8_t spp_command_val[10] = {0x00};
  133. /// SPP Service - status characteristic, notify&read
  134. static const uint16_t spp_status_uuid = ESP_GATT_UUID_SPP_COMMAND_NOTIFY;
  135. static const uint8_t spp_status_val[10] = {0x00};
  136. static const uint8_t spp_status_ccc[2] = {0x00, 0x00};
  137. #ifdef SUPPORT_HEARTBEAT
  138. /// SPP Server - Heart beat characteristic, notify&write&read
  139. static const uint16_t spp_heart_beat_uuid = ESP_GATT_UUID_SPP_HEARTBEAT;
  140. static const uint8_t spp_heart_beat_val[2] = {0x00, 0x00};
  141. static const uint8_t spp_heart_beat_ccc[2] = {0x00, 0x00};
  142. #endif
  143. /// Full HRS Database Description - Used to add attributes into the database
  144. static const esp_gatts_attr_db_t spp_gatt_db[SPP_IDX_NB] = {
  145. // SPP - Service Declaration
  146. [SPP_IDX_SVC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ, sizeof(spp_service_uuid), sizeof(spp_service_uuid), (uint8_t *)&spp_service_uuid}},
  147. // SPP - data receive characteristic Declaration
  148. [SPP_IDX_SPP_DATA_RECV_CHAR] = {{ESP_GATT_AUTO_RSP},
  149. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}},
  150. // SPP - data receive characteristic Value
  151. [SPP_IDX_SPP_DATA_RECV_VAL] = {{ESP_GATT_AUTO_RSP},
  152. {ESP_UUID_LEN_16, (uint8_t *)&spp_data_receive_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, SPP_DATA_MAX_LEN, sizeof(spp_data_receive_val),
  153. (uint8_t *)spp_data_receive_val}},
  154. // SPP - data notify characteristic Declaration
  155. [SPP_IDX_SPP_DATA_NOTIFY_CHAR] = {{ESP_GATT_AUTO_RSP},
  156. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  157. // SPP - data notify characteristic Value
  158. [SPP_IDX_SPP_DATA_NTY_VAL] = {{ESP_GATT_AUTO_RSP},
  159. {ESP_UUID_LEN_16, (uint8_t *)&spp_data_notify_uuid, ESP_GATT_PERM_READ, SPP_DATA_MAX_LEN, sizeof(spp_data_notify_val), (uint8_t *)spp_data_notify_val}},
  160. // SPP - data notify characteristic - Client Characteristic Configuration Descriptor
  161. [SPP_IDX_SPP_DATA_NTF_CFG] = {{ESP_GATT_AUTO_RSP},
  162. {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_data_notify_ccc),
  163. (uint8_t *)spp_data_notify_ccc}},
  164. // SPP - command characteristic Declaration
  165. [SPP_IDX_SPP_COMMAND_CHAR] = {{ESP_GATT_AUTO_RSP},
  166. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}},
  167. // SPP - command characteristic Value
  168. [SPP_IDX_SPP_COMMAND_VAL] = {{ESP_GATT_AUTO_RSP},
  169. {ESP_UUID_LEN_16, (uint8_t *)&spp_command_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, SPP_CMD_MAX_LEN, sizeof(spp_command_val), (uint8_t *)spp_command_val}},
  170. // SPP - status characteristic Declaration
  171. [SPP_IDX_SPP_STATUS_CHAR] = {{ESP_GATT_AUTO_RSP},
  172. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},
  173. // SPP - status characteristic Value
  174. [SPP_IDX_SPP_STATUS_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_status_uuid, ESP_GATT_PERM_READ, SPP_STATUS_MAX_LEN, sizeof(spp_status_val), (uint8_t *)spp_status_val}},
  175. // SPP - status characteristic - Client Characteristic Configuration Descriptor
  176. [SPP_IDX_SPP_STATUS_CFG] = {{ESP_GATT_AUTO_RSP},
  177. {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_status_ccc),
  178. (uint8_t *)spp_status_ccc}},
  179. #ifdef SUPPORT_HEARTBEAT
  180. // SPP - Heart beat characteristic Declaration
  181. [SPP_IDX_SPP_HEARTBEAT_CHAR] = {{ESP_GATT_AUTO_RSP},
  182. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
  183. (uint8_t *)&char_prop_read_write_notify}},
  184. // SPP - Heart beat characteristic Value
  185. [SPP_IDX_SPP_HEARTBEAT_VAL] = {{ESP_GATT_AUTO_RSP},
  186. {ESP_UUID_LEN_16, (uint8_t *)&spp_heart_beat_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(spp_heart_beat_val), sizeof(spp_heart_beat_val),
  187. (uint8_t *)spp_heart_beat_val}},
  188. // SPP - Heart beat characteristic - Client Characteristic Configuration Descriptor
  189. [SPP_IDX_SPP_HEARTBEAT_CFG] = {{ESP_GATT_AUTO_RSP},
  190. {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, sizeof(uint16_t), sizeof(spp_data_notify_ccc),
  191. (uint8_t *)spp_heart_beat_ccc}},
  192. #endif
  193. };
  194. static uint8_t find_char_and_desr_index(uint16_t handle) {
  195. uint8_t error = 0xff;
  196. for (int i = 0; i < SPP_IDX_NB; i++) {
  197. if (handle == spp_handle_table[i]) {
  198. return i;
  199. }
  200. }
  201. return error;
  202. }
  203. static void blerxprocess(uint8_t *rxmessage, size_t rxsize);
  204. static bool store_wr_buffer(esp_ble_gatts_cb_param_t *p_data) {
  205. temp_spp_recv_data_node_p1 = (spp_receive_data_node_t *)malloc(sizeof(spp_receive_data_node_t));
  206. if (temp_spp_recv_data_node_p1 == NULL) {
  207. ESP_LOGI(GATTS_TABLE_TAG, "malloc error %s %d\n", __func__, __LINE__);
  208. return false;
  209. }
  210. if (temp_spp_recv_data_node_p2 != NULL) {
  211. temp_spp_recv_data_node_p2->next_node = temp_spp_recv_data_node_p1;
  212. }
  213. temp_spp_recv_data_node_p1->len = p_data->write.len;
  214. SppRecvDataBuff.buff_size += p_data->write.len;
  215. temp_spp_recv_data_node_p1->next_node = NULL;
  216. temp_spp_recv_data_node_p1->node_buff = (uint8_t *)malloc(p_data->write.len);
  217. temp_spp_recv_data_node_p2 = temp_spp_recv_data_node_p1;
  218. memcpy(temp_spp_recv_data_node_p1->node_buff, p_data->write.value, p_data->write.len);
  219. if (SppRecvDataBuff.node_num == 0) {
  220. SppRecvDataBuff.first_node = temp_spp_recv_data_node_p1;
  221. SppRecvDataBuff.node_num++;
  222. } else {
  223. SppRecvDataBuff.node_num++;
  224. }
  225. return true;
  226. }
  227. static void free_write_buffer(void) {
  228. temp_spp_recv_data_node_p1 = SppRecvDataBuff.first_node;
  229. while (temp_spp_recv_data_node_p1 != NULL) {
  230. temp_spp_recv_data_node_p2 = temp_spp_recv_data_node_p1->next_node;
  231. free(temp_spp_recv_data_node_p1->node_buff);
  232. free(temp_spp_recv_data_node_p1);
  233. temp_spp_recv_data_node_p1 = temp_spp_recv_data_node_p2;
  234. }
  235. SppRecvDataBuff.node_num = 0;
  236. SppRecvDataBuff.buff_size = 0;
  237. SppRecvDataBuff.first_node = NULL;
  238. }
  239. static void print_write_buffer(void) {
  240. temp_spp_recv_data_node_p1 = SppRecvDataBuff.first_node;
  241. while (temp_spp_recv_data_node_p1 != NULL) {
  242. uart_write_bytes(UART_NUM_0, (char *)(temp_spp_recv_data_node_p1->node_buff), temp_spp_recv_data_node_p1->len);
  243. temp_spp_recv_data_node_p1 = temp_spp_recv_data_node_p1->next_node;
  244. }
  245. }
  246. void uart_task(void *pvParameters) {
  247. uart_event_t event;
  248. uint8_t total_num = 0;
  249. uint8_t current_num = 0;
  250. for (;;) {
  251. // Waiting for UART event.
  252. if (xQueueReceive(spp_uart_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
  253. switch (event.type) {
  254. // Event of UART receving data
  255. case UART_DATA:
  256. if ((event.size) && (is_connected)) {
  257. uint8_t *temp = NULL;
  258. uint8_t *ntf_value_p = NULL;
  259. #ifdef SUPPORT_HEARTBEAT
  260. if (!enable_heart_ntf) {
  261. ESP_LOGE(GATTS_TABLE_TAG, "%s do not enable heartbeat Notify\n", __func__);
  262. break;
  263. }
  264. #endif
  265. if (!enable_data_ntf) {
  266. ESP_LOGE(GATTS_TABLE_TAG, "%s do not enable data Notify\n", __func__);
  267. break;
  268. }
  269. temp = (uint8_t *)malloc(sizeof(uint8_t) * event.size);
  270. if (temp == NULL) {
  271. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc.1 failed\n", __func__);
  272. break;
  273. }
  274. memset(temp, 0x0, event.size);
  275. uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY);
  276. if (event.size <= (spp_mtu_size - 3)) {
  277. esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL], event.size, temp, false);
  278. } else if (event.size > (spp_mtu_size - 3)) {
  279. if ((event.size % (spp_mtu_size - 7)) == 0) {
  280. total_num = event.size / (spp_mtu_size - 7);
  281. } else {
  282. total_num = event.size / (spp_mtu_size - 7) + 1;
  283. }
  284. current_num = 1;
  285. ntf_value_p = (uint8_t *)malloc((spp_mtu_size - 3) * sizeof(uint8_t));
  286. if (ntf_value_p == NULL) {
  287. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc.2 failed\n", __func__);
  288. free(temp);
  289. break;
  290. }
  291. while (current_num <= total_num) {
  292. if (current_num < total_num) {
  293. ntf_value_p[0] = '#';
  294. ntf_value_p[1] = '#';
  295. ntf_value_p[2] = total_num;
  296. ntf_value_p[3] = current_num;
  297. memcpy(ntf_value_p + 4, temp + (current_num - 1) * (spp_mtu_size - 7), (spp_mtu_size - 7));
  298. esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL], (spp_mtu_size - 3), ntf_value_p, false);
  299. } else if (current_num == total_num) {
  300. ntf_value_p[0] = '#';
  301. ntf_value_p[1] = '#';
  302. ntf_value_p[2] = total_num;
  303. ntf_value_p[3] = current_num;
  304. memcpy(ntf_value_p + 4, temp + (current_num - 1) * (spp_mtu_size - 7), (event.size - (current_num - 1) * (spp_mtu_size - 7)));
  305. esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL], (event.size - (current_num - 1) * (spp_mtu_size - 7) + 4), ntf_value_p, false);
  306. }
  307. vTaskDelay(20 / portTICK_PERIOD_MS);
  308. current_num++;
  309. }
  310. free(ntf_value_p);
  311. }
  312. free(temp);
  313. }
  314. break;
  315. default:
  316. break;
  317. }
  318. }
  319. }
  320. vTaskDelete(NULL);
  321. }
  322. static void spp_uart_init(void) {
  323. uart_config_t uart_config = {
  324. .baud_rate = 115200,
  325. .data_bits = UART_DATA_8_BITS,
  326. .parity = UART_PARITY_DISABLE,
  327. .stop_bits = UART_STOP_BITS_1,
  328. .flow_ctrl = UART_HW_FLOWCTRL_RTS,
  329. .rx_flow_ctrl_thresh = 122,
  330. .source_clk = UART_SCLK_APB,
  331. };
  332. // Install UART driver, and get the queue.
  333. uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_uart_queue, 0);
  334. // Set UART parameters
  335. uart_param_config(UART_NUM_0, &uart_config);
  336. // Set UART pins
  337. uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  338. xTaskCreate(uart_task, "uTask", 2048, (void *)UART_NUM_0, 8, NULL);
  339. }
  340. #ifdef SUPPORT_HEARTBEAT
  341. void spp_heartbeat_task(void *arg) {
  342. uint16_t cmd_id;
  343. for (;;) {
  344. vTaskDelay(50 / portTICK_PERIOD_MS);
  345. if (xQueueReceive(cmd_heartbeat_queue, &cmd_id, portMAX_DELAY)) {
  346. while (1) {
  347. heartbeat_count_num++;
  348. vTaskDelay(5000 / portTICK_PERIOD_MS);
  349. if ((heartbeat_count_num > 3) && (is_connected)) {
  350. esp_ble_gap_disconnect(spp_remote_bda);
  351. }
  352. if (is_connected && enable_heart_ntf) {
  353. esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_HEARTBEAT_VAL], sizeof(heartbeat_s), heartbeat_s, false);
  354. } else if (!is_connected) {
  355. break;
  356. }
  357. }
  358. }
  359. }
  360. vTaskDelete(NULL);
  361. }
  362. #endif
  363. void spp_cmd_task(void *arg) {
  364. uint8_t *cmd_id;
  365. for (;;) {
  366. vTaskDelay(50 / portTICK_PERIOD_MS);
  367. if (xQueueReceive(cmd_cmd_queue, &cmd_id, portMAX_DELAY)) {
  368. esp_log_buffer_char(GATTS_TABLE_TAG, (char *)(cmd_id), strlen((char *)cmd_id));
  369. free(cmd_id);
  370. }
  371. }
  372. vTaskDelete(NULL);
  373. }
  374. static void spp_task_init(void) {
  375. spp_uart_init();
  376. #ifdef SUPPORT_HEARTBEAT
  377. cmd_heartbeat_queue = xQueueCreate(10, sizeof(uint32_t));
  378. xTaskCreate(spp_heartbeat_task, "spp_heartbeat_task", 2048, NULL, 10, NULL);
  379. #endif
  380. cmd_cmd_queue = xQueueCreate(10, sizeof(uint32_t));
  381. xTaskCreate(spp_cmd_task, "spp_cmd_task", 2048, NULL, 10, NULL);
  382. }
  383. static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
  384. esp_err_t err;
  385. ESP_LOGE(GATTS_TABLE_TAG, "GAP_EVT, event %d\n", event);
  386. switch (event) {
  387. case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
  388. esp_ble_gap_start_advertising(&spp_adv_params);
  389. break;
  390. case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
  391. // advertising start complete event to indicate advertising start successfully or failed
  392. if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
  393. ESP_LOGE(GATTS_TABLE_TAG, "Advertising start failed: %s\n", esp_err_to_name(err));
  394. }
  395. break;
  396. default:
  397. break;
  398. }
  399. }
  400. static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
  401. esp_ble_gatts_cb_param_t *p_data = (esp_ble_gatts_cb_param_t *)param;
  402. uint8_t res = 0xff;
  403. ESP_LOGI(GATTS_TABLE_TAG, "event = %x\n", event);
  404. switch (event) {
  405. case ESP_GATTS_REG_EVT:
  406. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  407. esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
  408. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  409. esp_ble_gap_config_adv_data_raw((uint8_t *)spp_adv_data, sizeof(spp_adv_data));
  410. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  411. esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID);
  412. break;
  413. case ESP_GATTS_READ_EVT:
  414. res = find_char_and_desr_index(p_data->read.handle);
  415. if (res == SPP_IDX_SPP_STATUS_VAL) {
  416. // TODO:client read the status characteristic
  417. }
  418. break;
  419. case ESP_GATTS_WRITE_EVT: {
  420. res = find_char_and_desr_index(p_data->write.handle);
  421. if (p_data->write.is_prep == false) {
  422. ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT : handle = %d\n", res);
  423. if (res == SPP_IDX_SPP_COMMAND_VAL) {
  424. uint8_t *spp_cmd_buff = NULL;
  425. spp_cmd_buff = (uint8_t *)malloc((spp_mtu_size - 3) * sizeof(uint8_t));
  426. if (spp_cmd_buff == NULL) {
  427. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc failed\n", __func__);
  428. break;
  429. }
  430. memset(spp_cmd_buff, 0x0, (spp_mtu_size - 3));
  431. memcpy(spp_cmd_buff, p_data->write.value, p_data->write.len);
  432. xQueueSend(cmd_cmd_queue, &spp_cmd_buff, 10 / portTICK_PERIOD_MS);
  433. } else if (res == SPP_IDX_SPP_DATA_NTF_CFG) {
  434. if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00)) {
  435. enable_data_ntf = true;
  436. } else if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x00) && (p_data->write.value[1] == 0x00)) {
  437. enable_data_ntf = false;
  438. }
  439. }
  440. #ifdef SUPPORT_HEARTBEAT
  441. else if (res == SPP_IDX_SPP_HEARTBEAT_CFG) {
  442. if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00)) {
  443. enable_heart_ntf = true;
  444. } else if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x00) && (p_data->write.value[1] == 0x00)) {
  445. enable_heart_ntf = false;
  446. }
  447. } else if (res == SPP_IDX_SPP_HEARTBEAT_VAL) {
  448. if ((p_data->write.len == sizeof(heartbeat_s)) && (memcmp(heartbeat_s, p_data->write.value, sizeof(heartbeat_s)) == 0)) {
  449. heartbeat_count_num = 0;
  450. }
  451. }
  452. #endif
  453. else if (res == SPP_IDX_SPP_DATA_RECV_VAL) {
  454. #ifdef SPP_DEBUG_MODE
  455. esp_log_buffer_char(GATTS_TABLE_TAG, (char *)(p_data->write.value), p_data->write.len);
  456. #else
  457. // uart_write_bytes(UART_NUM_0, (char *)(p_data->write.value), p_data->write.len);
  458. blerxprocess(p_data->write.value, p_data->write.len);
  459. #endif
  460. } else {
  461. // TODO:
  462. }
  463. } else if ((p_data->write.is_prep == true) && (res == SPP_IDX_SPP_DATA_RECV_VAL)) {
  464. ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_PREP_WRITE_EVT : handle = %d\n", res);
  465. store_wr_buffer(p_data);
  466. }
  467. break;
  468. }
  469. case ESP_GATTS_EXEC_WRITE_EVT: {
  470. ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT\n");
  471. if (p_data->exec_write.exec_write_flag) {
  472. print_write_buffer();
  473. free_write_buffer();
  474. }
  475. break;
  476. }
  477. case ESP_GATTS_MTU_EVT:
  478. spp_mtu_size = p_data->mtu.mtu;
  479. break;
  480. case ESP_GATTS_CONF_EVT:
  481. break;
  482. case ESP_GATTS_UNREG_EVT:
  483. break;
  484. case ESP_GATTS_DELETE_EVT:
  485. break;
  486. case ESP_GATTS_START_EVT:
  487. break;
  488. case ESP_GATTS_STOP_EVT:
  489. break;
  490. case ESP_GATTS_CONNECT_EVT:
  491. table_conn_id_m = param->connect.conn_id;
  492. table_gatts_if_m = gatts_if;
  493. table_handle_m = spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL];
  494. spp_conn_id = p_data->connect.conn_id;
  495. spp_gatts_if = gatts_if;
  496. is_connected = true;
  497. memcpy(&spp_remote_bda, &p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
  498. #ifdef SUPPORT_HEARTBEAT
  499. uint16_t cmd = 0;
  500. xQueueSend(cmd_heartbeat_queue, &cmd, 10 / portTICK_PERIOD_MS);
  501. #endif
  502. break;
  503. case ESP_GATTS_DISCONNECT_EVT:
  504. table_conn_id_m = 0;
  505. table_gatts_if_m = 0;
  506. table_handle_m = 0;
  507. is_connected = false;
  508. enable_data_ntf = false;
  509. #ifdef SUPPORT_HEARTBEAT
  510. enable_heart_ntf = false;
  511. heartbeat_count_num = 0;
  512. #endif
  513. esp_ble_gap_start_advertising(&spp_adv_params);
  514. break;
  515. case ESP_GATTS_OPEN_EVT:
  516. break;
  517. case ESP_GATTS_CANCEL_OPEN_EVT:
  518. break;
  519. case ESP_GATTS_CLOSE_EVT:
  520. break;
  521. case ESP_GATTS_LISTEN_EVT:
  522. break;
  523. case ESP_GATTS_CONGEST_EVT:
  524. break;
  525. case ESP_GATTS_CREAT_ATTR_TAB_EVT: {
  526. ESP_LOGI(GATTS_TABLE_TAG, "The number handle =%x\n", param->add_attr_tab.num_handle);
  527. if (param->add_attr_tab.status != ESP_GATT_OK) {
  528. ESP_LOGE(GATTS_TABLE_TAG, "Create attribute table failed, error code=0x%x", param->add_attr_tab.status);
  529. } else if (param->add_attr_tab.num_handle != SPP_IDX_NB) {
  530. ESP_LOGE(GATTS_TABLE_TAG, "Create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, SPP_IDX_NB);
  531. } else {
  532. memcpy(spp_handle_table, param->add_attr_tab.handles, sizeof(spp_handle_table));
  533. esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]);
  534. }
  535. break;
  536. }
  537. default:
  538. break;
  539. }
  540. }
  541. static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
  542. ESP_LOGI(GATTS_TABLE_TAG, "EVT %d, gatts if %d\n", event, gatts_if);
  543. /* If event is register event, store the gatts_if for each profile */
  544. if (event == ESP_GATTS_REG_EVT) {
  545. if (param->reg.status == ESP_GATT_OK) {
  546. spp_profile_tab[SPP_PROFILE_APP_IDX].gatts_if = gatts_if;
  547. } else {
  548. ESP_LOGI(GATTS_TABLE_TAG, "Reg app failed, app_id %04x, status %d\n", param->reg.app_id, param->reg.status);
  549. return;
  550. }
  551. }
  552. do {
  553. int idx;
  554. for (idx = 0; idx < SPP_PROFILE_NUM; idx++) {
  555. if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
  556. gatts_if == spp_profile_tab[idx].gatts_if) {
  557. if (spp_profile_tab[idx].gatts_cb) {
  558. spp_profile_tab[idx].gatts_cb(event, gatts_if, param);
  559. }
  560. }
  561. }
  562. } while (0);
  563. }
  564. void bleuart_reg_cb(blerxcb_t cb) { s_cb = cb; }
  565. void bleuart_init(bleuart_t *bleuart) {
  566. esp_err_t ret;
  567. esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
  568. s_module = bleuart;
  569. // Initialize NVS
  570. ret = nvs_flash_init();
  571. if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  572. ESP_ERROR_CHECK(nvs_flash_erase());
  573. ret = nvs_flash_init();
  574. }
  575. ESP_ERROR_CHECK(ret);
  576. ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
  577. ret = esp_bt_controller_init(&bt_cfg);
  578. if (ret) {
  579. ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
  580. return;
  581. }
  582. ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
  583. if (ret) {
  584. ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
  585. return;
  586. }
  587. ESP_LOGI(GATTS_TABLE_TAG, "%s init bluetooth\n", __func__);
  588. ret = esp_bluedroid_init();
  589. if (ret) {
  590. ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
  591. return;
  592. }
  593. ret = esp_bluedroid_enable();
  594. if (ret) {
  595. ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
  596. return;
  597. }
  598. esp_ble_gatts_register_callback(gatts_event_handler);
  599. esp_ble_gap_register_callback(gap_event_handler);
  600. esp_ble_gatts_app_register(ESP_SPP_APP_ID);
  601. spp_task_init();
  602. return;
  603. }
  604. void blerxprocess(uint8_t *rxmessage, size_t rxsize) {
  605. if (s_module->has_rx_size + rxsize > s_module->rxbufsize - 10) {
  606. return;
  607. }
  608. if (s_module->receive_data_processing_flag) {
  609. return;
  610. }
  611. s_module->last_rx_ticket = port_get_ticket();
  612. memcpy(&s_module->rxbuf[s_module->has_rx_size], rxmessage, rxsize);
  613. s_module->has_rx_size = s_module->has_rx_size + rxsize;
  614. }
  615. void bleuart_schedule() {
  616. if (s_module->has_rx_size != 0 && port_haspassedms(s_module->last_rx_ticket) > 200) {
  617. s_module->receive_data_processing_flag = true;
  618. s_cb(s_module->rxbuf, s_module->has_rx_size);
  619. s_module->has_rx_size = 0;
  620. s_module->receive_data_processing_flag = false;
  621. }
  622. }
  623. /**
  624. * @brief
  625. *
  626. * @param buffer
  627. * @param buffer_size
  628. */
  629. void bleuart_notify_send(uint8_t *buffer, uint8_t buffer_size) {
  630. uint8_t send_times = buffer_size / 15; //发送次数
  631. uint8_t send_buffer_remainder = buffer_size % 15;
  632. uint8_t buffer_temp[16] = {0};
  633. uint8_t send_buffer_size = 0;
  634. uint8_t i = 0;
  635. uint8_t j = 0;
  636. if (table_handle_m != 0) {
  637. for (i = 0; i < send_times; i++) {
  638. for (j = 0; j < 15; j++) {
  639. buffer_temp[j] = buffer[send_buffer_size++];
  640. }
  641. esp_ble_gatts_send_indicate(table_gatts_if_m, table_conn_id_m, table_handle_m, 15, buffer_temp, false);
  642. }
  643. if (send_buffer_remainder > 0) {
  644. for (j = 0; j < send_buffer_remainder; j++) {
  645. buffer_temp[j] = buffer[send_buffer_size++];
  646. }
  647. buffer_temp[send_buffer_remainder] = 0;
  648. esp_ble_gatts_send_indicate(table_gatts_if_m, table_conn_id_m, table_handle_m, send_buffer_remainder, buffer_temp, false);
  649. }
  650. }
  651. }