Bluetooth gatt server ======================================= 1. Project Overview -------------------------- This project is used for demonstrating bluetooth gatt server, show you the following operation: - how to config ble advertising pararmeters and datas, how to start the advertising. - how to make up a gatt service database and process the att read write request. 2. Hardware Requirements ---------------------------- Beken development board. 3. Build ---------------------------- Enter the following command in the Armino root directory to compile: > make bk72xx PROJECT=bluetooth/gatt_server 4. Connect UART ---------------------------- UART0 is used for: - BKFIL to download images - Logging and Cli commands 5. Flash all-app.bin ---------------------------- Flash Armino/build/gatt_server/bk72xx/all-app.bin to the board by the tool BKFIL. 6. Play and Output ---------------------------------- Restart the board, the gatt_server will advertise automatically with the name ``doorbell_xxxxxx``, then you can use another board falshed with project gatt_client or other ble tools to connect with this board. 6.1 Initiate Log *********************************** :: [15:51:01.911]IN←◆ble:I(816):ble create new db ble:I(820):ble_env->start_hdl = 0x10 ble:I(820):[gapm_profile_added_ind_handler] prf_task_id:0x6e,prf_task_nb:9,start_hdl:16,state:0x1 ble:I(820):conidx:0x0,role:0x0,dest_id:0x3,src_id:0x8,param->status:0x0 BLE-GATT:I(820):cd_ind:prf_id:10, status:0 ble:I(820):[gapm_cmp_evt_handler]actv_idx:0 conidx:0,operation:0x1b,status:0x0 BLE-GATT:I(820):create gatt db success BLE-GATT:I(820):gatt_server_demo_init, dev_name:doorbell_7FCC5F, ret:15 BLE-GATT:I(822):adv data length :28 ble:I(828):[gapm_cmp_evt_handler]actv_idx:0 conidx:0,operation:0xa0,status:0x0 BLE-GATT:I(828):set adv paramters success ble:I(836):[gapm_cmp_evt_handler]actv_idx:0 conidx:0,operation:0xa9,status:0x0 BLE-GATT:I(836):set adv data success ble:I(842):[gapm_cmp_evt_handler]actv_idx:0 conidx:0,operation:0xa4,status:0x0 BLE-GATT:I(842):sart adv success BLE-GATT:I(842):gatt_server_demo_init success 6.2 Connected Log *********************************** :: [15:51:30.373]IN←◆tempd:I(29278):change config, interval=15, threshold=46, dist=0 [15:51:45.504]IN←◆ble:I(44408):[gapc_connection_req_ind_handler]conidx:0,dest_id:0x3,con_peer_addr:63:2b:d8:b6:fd:50 ble:I(44408):[gapc_connection_req_ind_handler]ble_slave conn_idx:0 ble:I(44408):addr:50:fd:b6:d8:2b:63 BLE-GATT:I(44408):c_ind:conn_idx:0, addr_type:1, peer_addr:63:2b:d8:b6:fd:50 ble:I(44410):[gapm_activity_stopped_ind_handler]conidx:0 [15:51:45.606]IN←◆ble:I(44510):gapc_le_pkt_size_ind_handler msgid:0xe2c,dest_id:0x3,src_id:0x7 ble:I(44510):conidx:0,ble:I(44510):1max_rx_octets = 27 ble:I(44510):1max_rx_time = 328 ble:I(44510):1max_tx_octets = 251 ble:I(44510):1max_tx_time = 2120 7. Work flow chart ---------------------------------- gatt server demo work flow chart: .. figure:: ../../../../_static/gatt_server_flow_chart.png :align: center :alt: gatt server demo work flow chart :figclass: align-center Figure 1. gatt server demo work flow 8. Cli Command ---------------------------------- | The project gatt_server supports the following commands through uart0: | ``ble_gatts help`` : get the list of commands. | ``ble_gatts notify`` : launch the att notify request after connected by other device. | ``ble_gatts adv_en 1`` : start the advertising, the advertising will stop once connected by other device. | ``ble_gatts adv_en 0`` : stop the advertising. 8.1 Command Log *********************************** - ble_gatts notify :: [15:52:00.140]OUT→◇ble_gatts notify [15:52:00.145]IN←◆ble_gatts notify os:I(59050):create shell_handle, tcb=28066de8, stack=[28072a70-28073e70:5120], prio=5 $BLE GATTS RSP:OK //gatt client demo project log [11:38:27.008]IN←◆BLE-GATT:I(3446536):CHARAC_NOTIFY|CHARAC_INDICATE, handle:0x12, len:5 BLE-GATT:I(3446536): ================== BLE-GATT:I(3446536): BLE-GATT:I(3446536): ================== BLE-GATT:I(3446536):0x00 0x00 0x00 0x00 BLE-GATT:I(3446536): ================== - ble_gatts adv_en 1 :: [15:54:26.103]OUT→◇ble_gatts adv_en 1 [15:54:26.109]IN←◆ble_gatts adv_en 1 os:I(205014):create shell_handle, tcb=28066de8, stack=[28072a70-28073e70:5120], prio=5 ble:I(205022):[gapm_cmp_evt_handler]actv_idx:0 conidx:0,operation:0xa4,status:0x0 BLE-GATT:I(205022):sart adv success BLE GATTS RSP:OK 9. Advertising and gatt service API ---------------------------------------- please refer to the souce code in the flie ``/projects/bluetooth/gatt_server/main/gatt_server_demo.c``. - setp1. register ble event callback function :: static void ble_cmd_cb(ble_cmd_t cmd, ble_cmd_param_t *param) { s_at_cmd_status = param->status; switch (cmd) { case BLE_CREATE_ADV: case BLE_SET_ADV_DATA: case BLE_SET_RSP_DATA: case BLE_START_ADV: case BLE_STOP_ADV: case BLE_CREATE_SCAN: case BLE_START_SCAN: case BLE_STOP_SCAN: case BLE_INIT_CREATE: case BLE_INIT_START_CONN: case BLE_INIT_STOP_CONN: case BLE_CONN_DIS_CONN: case BLE_CONN_UPDATE_PARAM: case BLE_DELETE_ADV: case BLE_DELETE_SCAN: case BLE_CONN_READ_PHY: case BLE_CONN_SET_PHY: case BLE_CONN_UPDATE_MTU: if (gatt_sema != NULL) rtos_set_semaphore( &gatt_sema ); break; default: break; } } void ble_at_notice_cb(ble_notice_t notice, void *param) { switch (notice) { //setp9 setp10 case BLE_5_WRITE_EVENT: //setp7 case BLE_5_READ_EVENT: //setp8 ble_read_req_t *r_req = (ble_read_req_t *)param; bk_ble_read_response_value(r_req->conn_idx, sizeof(tmp), &tmp, r_req->prf_id, r_req->att_idx); break; //setp6 case BLE_5_CONNECT_EVENT: case BLE_5_DISCONNECT_EVENT: .... break; } } bk_ble_set_notice_cb(ble_gatts_notice_cb); - step2. make up a gatt database please make up the database before start the advertising. :: #define GATTS_SERVICE_UUID (0xFA00) #define GATTS_CHARA_PROPERTIES_UUID (0xEA01) #define GATTS_CHARA_N1_UUID (0xEA02) #define GATTS_CHARA_N2_UUID (0xEA05) #define GATTS_CHARA_N3_UUID (0xEA06) #define DECL_PRIMARY_SERVICE_128 {0x00,0x28,0,0,0,0,0,0,0,0,0,0,0,0,0,0} #define DECL_CHARACTERISTIC_128 {0x03,0x28,0,0,0,0,0,0,0,0,0,0,0,0,0,0} #define DESC_CLIENT_CHAR_CFG_128 {0x02,0x29,0,0,0,0,0,0,0,0,0,0,0,0,0,0} //database static ble_attm_desc_t gatts_service_db[GATTS_IDX_NB] = { // Service Declaration [GATTS_IDX_SVC] = {DECL_PRIMARY_SERVICE_128, GATTS_SERVICE_UUID >> 8}, BK_BLE_PERM_SET(RD, ENABLE), 0, 0}, [GATTS_IDX_CHAR_DECL] = {DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0}, // Characteristic Value [GATTS_IDX_CHAR_VALUE] = {{GATTS_CHARA_PROPERTIES_UUID & 0xFF, GATTS_CHARA_PROPERTIES_UUID >> 8}, BK_BLE_PERM_SET(NTF, ENABLE), BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_16), 128}, //Client Characteristic Configuration Descriptor [GATTS_IDX_CHAR_DESC] = {DESC_CLIENT_CHAR_CFG_128, BK_BLE_PERM_SET(RD, ENABLE) | BK_BLE_PERM_SET(WRITE_REQ, ENABLE), 0, 0}, //opreation [GATTS_IDX_CHAR_N1_DECL] = {DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0}, [GATTS_IDX_CHAR_N1_VALUE] = {{GATTS_CHARA_N1_UUID & 0xFF, GATTS_CHARA_N1_UUID >> 8, 0}, BK_BLE_PERM_SET(WRITE_REQ, ENABLE), BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_16), 128}, //s_v [GATTS_IDX_CHAR_N2_DECL] = {DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0}, [GATTS_IDX_CHAR_N2_VALUE] = {{GATTS_CHARA_N2_UUID & 0xFF, GATTS_CHARA_N2_UUID >> 8, 0}, BK_BLE_PERM_SET(WRITE_REQ, ENABLE) | BK_BLE_PERM_SET(RD, ENABLE), BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_16), 128}, //p_v [GATTS_IDX_CHAR_N3_DECL] = {DECL_CHARACTERISTIC_128, BK_BLE_PERM_SET(RD, ENABLE), 0, 0}, [GATTS_IDX_CHAR_N3_VALUE] = {{GATTS_CHARA_N3_UUID & 0xFF, GATTS_CHARA_N3_UUID >> 8, 0}, BK_BLE_PERM_SET(WRITE_REQ, ENABLE) | BK_BLE_PERM_SET(RD, ENABLE), BK_BLE_PERM_SET(RI, ENABLE) | BK_BLE_PERM_SET(UUID_LEN, UUID_16), 128}, }; //create the service database ble_db_cfg.att_db = (ble_attm_desc_t *)gatts_service_db; ble_db_cfg.att_db_nb = GATTS_IDX_NB; ble_db_cfg.prf_task_id = PRF_TASK_ID_GATTS; ble_db_cfg.start_hdl = 0; ble_db_cfg.svc_perm = BK_BLE_PERM_SET(SVC_UUID_LEN, UUID_16); ble_db_cfg.uuid[0] = GATTS_SERVICE_UUID & 0xFF; ble_db_cfg.uuid[1] = GATTS_SERVICE_UUID >> 8; ret = bk_ble_create_db(&ble_db_cfg); if (ret == BK_OK) { LOGI("create gatt db success\n"); } - setp3 step4 setp5. start a advertising :: ble_adv_param_t adv_param; int actv_idx = 0; bt_err_t ret = BK_FAIL; /* set adv paramters */ os_memset(&adv_param, 0, sizeof(ble_adv_param_t)); adv_param.chnl_map = ADV_ALL_CHNLS; adv_param.adv_intv_min = BLE_GATTS_ADV_INTERVAL_MIN; adv_param.adv_intv_max = BLE_GATTS_ADV_INTERVAL_MAX; adv_param.own_addr_type = OWN_ADDR_TYPE_PUBLIC_OR_STATIC_ADDR; adv_param.adv_type = ADV_TYPE_LEGACY; adv_param.adv_prop = ADV_PROP_CONNECTABLE_BIT | ADV_PROP_SCANNABLE_BIT; adv_param.prim_phy = INIT_PHY_TYPE_LE_1M; adv_param.second_phy = INIT_PHY_TYPE_LE_1M; ret = bk_ble_create_advertising(actv_idx, &adv_param, ble_cmd_cb); if (ret != BK_ERR_BLE_SUCCESS) { LOGE("config adv paramters failed %d\n", ret); goto error; } ret = rtos_get_semaphore(&gatt_sema, AT_SYNC_CMD_TIMEOUT_MS); /* set adv data */ uint8_t adv_data[ADV_MAX_SIZE] = {0}; uint8_t adv_index = 0; uint8_t len_index = 0; uint8_t mac[6]; int ret; /* flags */ len_index = adv_index; adv_data[adv_index++] = 0x00; adv_data[adv_index++] = ADV_TYPE_FLAGS; adv_data[adv_index++] = 0x06; adv_data[len_index] = 2; /* local name */ bk_bluetooth_get_address(mac); len_index = adv_index; adv_data[adv_index++] = 0x00; adv_data[adv_index++] = ADV_TYPE_LOCAL_NAME; ret = sprintf((char *)&adv_data[adv_index], "%s_%02X%02X%02X", ADV_NAME_HEAD, mac[0], mac[1], mac[2]); bk_ble_appm_set_dev_name(ret, &adv_data[adv_index]); BLEGATTS_LOGI("%s, dev_name:%s, ret:%d \n", __func__, (char *)&adv_data[adv_index], ret); adv_index += ret; adv_data[len_index] = ret + 1; /* 16bit uuid */ len_index = adv_index; adv_data[adv_index++] = 0x00; adv_data[adv_index++] = ADV_TYPE_SERVICE_DATA; adv_data[adv_index++] = GATTS_UUID & 0xFF; adv_data[adv_index++] = GATTS_UUID >> 8; adv_data[len_index] = 3; /* manufacturer */ len_index = adv_index; adv_data[adv_index++] = 0x00; adv_data[adv_index++] = ADV_TYPE_MANUFACTURER_SPECIFIC; adv_data[adv_index++] = BEKEN_COMPANY_ID & 0xFF; adv_data[adv_index++] = BEKEN_COMPANY_ID >> 8; adv_data[len_index] = 3; ret = bk_ble_set_adv_data(actv_idx, adv_data, adv_len, ble_cmd_cb); if (ret != BK_ERR_BLE_SUCCESS) { LOGE("set adv data failed %d\n", ret); goto error; } ret = rtos_get_semaphore(&gatt_sema, AT_SYNC_CMD_TIMEOUT_MS); /* sart adv */ ret = bk_ble_start_advertising(actv_idx, 0, ble_cmd_cb); if (ret != BK_ERR_BLE_SUCCESS) { LOGE("start adv failed %d\n", ret); goto error; } ret = rtos_get_semaphore(&gatt_sema, AT_SYNC_CMD_TIMEOUT_MS); - Detailed api reference please go to ``api-reference/bluetooth/ble.html``