nrf52832 学习笔记蓝牙主机发现服务
Posted 不咸不要钱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙主机发现服务相关的知识,希望对你有一定的参考价值。
nrf52832 学习笔记(九)蓝牙主机发现服务
服务发现流程
数据如同下表一样存储在服务端,客户端首先要获取表中的Handle和Type列,从而知道服务端中存在哪些数据,以便后面读、写、通知等操作。这个过程叫做发现服务。
服务发现初始化
以SDK中 ble_app_blinky_c 为例
需要添加对应文件及头文件路径信息
然后对服务发现库进行初始化,并定义服务发现函数回调函数 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 支持多连接(一主多从),当给蓝牙协议栈下发命令时,蓝牙协议栈可能正在执行其他连接的命令,因此做了两个消息队列,将连接信息和命令信息分别缓存起来,防止命令信息错乱丢失。
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 回调函数
在回调函数ble_lbs_on_db_disc_evt 中,设置句柄信息
并在函数结束时 调用 p_ble_lbs_c->evt_handler(p_ble_lbs_c, &evt); 函数,也就是 lbs_c_evt_handler 函数,使能 通知(ble_lbs_c_button_notif_enable)
服务端通知
如果客户端使能了服务端的CCCD,服务端通知时会触发客户端回调函数
在 函数 on_hvx 中完成对通知的处理
客户端读
调用客户端读 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 学习笔记蓝牙主机发现服务的主要内容,如果未能解决你的问题,请参考以下文章