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 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