ble peripheral demo¶
示例说明¶
如何新建自定义 service
- 参考: ble 自定义 service
如何设置 ble peripheral 角色
- 参考: ble 角色设置
如何处理 ble 协议栈和应用协议栈的信息交互
执行流程¶
1. 用户自己函数入口
在 ble_user_main.c 中, osapp_user_main_init()初始化自己数据。
2. 开启ble协议栈调度
在用户函数执行完后,调用 osapp_ble_stack_run(),开启ble协议栈调度。
3. 示例伪代码
void osapp_user_main_init(void)
{
///user data init
{
//do ...
}
///ble stack run
osapp_ble_stack_run();
LOG(LOG_LVL_INFO,"ble user run\n");
}
ble 自定义 service¶
参考ble bx simple service 创建模板¶
1. 定义自己的service 描述
static const struct gattm_svc_desc bx_simple_svc_desc = {
.start_hdl = 0,
.task_id = TASK_ID_AHI,
.perm = PERM(SVC_MI,DISABLE)|PERM(SVC_EKS,DISABLE)|\
PERM(SVC_AUTH,NO_AUTH)|PERM(SVC_UUID_LEN,UUID_128),PERM_VAL(SVC_SECONDARY,0),
.nb_att = BX_SIMPLES_ATT_NUM,
.uuid = BX_SIMPLE_SVC_UUID_128,
};
2. 定义自己的att 属性列表
static const struct gattm_att_desc bx_simple_svc_att_db[] =
{
// Characteristic1 Declaration
[BX_SIMPLES_IDX_CHAR1_CHAR] = {
.uuid = ATT_UUID16_TO_ARRAY(ATT_DECL_CHARACTERISTIC),
.perm = PERM(RD, ENABLE),
.max_len =0,
.ext_perm = PERM(UUID_LEN,UUID_16),
},
// Characteristic1 Value
[BX_SIMPLES_IDX_CHAR1_VAL] = {
.uuid = BX_SIMPLE_CHAR1_UUID_128,
.perm = PERM(WRITE_REQ,ENABLE)|PERM(WRITE_COMMAND,ENABLE)|PERM(WP,NO_AUTH)|PERM(RD, ENABLE)|PERM(RP,NO_AUTH),//write read
.max_len = BX_SIMPLE_CHAR1_MAX_LEN,
.ext_perm = PERM(RI,ENABLE)|PERM(UUID_LEN, UUID_128),// if the char's perm has 'read',this must be set. uuid 128
},
// Characteristic2 Declaration
[BX_SIMPLES_IDX_CHAR2_CHAR] = {
.uuid = ATT_UUID16_TO_ARRAY(ATT_DECL_CHARACTERISTIC),
.perm = PERM(RD, ENABLE),
.max_len =0,
.ext_perm = PERM(UUID_LEN,UUID_16),
},
// Characteristic2 Value
[BX_SIMPLES_IDX_CHAR2_VAL] = {
.uuid = BX_SIMPLE_CHAR2_UUID_128,
.perm = PERM(RD, ENABLE)|PERM(RP,NO_AUTH),//read
.max_len = BX_SIMPLE_CHAR2_MAX_LEN,
.ext_perm = PERM(RI,ENABLE)|PERM(UUID_LEN, UUID_128),// if the char's perm has 'read',this must be set. uuid 128
},
// Characteristic3 Declaration
[BX_SIMPLES_IDX_CHAR3_CHAR] = {
.uuid = ATT_UUID16_TO_ARRAY(ATT_DECL_CHARACTERISTIC),
.perm = PERM(RD, ENABLE),
.max_len =0,
.ext_perm = PERM(UUID_LEN,UUID_16),
},
// Characteristic3 Value
[BX_SIMPLES_IDX_CHAR3_VAL] = {
.uuid = BX_SIMPLE_CHAR3_UUID_128,
.perm = PERM(NTF, ENABLE)|PERM(NP,NO_AUTH),//notify
.max_len = BX_SIMPLE_CHAR3_MAX_LEN,
.ext_perm = PERM(UUID_LEN, UUID_128),//uuid 128
},
// Client Characteristic Configuration Descriptor
[BX_SIMPLES_IDX_CHAR3_CFG] = {
.uuid = ATT_UUID16_TO_ARRAY(ATT_DESC_CLIENT_CHAR_CFG),
.perm = PERM(RD, ENABLE) |PERM(WRITE_REQ, ENABLE),
.max_len =0,
.ext_perm = PERM(UUID_LEN,UUID_16),
},
};
3. 实现service的函数事件回调
static const gattServiceCBs_t bx_simple_callbacks = {
.pfnReadAttrCB = ble_bx_simple_read_callback,
.pfnWriteAttrCB = ble_bx_simple_write_callback,
.pfnConnectCB = ble_bx_simple_connect_callback,
.pfnHandlerInitCB = ble_bx_simple_handler_init,
};
4. 实现外部应用服务添加接口
int32_t ble_bx_simple_add_svc(gattServiceCBs_t *cb)
{
struct gattm_add_svc_req *req = AHI_MSG_ALLOC_DYN(GATTM_ADD_SVC_REQ,TASK_ID_GATTM,\
gattm_add_svc_req,sizeof(bx_simple_svc_att_db));
struct gattm_svc_desc *svc = &req->svc_desc;
memcpy(svc,&bx_simple_svc_desc,sizeof(bx_simple_svc_desc));
memcpy(svc->atts,bx_simple_svc_att_db,sizeof(bx_simple_svc_att_db));
memcpy(cb,&bx_simple_callbacks,sizeof(gattServiceCBs_t));
LOG(LOG_LVL_INFO," svc ble_bx_simple_add_svc \n");
return osapp_msg_build_send(req, sizeof(struct gattm_svc_desc)+sizeof(bx_simple_svc_att_db));
}
5. 书写service应用的外部数据访问接口
void ble_bx_simple_char3_send_notification(uint8_t const *data,uint8_t length)
{
static uint16_t notify_seq_num = 0;
struct gattc_send_evt_cmd *cmd= AHI_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD,TASK_ID_GATTC, gattc_send_evt_cmd, length);
if(bx_simple_env.is_connect == IS_CONNECTED && char3_notify_cfg)
{
LOG(LOG_LVL_INFO,"ble_bx_simple_char3_send_notification\n");
cmd->operation = GATTC_NOTIFY;
cmd->seq_num = notify_seq_num++;
cmd->handle = start_handler + BX_SIMPLES_IDX_CHAR3_CFG;
cmd->length = length;
memcpy(cmd->value,data,length);
osapp_ahi_msg_send(cmd, (sizeof(struct gattc_send_evt_cmd) + length), portMAX_DELAY);
}
}
ble 角色设置¶
设置流程¶
void osapp_ble_stack_run(void)
{
osapp_ble_stack_data_init();
osapp_set_dev_config(GAP_ROLE_PERIPHERAL,GAPM_CFG_ADDR_PUBLIC,GAPM_PAIRING_LEGACY,BLE_PERIPHERAL_MAX_MTU);
LOG(LOG_LVL_INFO,"osapp_ble_stack_run\n");
}
1. 设置perapheral 支持的自定义服务¶
1. 在ble_peripheral_simple.h 中,设置枚举自定义service id
/// BX Peripheral Service Table
enum
{
BX_SIMPLES_SERVICE_ID,
BLE_PERIPHERAL_SERVICES_NUM,
};
2. 在ble_peripheral_simple.c 中,设置初始话service 信息
static void osapp_ble_stack_data_init(void)
{
memset(&peripheral_env, 0 , sizeof(ble_peripheral_simple_env_t));
peripheral_env.svc.max_num = BLE_PERIPHERAL_SERVICES_NUM;
peripheral_env.svc.index = 0;
peripheral_env.svc.handles[BX_SIMPLES_SERVICE_ID] = ble_bx_simple_add_svc;
}
2. 设置设备的 角色设置¶
osapp_set_dev_config(GAP_ROLE_PERIPHERAL,GAPM_CFG_ADDR_PUBLIC,GAPM_PAIRING_LEGACY,BLE_PERIPHERAL_MAX_MTU);
static int32_t osapp_set_dev_config(uint8_t role,uint8_t addr_type,uint8_t pairing_mode,uint16_t max_mtu)
{
// Set Device configuration
struct gapm_set_dev_config_cmd* cmd = AHI_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD,TASK_ID_GAPM,gapm_set_dev_config_cmd);
memset(cmd, 0 , sizeof(struct gapm_set_dev_config_cmd));
cmd->operation = GAPM_SET_DEV_CONFIG;
cmd->role = role;
// Set Data length parameters
cmd->sugg_max_tx_octets = BLE_MIN_OCTETS;
cmd->sugg_max_tx_time = BLE_MIN_TIME;
cmd->max_mtu = max_mtu;
cmd->addr_type = addr_type;
cmd->pairing_mode = pairing_mode;
return osapp_msg_build_send(cmd, sizeof(struct gapm_set_dev_config_cmd));
}
3. 协议栈开始完整运行¶
。。。。
ble 协议栈和应用协议栈的信息交互¶
实现消息交互的处理函数¶
/**
* @brief message and handler table. This define the connection of message and it's callback.
*/
static const osapp_msg_handler_table_t handler_table[]=
{
[0] = {KE_MSG_DEFAULT_HANDLER,(osapp_msg_handler_t)osapp_default_msg_handler},
///connection indicate: receive connect request from master
{GAPC_CONNECTION_REQ_IND,(osapp_msg_handler_t)osapp_gapc_conn_req_ind_handler},
///connection lost indicate handler
{GAPC_DISCONNECT_IND,(osapp_msg_handler_t)osapp_gapc_disconnect_ind_handler},
///GAPM event complete
{GAPM_CMP_EVT,(osapp_msg_handler_t)osapp_gapm_cmp_evt_handler},
///ble power on ready and should do a reset
{GAPM_DEVICE_READY_IND,(osapp_msg_handler_t)osapp_device_ready_ind_handler},
///trigger when master need to read device information uuid 0x1800
{GAPC_GET_DEV_INFO_REQ_IND,(osapp_msg_handler_t)osapp_gapc_get_dev_info_req_ind_handler},
///add service complete and store service handler
{GATTM_ADD_SVC_RSP,(osapp_msg_handler_t)osapp_gattm_add_svc_rsp_handler},
///master write data to device
{GATTC_WRITE_REQ_IND,(osapp_msg_handler_t)osapp_gattc_write_req_ind_handler},
///master read data from device
{GATTC_READ_REQ_IND,(osapp_msg_handler_t)osapp_gattc_read_req_ind_handler},
///gattc event has completed
{GATTC_CMP_EVT,(osapp_msg_handler_t)osapp_gattc_cmp_evt_handler},
};
const osapp_msg_handler_info_t handler_info = ARRAY_INFO(handler_table);