nrf52832 学习笔记(九)蓝牙主机发现服务

nrf52832 学习笔记(九)蓝牙主机发现服务

服务发现流程

数据如同下表一样存储在服务端,客户端首先要获取表中的Handle和Type列,从而知道服务端中存在哪些数据,以便后面读、写、通知等操作。这个过程叫做发现服务。
nrf52832 学习笔记(九)蓝牙主机发现服务_第1张图片

服务发现初始化

以SDK中 ble_app_blinky_c 为例

需要添加对应文件及头文件路径信息
nrf52832 学习笔记(九)蓝牙主机发现服务_第2张图片

然后对服务发现库进行初始化,并定义服务发现函数回调函数 db_disc_handler, 当服务发现完成时会触发该回调函数。

/**@brief Function for handling database discovery events.
 *
 * @details This function is callback function to handle events from the database discovery module.
 *          Depending on the UUIDs that are discovered, this function should forward the events
 *          to their respective services.
 *
 * @param[in] p_event  Pointer to the database discovery event.
 */
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
    ble_lbs_on_db_disc_evt(&m_ble_lbs_c, p_evt);
}


/**@brief Database discovery initialization.
 */
static void db_discovery_init(void)
{
    ble_db_discovery_init_t db_init;

    memset(&db_init, 0, sizeof(db_init));

    db_init.evt_handler  = db_disc_handler;
    db_init.p_gatt_queue = &m_ble_gatt_queue;

    ret_code_t err_code = ble_db_discovery_init(&db_init);
    APP_ERROR_CHECK(err_code);
}

主机进行服务发现时不能发现私有服务的128bit UUID,需要对私有UUID进行注册

/**@brief Handles events coming from the LED Button central module.
 */
static void lbs_c_evt_handler(ble_lbs_c_t * p_lbs_c, ble_lbs_c_evt_t * p_lbs_c_evt)
{
    switch (p_lbs_c_evt->evt_type)
    {
        case BLE_LBS_C_EVT_DISCOVERY_COMPLETE:
        {
            ret_code_t err_code;

            err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c,
                                                p_lbs_c_evt->conn_handle,
                                                &p_lbs_c_evt->params.peer_db);
            NRF_LOG_INFO("LED Button service discovered on conn_handle 0x%x.", p_lbs_c_evt->conn_handle);

            err_code = app_button_enable();
            APP_ERROR_CHECK(err_code);

            // LED Button service discovered. Enable notification of Button.
            err_code = ble_lbs_c_button_notif_enable(p_lbs_c);
            APP_ERROR_CHECK(err_code);
        } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE

        case BLE_LBS_C_EVT_BUTTON_NOTIFICATION:
        {
            NRF_LOG_INFO("Button state changed on peer to 0x%x.", p_lbs_c_evt->params.button.button_state);
            if (p_lbs_c_evt->params.button.button_state)
            {
                bsp_board_led_on(LEDBUTTON_LED);
            }
            else
            {
                bsp_board_led_off(LEDBUTTON_LED);
            }
        } break; // BLE_LBS_C_EVT_BUTTON_NOTIFICATION

        default:
            // No implementation needed.
            break;
    }
}
uint32_t ble_lbs_c_init(ble_lbs_c_t * p_ble_lbs_c, ble_lbs_c_init_t * p_ble_lbs_c_init)
{
    uint32_t      err_code;
    ble_uuid_t    lbs_uuid;
    ble_uuid128_t lbs_base_uuid = {LBS_UUID_BASE};

    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c);
    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c_init);
    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c_init->evt_handler);
    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c_init->p_gatt_queue);

    p_ble_lbs_c->peer_lbs_db.button_cccd_handle = BLE_GATT_HANDLE_INVALID;
    p_ble_lbs_c->peer_lbs_db.button_handle      = BLE_GATT_HANDLE_INVALID;
    p_ble_lbs_c->peer_lbs_db.led_handle         = BLE_GATT_HANDLE_INVALID;
    p_ble_lbs_c->conn_handle                    = BLE_CONN_HANDLE_INVALID;
    p_ble_lbs_c->evt_handler                    = p_ble_lbs_c_init->evt_handler;
    p_ble_lbs_c->p_gatt_queue                   = p_ble_lbs_c_init->p_gatt_queue;
    p_ble_lbs_c->error_handler                  = p_ble_lbs_c_init->error_handler;

    err_code = sd_ble_uuid_vs_add(&lbs_base_uuid, &p_ble_lbs_c->uuid_type);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    VERIFY_SUCCESS(err_code);

    lbs_uuid.type = p_ble_lbs_c->uuid_type;
    lbs_uuid.uuid = LBS_UUID_SERVICE;

    return ble_db_discovery_evt_register(&lbs_uuid);
}

