前言
(1)学习本文之前,需要先了解的基础知识:ESP32 BLE学习(0) — 基础架构 (2)该部分只是对
GAP
和GATT
回调函数进行简单的介绍,因为这两个回调函数中参数太多,个人认为没必要全部进行讲解。因此只有当我认为需要使用的时候,才会讲解对应的内容。
回调函数作用介绍
(1)在学习蓝牙基础架构的时候,我们知道
GAP
主要用来进行广播,扫描和发起连接等。而GATT
用来规范属性(Attribute
)中的数据内容,并运用分组(group
)的概念对属性(Attribute
)进行分类管理。
(2)在ESP32
中,GAP
和GATT
的所有操作将分别在esp_ble_gatts_register_callback()
和esp_ble_gap_register_callback()
这两个函数注册的回调函数中进行。
// 注册 GATT 回调函数,处理所有的 GATT 事件
ret = esp_ble_gatts_register_callback(gatts_event_handler);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret);
return;
}
// 注册 GAP 回调函数,
ret = esp_ble_gap_register_callback(gap_event_handler);
if (ret){
ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret);
return;
}
(3)在这两个回调函数中的类型如下:
// GATT 回调函数
typedef void (* esp_gatts_cb_t)(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
// GAP 回调函数
typedef void (* esp_gap_ble_cb_t)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
回调函数参数具体分析
GATT回调函数
esp_gatts_cb_event_t结构体
(1)
esp_gatts_cb_event_t
就是一个enmu
枚举参数。当出现对应的GATT
事件的时候,底层协议栈就会触发GATT
回调函数,并将对应事件以esp_gatts_cb_event_t
枚举形式进行通知。
(2)接下来我将会讲解常见的几种GATT
事件及其如何进行触发。
- ESP_GATTS_REG_EVT : 当调用
esp_ble_gatts_app_register()
函数注册应用ID
触发该事件。- ESP_GATTS_READ_EVT :当客户端发送读命令,
ESP32
作为服务端将会触发该事件。- ESP_GATTS_WRITE_EVT : 当客户端发送一个写请求并且写的数据
<=(MTU-3)
,ESP32
作为从设备将会触发该事件。- ESP_GATTS_EXEC_WRITE_EVT : 当客户端发送一个写请求并且写的数据
>(MTU-3)
,ESP32
作为从设备将会触发该事件。- ESP_GATTS_MTU_EVT :当客户端发送设置
MTU
请求时,ESP32
作为服务端触发该事件。- ESP_GATTS_CONF_EVT : 当
ESP32
作为服务端收到客户端对之前发送的指示(Indication
)或通知(Notification
)的确认时,就会触发该事件。- ESP_GATTS_START_EVT : 当
ESP32
作为服务端成功启动,该事件触发。- ESP_GATTS_CONNECT_EVT : 当客户端发起连接事件,
ESP32
作为服务端,该事件触发。- ESP_GATTS_DISCONNECT_EVT : 当客户端断开连接,
ESP32
作为服务端,该事件触发。- ESP_GATTS_CREAT_ATTR_TAB_EVT :
esp_ble_gatts_create_attr_tab()
创建GATT
完成时触发该事件。
esp_gatt_if_t
(1)这其实就是一个无符号的
8bit
数据,它用于标识不同的GATT
客户端,该参数与esp_ble_gatts_app_register()
函数注册的app_id
成对应关系。
(2)当我们调用esp_ble_gatts_app_register()
函数注册的app_id
时候,协议栈会为其分配一个对应的gatts_if
,用于标识一个GATT
服务。同时会触发esp_ble_gatts_register_callback()
注册的回调函数中的ESP_GATTS_REG_EVT
事件。
typedef uint8_t esp_gatt_if_t;
esp_ble_gatts_cb_param_t结构体
(1)
esp_ble_gatts_cb_param_t
是一个联合体,该联合体和esp_gatts_cb_event_t
这个enmu
枚举参数是存在对应关系的。
(2)如下为对应图:
/* --- ESP_GATTS_REG_EVT --- */
param->reg.status // 注册应用ID的操作状态
param->reg.app_id // esp_ble_gatts_app_register()注册函数中输入的app_id
/* --- ESP_GATTS_READ_EVT --- */
param->read.conn_id // GATT读事件的连接ID,用于标识当前读取操作所涉及的连接的唯一标识符
param->read.trans_id // 确保了每个读操作的事务一致性,防止响应被错误地关联到其他读请求
param->read.bda // 写入的蓝牙设备地址
param->read.handle // GATT 句柄
param->read.offset // 如果需要读取的值太长,该值为偏移量
param->read.is_long // 需要读取的值是否过长,与.offset进行配合
param->read.need_rsp // 该写操是否需要回复
/* --- ESP_GATTS_WRITE_EVT --- */
param->write.conn_id // GATT写事件的连接ID,用于标识当前写操作所涉及的连接的唯一标识符
param->write.trans_id // 确保了每个写操作的事务一致性,防止响应被错误地关联到其他读请求
param->write.bda // 要被写入的蓝牙设备地址
param->write.handle // GATT 句柄
param->write.offset // 如果需要写的值太长,该值为偏移量
param->write.need_rsp // 该写操是否需要回复
param->write.is_prep // GATT(通用属性配置文件)服务器的写入操作是否为预备写入(Prepare Write)
param->write.len // 该写操作的值长度
param->write.value // 该写操作的值
/* --- ESP_GATTS_EXEC_WRITE_EVT --- */
param->exec_write.conn_id // 连接ID
param->exec_write.trans_id // 传递ID
param->exec_write.bda // 要被写入的蓝牙设备地址
param->exec_write.exec_write_flag // 执行写标志
/* --- ESP_GATTS_MTU_EVT --- */
param->mtu.conn_id // 连接ID
param->mtu.mtu // MTU大小
/* --- ESP_GATTS_CONF_EVT --- */
param->conf.status // 客户端的确认状态
param->conf.conn_id // 连接ID
param->conf.handle // GATT句柄
param->conf.len // 指示(Indication)或通知(Notification)的值长度,在发送指示(Indication)或通知(Notification)失败的时候,该值有效
param->conf.value // 指示(Indication)或通知(Notification)的值,在发送指示(Indication)或通知(Notification)失败的时候,该值有效
/* --- ESP_GATTS_START_EVT --- */
param->start.status // GATT服务启动状态
param->start.service_handle // GATT服务句柄
/* --- ESP_GATTS_CONNECT_EVT --- */
param->connect.conn_id // 连接ID
param->connect.link_role // 链路层角色,0标识主设备,1标识从设备
param->connect.remote_bda // 对端蓝牙地址
param->connect.conn_params // 当前的连接参数
param->connect.ble_addr_type // 对端蓝牙设备地址类型
param->connect.conn_handle // HCI层连接句柄
/* --- ESP_GATTS_DISCONNECT_EVT --- */
param->disconnect.conn_id // 连接ID
param->disconnect.remote_bda // 对端蓝牙设备地址
param->disconnect.reason // 蓝牙断连原因
/* --- ESP_GATTS_CREAT_ATTR_TAB_EVT --- */
param->add_attr_tab.status // GATT服务创建状态
param->add_attr_tab.svc_uuid // 创建的GATT服务UUID类型,有16bit、32bit、128bit
param->add_attr_tab.svc_inst_id // 创建的GATT服务UUID ID号
param->add_attr_tab.num_handle // 要添加到GATT数据库的属性句柄编号
param->add_attr_tab.handles // GATT句柄编号
GAP回调函数
esp_gap_ble_cb_event_t
(1)
esp_gap_ble_cb_event_t
就是一个enmu
枚举参数。当出现对应的GAP
事件的时候,底层协议栈就会触发GAP
回调函数,并将对应事件以esp_gap_ble_cb_event_t
枚举形式进行通知。
(2)接下来我将会讲解常见的几种GAP
事件及其如何进行触发。
- ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT : 当调用
esp_ble_gap_config_adv_data_raw()
函数设置了广播包成功后触发该事件。- ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT : 当调用
esp_ble_gap_config_scan_rsp_data_raw()
函数设置了广播扫描响应包成功后触发该事件。- ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT : 当调用
esp_ble_gap_config_adv_data()
函数,其中.set_scan_rsp = false
设置广播包成功后触发该事件。- ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT : 当调用
esp_ble_gap_config_adv_data()
函数,其中.set_scan_rsp = true
设置广播扫描响应包成功后触发该事件。- ESP_GAP_BLE_ADV_START_COMPLETE_EVT : 当调用
esp_ble_gap_start_advertising()
函数成功启动广播之后触发该事件。- ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT : 当调用
esp_ble_gap_stop_advertising()
函数成功启动广播之后触发该事件。不过在BLE5.0
之后的广播包在连接时有ESP_GAP_BLE_ADV_TERMINATED_EVT
事件报上来。- ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT : 很多应用场景中,从设备和主设备刚建立连接时,会使用“快速”的连接参数以达到迅速交换信息的目的,但是,从设备和主设备机之间并不是一直需要快速的交换信息,因为这样会加快从机电池能量的消耗,这时候,从设备就希望能降低连接事件的频度(连接间隔),从而降低功耗,延长电池工作时间。因此,这里从设备就可以向主设备发起链路层连接参数更新控制(
Connection Parameter Update Control
)。连接参数更新成功,那么该事件就会被触发。
esp_ble_gap_cb_param_t
(1)
esp_ble_gap_cb_param_t
是一个联合体,该联合体和esp_gap_ble_cb_event_t
这个enmu
枚举参数是存在对应关系的。
(2)如下为对应图:
/* --- ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT --- */
param->adv_data_raw_cmpl.status // 设置广播包操作成功状态
/* --- ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT --- */
param->scan_rsp_data_raw_cmpl.status // 设置扫描回应包操作成功状态
/* --- ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT --- */
param->adv_data_cmpl.status // 设置广播包操作成功状态
/* --- ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT --- */
param->scan_rsp_data_cmpl.status // 设置扫描回应包操作成功状态
/* --- ESP_GAP_BLE_ADV_START_COMPLETE_EVT --- */
param->adv_start_cmpl.status // 设置广播开始操作成功状态
/* --- ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT --- */
param->adv_stop_cmpl.status // 设置广播停止操作成功状态
/* --- ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT --- */
param->update_conn_params.status // 设置连接更新参数操作成功状态
param->update_conn_params.bda // 蓝牙设备地址
param->update_conn_params.min_int // 最小连接间隔
param->update_conn_params.max_int // 最大连接间隔
param->update_conn_params.latency // 从机连接延迟时间(以连接事件数为单位)。范围:0x0000 ~ 0x01F3
param->update_conn_params.conn_int // 当前连接间隔
param->update_conn_params.timeout // LE Link的监督超时。取值范围:0x000A ~ 0x0C80。Time = N * 10 msec
参考