ESP32 BLE学习(1) — GAP和GATT回调函数作用

2024-06-19 14:04

本文主要是介绍ESP32 BLE学习(1) — GAP和GATT回调函数作用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

(1)学习本文之前,需要先了解的基础知识:ESP32 BLE学习(0) — 基础架构
(2)该部分只是对GAPGATT回调函数进行简单的介绍,因为这两个回调函数中参数太多,个人认为没必要全部进行讲解。因此只有当我认为需要使用的时候,才会讲解对应的内容。

回调函数作用介绍

(1)在学习蓝牙基础架构的时候,我们知道GAP主要用来进行广播,扫描和发起连接等。而GATT用来规范属性(Attribute)中的数据内容,并运用分组(group)的概念对属性(Attribute)进行分类管理。
(2)在ESP32中,GAPGATT的所有操作将分别在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_EVTesp_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

参考

(1)乐鑫官方文档
(2)乐鑫官方论坛:Write a string to characteristic

这篇关于ESP32 BLE学习(1) — GAP和GATT回调函数作用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075229

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个