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

690 lines
26 KiB

  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 "string.h"
  21. static bleuart_t *s_ble_uart_init_struct;
  22. static blerxcb_t s_cb;
  23. static uint16_t table_conn_id_m;
  24. static esp_gatt_if_t table_gatts_if_m;
  25. static uint16_t table_handle_m;
  26. #define GATTS_TABLE_TAG "GATTS_SPP_DEMO"
  27. #define SPP_PROFILE_NUM 1
  28. #define SPP_PROFILE_APP_IDX 0
  29. #define ESP_SPP_APP_ID 0x56
  30. #define SAMPLE_DEVICE_NAME "ESP_SPP_SERVER" // The Device Name Characteristics in GAP
  31. #define SPP_SVC_INST_ID 0
  32. /// SPP Service
  33. static const uint16_t spp_service_uuid = 0xABF0;
  34. /// Characteristic UUID
  35. #define ESP_GATT_UUID_SPP_DATA_RECEIVE 0xABF1
  36. #define ESP_GATT_UUID_SPP_DATA_NOTIFY 0xABF2
  37. #define ESP_GATT_UUID_SPP_COMMAND_RECEIVE 0xABF3
  38. #define ESP_GATT_UUID_SPP_COMMAND_NOTIFY 0xABF4
  39. #ifdef SUPPORT_HEARTBEAT
  40. #define ESP_GATT_UUID_SPP_HEARTBEAT 0xABF5
  41. #endif
  42. static const uint8_t spp_adv_data[23] = {
  43. /* Flags */
  44. 0x02, 0x01, 0x06,
  45. /* Complete List of 16-bit Service Class UUIDs */
  46. 0x03, 0x03, 0xF0, 0xAB,
  47. /* Complete Local Name in advertising */
  48. 0x0F, 0x09, 'E', 'S', 'P', '_', 'S', 'P', 'P', '_', 'S', 'E', 'R', 'V', 'E', 'R'};
  49. static uint16_t spp_mtu_size = 23;
  50. static uint16_t spp_conn_id = 0xffff;
  51. static esp_gatt_if_t spp_gatts_if = 0xff;
  52. QueueHandle_t spp_uart_queue = NULL;
  53. static xQueueHandle cmd_cmd_queue = NULL;
  54. #ifdef SUPPORT_HEARTBEAT
  55. static xQueueHandle cmd_heartbeat_queue = NULL;
  56. static uint8_t heartbeat_s[9] = {'E', 's', 'p', 'r', 'e', 's', 's', 'i', 'f'};
  57. static bool enable_heart_ntf = false;
  58. static uint8_t heartbeat_count_num = 0;
  59. #endif
  60. static bool enable_data_ntf = false;
  61. static bool is_connected = false;
  62. static esp_bd_addr_t spp_remote_bda = {
  63. 0x0,
  64. };
  65. static uint16_t spp_handle_table[SPP_IDX_NB];
  66. static esp_ble_adv_params_t spp_adv_params = {
  67. .adv_int_min = 0x20,
  68. .adv_int_max = 0x40,
  69. .adv_type = ADV_TYPE_IND,
  70. .own_addr_type = BLE_ADDR_TYPE_PUBLIC,
  71. .channel_map = ADV_CHNL_ALL,
  72. .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
  73. };
  74. struct gatts_profile_inst {
  75. esp_gatts_cb_t gatts_cb;
  76. uint16_t gatts_if;
  77. uint16_t app_id;
  78. uint16_t conn_id;
  79. uint16_t service_handle;
  80. esp_gatt_srvc_id_t service_id;
  81. uint16_t char_handle;
  82. esp_bt_uuid_t char_uuid;
  83. esp_gatt_perm_t perm;
  84. esp_gatt_char_prop_t property;
  85. uint16_t descr_handle;
  86. esp_bt_uuid_t descr_uuid;
  87. };
  88. typedef struct spp_receive_data_node {
  89. int32_t len;
  90. uint8_t *node_buff;
  91. struct spp_receive_data_node *next_node;
  92. } spp_receive_data_node_t;
  93. static spp_receive_data_node_t *temp_spp_recv_data_node_p1 = NULL;
  94. static spp_receive_data_node_t *temp_spp_recv_data_node_p2 = NULL;
  95. typedef struct spp_receive_data_buff {
  96. int32_t node_num;
  97. int32_t buff_size;
  98. spp_receive_data_node_t *first_node;
  99. } spp_receive_data_buff_t;
  100. static spp_receive_data_buff_t SppRecvDataBuff = {.node_num = 0, .buff_size = 0, .first_node = NULL};
  101. 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);
  102. /* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
  103. static struct gatts_profile_inst spp_profile_tab[SPP_PROFILE_NUM] = {
  104. [SPP_PROFILE_APP_IDX] =
  105. {
  106. .gatts_cb = gatts_profile_event_handler, .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
  107. },
  108. };
  109. /*
  110. * SPP PROFILE ATTRIBUTES
  111. ****************************************************************************************
  112. */
  113. #define CHAR_DECLARATION_SIZE (sizeof(uint8_t))
  114. static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
  115. static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
  116. static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
  117. static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
  118. static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE_NR | ESP_GATT_CHAR_PROP_BIT_READ;
  119. #ifdef SUPPORT_HEARTBEAT
  120. 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;
  121. #endif
  122. /// SPP Service - data receive characteristic, read&write without response
  123. static const uint16_t spp_data_receive_uuid = ESP_GATT_UUID_SPP_DATA_RECEIVE;
  124. static const uint8_t spp_data_receive_val[20] = {0x00};
  125. /// SPP Service - data notify characteristic, notify&read
  126. static const uint16_t spp_data_notify_uuid = ESP_GATT_UUID_SPP_DATA_NOTIFY;
  127. static const uint8_t spp_data_notify_val[20] = {0x00};
  128. static const uint8_t spp_data_notify_ccc[2] = {0x00, 0x00};
  129. /// SPP Service - command characteristic, read&write without response
  130. static const uint16_t spp_command_uuid = ESP_GATT_UUID_SPP_COMMAND_RECEIVE;
  131. static const uint8_t spp_command_val[10] = {0x00};
  132. /// SPP Service - status characteristic, notify&read
  133. static const uint16_t spp_status_uuid = ESP_GATT_UUID_SPP_COMMAND_NOTIFY;
  134. static const uint8_t spp_status_val[10] = {0x00};
  135. static const uint8_t spp_status_ccc[2] = {0x00, 0x00};
  136. #ifdef SUPPORT_HEARTBEAT
  137. /// SPP Server - Heart beat characteristic, notify&write&read
  138. static const uint16_t spp_heart_beat_uuid = ESP_GATT_UUID_SPP_HEARTBEAT;
  139. static const uint8_t spp_heart_beat_val[2] = {0x00, 0x00};
  140. static const uint8_t spp_heart_beat_ccc[2] = {0x00, 0x00};
  141. #endif
  142. /// Full HRS Database Description - Used to add attributes into the database
  143. static const esp_gatts_attr_db_t spp_gatt_db[SPP_IDX_NB] = {
  144. // SPP - Service Declaration
  145. [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}},
  146. // SPP - data receive characteristic Declaration
  147. [SPP_IDX_SPP_DATA_RECV_CHAR] = {{ESP_GATT_AUTO_RSP},
  148. {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}},
  149. // SPP - data receive characteristic Value
  150. [SPP_IDX_SPP_DATA_RECV_VAL] = {{ESP_GATT_AUTO_RSP},
  151. {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),
  152. (uint8_t *)spp_data_receive_val}},
  153. // SPP - data notify characteristic Declaration
  154. [SPP_IDX_SPP_DATA_NOTIFY_CHAR] = {{ESP_GATT_AUTO_RSP},
  155. {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}},
  156. // SPP - data notify characteristic Value
  157. [SPP_IDX_SPP_DATA_NTY_VAL] = {{ESP_GATT_AUTO_RSP},
  158. {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}},
  159. // SPP - data notify characteristic - Client Characteristic Configuration Descriptor
  160. [SPP_IDX_SPP_DATA_NTF_CFG] = {{ESP_GATT_AUTO_RSP},
  161. {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),
  162. (uint8_t *)spp_data_notify_ccc}},
  163. // SPP - command characteristic Declaration
  164. [SPP_IDX_SPP_COMMAND_CHAR] = {{ESP_GATT_AUTO_RSP},
  165. {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}},
  166. // SPP - command characteristic Value
  167. [SPP_IDX_SPP_COMMAND_VAL] = {{ESP_GATT_AUTO_RSP},
  168. {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}},
  169. // SPP - status characteristic Declaration
  170. [SPP_IDX_SPP_STATUS_CHAR] = {{ESP_GATT_AUTO_RSP},
  171. {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}},
  172. // SPP - status characteristic Value
  173. [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}},
  174. // SPP - status characteristic - Client Characteristic Configuration Descriptor
  175. [SPP_IDX_SPP_STATUS_CFG] = {{ESP_GATT_AUTO_RSP},
  176. {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),
  177. (uint8_t *)spp_status_ccc}},
  178. #ifdef SUPPORT_HEARTBEAT
  179. // SPP - Heart beat characteristic Declaration
  180. [SPP_IDX_SPP_HEARTBEAT_CHAR] = {{ESP_GATT_AUTO_RSP},
  181. {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE,
  182. (uint8_t *)&char_prop_read_write_notify}},
  183. // SPP - Heart beat characteristic Value
  184. [SPP_IDX_SPP_HEARTBEAT_VAL] = {{ESP_GATT_AUTO_RSP},
  185. {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),
  186. (uint8_t *)spp_heart_beat_val}},
  187. // SPP - Heart beat characteristic - Client Characteristic Configuration Descriptor
  188. [SPP_IDX_SPP_HEARTBEAT_CFG] = {{ESP_GATT_AUTO_RSP},
  189. {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),
  190. (uint8_t *)spp_heart_beat_ccc}},
  191. #endif
  192. };
  193. static uint8_t find_char_and_desr_index(uint16_t handle) {
  194. uint8_t error = 0xff;
  195. for (int i = 0; i < SPP_IDX_NB; i++) {
  196. if (handle == spp_handle_table[i]) {
  197. return i;
  198. }
  199. }
  200. return error;
  201. }
  202. static bool store_wr_buffer(esp_ble_gatts_cb_param_t *p_data) {
  203. temp_spp_recv_data_node_p1 = (spp_receive_data_node_t *)malloc(sizeof(spp_receive_data_node_t));
  204. if (temp_spp_recv_data_node_p1 == NULL) {
  205. ESP_LOGI(GATTS_TABLE_TAG, "malloc error %s %d\n", __func__, __LINE__);
  206. return false;
  207. }
  208. if (temp_spp_recv_data_node_p2 != NULL) {
  209. temp_spp_recv_data_node_p2->next_node = temp_spp_recv_data_node_p1;
  210. }
  211. temp_spp_recv_data_node_p1->len = p_data->write.len;
  212. SppRecvDataBuff.buff_size += p_data->write.len;
  213. temp_spp_recv_data_node_p1->next_node = NULL;
  214. temp_spp_recv_data_node_p1->node_buff = (uint8_t *)malloc(p_data->write.len);
  215. temp_spp_recv_data_node_p2 = temp_spp_recv_data_node_p1;
  216. memcpy(temp_spp_recv_data_node_p1->node_buff, p_data->write.value, p_data->write.len);
  217. if (SppRecvDataBuff.node_num == 0) {
  218. SppRecvDataBuff.first_node = temp_spp_recv_data_node_p1;
  219. SppRecvDataBuff.node_num++;
  220. } else {
  221. SppRecvDataBuff.node_num++;
  222. }
  223. return true;
  224. }
  225. static void free_write_buffer(void) {
  226. temp_spp_recv_data_node_p1 = SppRecvDataBuff.first_node;
  227. while (temp_spp_recv_data_node_p1 != NULL) {
  228. temp_spp_recv_data_node_p2 = temp_spp_recv_data_node_p1->next_node;
  229. free(temp_spp_recv_data_node_p1->node_buff);
  230. free(temp_spp_recv_data_node_p1);
  231. temp_spp_recv_data_node_p1 = temp_spp_recv_data_node_p2;
  232. }
  233. SppRecvDataBuff.node_num = 0;
  234. SppRecvDataBuff.buff_size = 0;
  235. SppRecvDataBuff.first_node = NULL;
  236. }
  237. static void print_write_buffer(void) {
  238. temp_spp_recv_data_node_p1 = SppRecvDataBuff.first_node;
  239. while (temp_spp_recv_data_node_p1 != NULL) {
  240. uart_write_bytes(UART_NUM_0, (char *)(temp_spp_recv_data_node_p1->node_buff), temp_spp_recv_data_node_p1->len);
  241. temp_spp_recv_data_node_p1 = temp_spp_recv_data_node_p1->next_node;
  242. }
  243. }
  244. void uart_task(void *pvParameters) {
  245. uart_event_t event;
  246. uint8_t total_num = 0;
  247. uint8_t current_num = 0;
  248. for (;;) {
  249. // Waiting for UART event.
  250. if (xQueueReceive(spp_uart_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
  251. switch (event.type) {
  252. // Event of UART receving data
  253. case UART_DATA:
  254. if ((event.size) && (is_connected)) {
  255. uint8_t *temp = NULL;
  256. uint8_t *ntf_value_p = NULL;
  257. #ifdef SUPPORT_HEARTBEAT
  258. if (!enable_heart_ntf) {
  259. ESP_LOGE(GATTS_TABLE_TAG, "%s do not enable heartbeat Notify\n", __func__);
  260. break;
  261. }
  262. #endif
  263. if (!enable_data_ntf) {
  264. ESP_LOGE(GATTS_TABLE_TAG, "%s do not enable data Notify\n", __func__);
  265. break;
  266. }
  267. temp = (uint8_t *)malloc(sizeof(uint8_t) * event.size);
  268. if (temp == NULL) {
  269. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc.1 failed\n", __func__);
  270. break;
  271. }
  272. memset(temp, 0x0, event.size);
  273. uart_read_bytes(UART_NUM_0, temp, event.size, portMAX_DELAY);
  274. if (event.size <= (spp_mtu_size - 3)) {
  275. esp_ble_gatts_send_indicate(spp_gatts_if, spp_conn_id, spp_handle_table[SPP_IDX_SPP_DATA_NTY_VAL], event.size, temp, false);
  276. } else if (event.size > (spp_mtu_size - 3)) {
  277. if ((event.size % (spp_mtu_size - 7)) == 0) {
  278. total_num = event.size / (spp_mtu_size - 7);
  279. } else {
  280. total_num = event.size / (spp_mtu_size - 7) + 1;
  281. }
  282. current_num = 1;
  283. ntf_value_p = (uint8_t *)malloc((spp_mtu_size - 3) * sizeof(uint8_t));
  284. if (ntf_value_p == NULL) {
  285. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc.2 failed\n", __func__);
  286. free(temp);
  287. break;
  288. }
  289. while (current_num <= total_num) {
  290. if (current_num < total_num) {
  291. ntf_value_p[0] = '#';
  292. ntf_value_p[1] = '#';
  293. ntf_value_p[2] = total_num;
  294. ntf_value_p[3] = current_num;
  295. memcpy(ntf_value_p + 4, temp + (current_num - 1) * (spp_mtu_size - 7), (spp_mtu_size - 7));
  296. 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);
  297. } else if (current_num == total_num) {
  298. ntf_value_p[0] = '#';
  299. ntf_value_p[1] = '#';
  300. ntf_value_p[2] = total_num;
  301. ntf_value_p[3] = current_num;
  302. memcpy(ntf_value_p + 4, temp + (current_num - 1) * (spp_mtu_size - 7), (event.size - (current_num - 1) * (spp_mtu_size - 7)));
  303. 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);
  304. }
  305. vTaskDelay(20 / portTICK_PERIOD_MS);
  306. current_num++;
  307. }
  308. free(ntf_value_p);
  309. }
  310. free(temp);
  311. }
  312. break;
  313. default:
  314. break;
  315. }
  316. }
  317. }
  318. vTaskDelete(NULL);
  319. }
  320. static void spp_uart_init(void) {
  321. uart_config_t uart_config = {
  322. .baud_rate = 115200,
  323. .data_bits = UART_DATA_8_BITS,
  324. .parity = UART_PARITY_DISABLE,
  325. .stop_bits = UART_STOP_BITS_1,
  326. .flow_ctrl = UART_HW_FLOWCTRL_RTS,
  327. .rx_flow_ctrl_thresh = 122,
  328. .source_clk = UART_SCLK_APB,
  329. };
  330. // Install UART driver, and get the queue.
  331. uart_driver_install(UART_NUM_0, 4096, 8192, 10, &spp_uart_queue, 0);
  332. // Set UART parameters
  333. uart_param_config(UART_NUM_0, &uart_config);
  334. // Set UART pins
  335. uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  336. xTaskCreate(uart_task, "uTask", 2048, (void *)UART_NUM_0, 8, NULL);
  337. }
  338. #ifdef SUPPORT_HEARTBEAT
  339. void spp_heartbeat_task(void *arg) {
  340. uint16_t cmd_id;
  341. for (;;) {
  342. vTaskDelay(50 / portTICK_PERIOD_MS);
  343. if (xQueueReceive(cmd_heartbeat_queue, &cmd_id, portMAX_DELAY)) {
  344. while (1) {
  345. heartbeat_count_num++;
  346. vTaskDelay(5000 / portTICK_PERIOD_MS);
  347. if ((heartbeat_count_num > 3) && (is_connected)) {
  348. esp_ble_gap_disconnect(spp_remote_bda);
  349. }
  350. if (is_connected && enable_heart_ntf) {
  351. 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);
  352. } else if (!is_connected) {
  353. break;
  354. }
  355. }
  356. }
  357. }
  358. vTaskDelete(NULL);
  359. }
  360. #endif
  361. void spp_cmd_task(void *arg) {
  362. uint8_t *cmd_id;
  363. for (;;) {
  364. vTaskDelay(50 / portTICK_PERIOD_MS);
  365. if (xQueueReceive(cmd_cmd_queue, &cmd_id, portMAX_DELAY)) {
  366. esp_log_buffer_char(GATTS_TABLE_TAG, (char *)(cmd_id), strlen((char *)cmd_id));
  367. free(cmd_id);
  368. }
  369. }
  370. vTaskDelete(NULL);
  371. }
  372. static void spp_task_init(void) {
  373. spp_uart_init();
  374. #ifdef SUPPORT_HEARTBEAT
  375. cmd_heartbeat_queue = xQueueCreate(10, sizeof(uint32_t));
  376. xTaskCreate(spp_heartbeat_task, "spp_heartbeat_task", 2048, NULL, 10, NULL);
  377. #endif
  378. cmd_cmd_queue = xQueueCreate(10, sizeof(uint32_t));
  379. xTaskCreate(spp_cmd_task, "spp_cmd_task", 2048, NULL, 10, NULL);
  380. }
  381. static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
  382. esp_err_t err;
  383. ESP_LOGE(GATTS_TABLE_TAG, "GAP_EVT, event %d\n", event);
  384. switch (event) {
  385. case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
  386. esp_ble_gap_start_advertising(&spp_adv_params);
  387. break;
  388. case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
  389. // advertising start complete event to indicate advertising start successfully or failed
  390. if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
  391. ESP_LOGE(GATTS_TABLE_TAG, "Advertising start failed: %s\n", esp_err_to_name(err));
  392. }
  393. break;
  394. default:
  395. break;
  396. }
  397. }
  398. 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) {
  399. esp_ble_gatts_cb_param_t *p_data = (esp_ble_gatts_cb_param_t *)param;
  400. uint8_t res = 0xff;
  401. ESP_LOGI(GATTS_TABLE_TAG, "event = %x\n", event);
  402. switch (event) {
  403. case ESP_GATTS_REG_EVT:
  404. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  405. esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
  406. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  407. esp_ble_gap_config_adv_data_raw((uint8_t *)spp_adv_data, sizeof(spp_adv_data));
  408. ESP_LOGI(GATTS_TABLE_TAG, "%s %d\n", __func__, __LINE__);
  409. esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, SPP_SVC_INST_ID);
  410. break;
  411. case ESP_GATTS_READ_EVT:
  412. res = find_char_and_desr_index(p_data->read.handle);
  413. if (res == SPP_IDX_SPP_STATUS_VAL) {
  414. // TODO:client read the status characteristic
  415. }
  416. break;
  417. case ESP_GATTS_WRITE_EVT: {
  418. res = find_char_and_desr_index(p_data->write.handle);
  419. if (p_data->write.is_prep == false) {
  420. ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT : handle = %d\n", res);
  421. if (res == SPP_IDX_SPP_COMMAND_VAL) {
  422. uint8_t *spp_cmd_buff = NULL;
  423. spp_cmd_buff = (uint8_t *)malloc((spp_mtu_size - 3) * sizeof(uint8_t));
  424. if (spp_cmd_buff == NULL) {
  425. ESP_LOGE(GATTS_TABLE_TAG, "%s malloc failed\n", __func__);
  426. break;
  427. }
  428. memset(spp_cmd_buff, 0x0, (spp_mtu_size - 3));
  429. memcpy(spp_cmd_buff, p_data->write.value, p_data->write.len);
  430. xQueueSend(cmd_cmd_queue, &spp_cmd_buff, 10 / portTICK_PERIOD_MS);
  431. } else if (res == SPP_IDX_SPP_DATA_NTF_CFG) {
  432. if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00)) {
  433. enable_data_ntf = true;
  434. } else if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x00) && (p_data->write.value[1] == 0x00)) {
  435. enable_data_ntf = false;
  436. }
  437. }
  438. #ifdef SUPPORT_HEARTBEAT
  439. else if (res == SPP_IDX_SPP_HEARTBEAT_CFG) {
  440. if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x01) && (p_data->write.value[1] == 0x00)) {
  441. enable_heart_ntf = true;
  442. } else if ((p_data->write.len == 2) && (p_data->write.value[0] == 0x00) && (p_data->write.value[1] == 0x00)) {
  443. enable_heart_ntf = false;
  444. }
  445. } else if (res == SPP_IDX_SPP_HEARTBEAT_VAL) {
  446. if ((p_data->write.len == sizeof(heartbeat_s)) && (memcmp(heartbeat_s, p_data->write.value, sizeof(heartbeat_s)) == 0)) {
  447. heartbeat_count_num = 0;
  448. }
  449. }
  450. #endif
  451. else if (res == SPP_IDX_SPP_DATA_RECV_VAL) {
  452. #ifdef SPP_DEBUG_MODE
  453. esp_log_buffer_char(GATTS_TABLE_TAG, (char *)(p_data->write.value), p_data->write.len);
  454. #else
  455. // uart_write_bytes(UART_NUM_0, (char *)(p_data->write.value), p_data->write.len);
  456. if (s_ble_uart_init_struct->receive_data_processing_flag == false) {
  457. s_cb(p_data->write.value, p_data->write.len);
  458. }
  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 ble_spp_server_demo_app_main(bleuart_t *bleuart) {
  566. esp_err_t ret;
  567. esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
  568. s_ble_uart_init_struct = 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. }