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.

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