ble peripheral demo

示例说明

执行流程

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