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

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