/**@brief LED Button client initialization.
 */
static void lbs_c_init(void)
{
    ret_code_t       err_code;
    ble_lbs_c_init_t lbs_c_init_obj;

    lbs_c_init_obj.evt_handler   = lbs_c_evt_handler;
    lbs_c_init_obj.p_gatt_queue  = &m_ble_gatt_queue;
    lbs_c_init_obj.error_handler = lbs_error_handler;

    err_code = ble_lbs_c_init(&m_ble_lbs_c, &lbs_c_init_obj);
    APP_ERROR_CHECK(err_code);
}

开启服务发现

从机广播,主机扫描到广播后,发出连接请求,主从机连接后就可以开始进行服务发现
nrf52832 学习笔记(九)蓝牙主机发现服务_第3张图片

这里有个句柄派发函数,主要是nrf52832 支持多连接(一主多从),当给蓝牙协议栈下发命令时,蓝牙协议栈可能正在执行其他连接的命令,因此做了两个消息队列,将连接信息和命令信息分别缓存起来,防止命令信息错乱丢失。

uint32_t ble_lbs_c_handles_assign(ble_lbs_c_t    * p_ble_lbs_c,
                                  uint16_t         conn_handle,
                                  const lbs_db_t * p_peer_handles)
{
    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c);

    p_ble_lbs_c->conn_handle = conn_handle;
    if (p_peer_handles != NULL)
    {
        p_ble_lbs_c->peer_lbs_db = *p_peer_handles;
    }
    return nrf_ble_gq_conn_handle_register(p_ble_lbs_c->p_gatt_queue, conn_handle);
}

服务发现完成

服务发现完成后会调用 ble_lbs_on_db_disc_evt 回调函数
nrf52832 学习笔记(九)蓝牙主机发现服务_第4张图片

在回调函数ble_lbs_on_db_disc_evt 中,设置句柄信息
nrf52832 学习笔记(九)蓝牙主机发现服务_第5张图片
并在函数结束时 调用 p_ble_lbs_c->evt_handler(p_ble_lbs_c, &evt); 函数,也就是 lbs_c_evt_handler 函数,使能 通知(ble_lbs_c_button_notif_enable)

nrf52832 学习笔记(九)蓝牙主机发现服务_第6张图片

服务端通知

如果客户端使能了服务端的CCCD,服务端通知时会触发客户端回调函数
nrf52832 学习笔记(九)蓝牙主机发现服务_第7张图片
在 函数 on_hvx 中完成对通知的处理
nrf52832 学习笔记(九)蓝牙主机发现服务_第8张图片

客户端读

调用客户端读 API,服务端会将对应数据上报上来

uint32_t ble_lbs_led_status_read(ble_lbs_c_t * p_ble_lbs_c)
{
    VERIFY_PARAM_NOT_NULL(p_ble_lbs_c);

    if (p_ble_lbs_c->conn_handle == BLE_CONN_HANDLE_INVALID)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    nrf_ble_gq_req_t read_req;

    memset(&read_req, 0, sizeof(nrf_ble_gq_req_t));

    read_req.type                        = NRF_BLE_GQ_REQ_GATTC_READ;
    read_req.error_handler.cb            = gatt_error_handler;
    read_req.error_handler.p_ctx         = p_ble_lbs_c;
    read_req.params.gattc_read.handle   = p_ble_lbs_c->peer_lbs_db.led_handle;
    read_req.params.gattc_read.offset   = 0;

    return nrf_ble_gq_item_add(p_ble_lbs_c->p_gatt_queue, &read_req, p_ble_lbs_c->conn_handle);
}

上报的数据会触发回调函数
nrf52832 学习笔记(九)蓝牙主机发现服务_第9张图片
在回调函数中对 读出数据进行处理

客户端写

客户端写和读类似,只不过没有回调函数
nrf52832 学习笔记(九)蓝牙主机发现服务_第10张图片

你可能感兴趣的:(蓝牙,BLE,nrf52832,ble,nordic,蓝牙,嵌入式)