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.

701 lines
27 KiB

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