当前位置: 首页 > news >正文

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

相关文章:

  • 【仿真建模-anylogic】ConveyorCustomStation原理解析
  • Zabbix自定义监控JAVA进程
  • Go基础编程 - 05 - 数组与切片
  • (一)SvelteKit教程:hello world
  • windows桌面运维----第三天
  • CCAA质量管理【学习笔记】​​ 备考知识点笔记(三)质量管理方法与常见工具
  • 了解并解决 Flutter 中的灰屏问题
  • 瞬间将模型改为原来的60-200倍小
  • PHP框架详解 - CakePHP框架
  • 细说MCU输出互补型PWM波形时设置死区时间的作用
  • 大数据之Hadoop的特点是什么?有什么优缺点?有哪些发行版本?
  • 军用FPGA软件 Verilog语言的编码准测之触发器、锁存器
  • 各类存储器类型(RAM、ROM、FLASH、DRAM、SRAM)
  • Kafka之ISR机制的理解
  • Java程序设计语言的特点
  • [译]前端离线指南(上)
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 2017 前端面试准备 - 收藏集 - 掘金
  • ES学习笔记(12)--Symbol
  • Java到底能干嘛?
  • Laravel5.4 Queues队列学习
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Markdown 语法简单说明
  • ng6--错误信息小结(持续更新)
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • PHP的类修饰符与访问修饰符
  • Redash本地开发环境搭建
  • windows下如何用phpstorm同步测试服务器
  • 产品三维模型在线预览
  • 动态魔术使用DBMS_SQL
  • 分享几个不错的工具
  • 机器学习 vs. 深度学习
  • 区块链将重新定义世界
  • 深度学习入门:10门免费线上课程推荐
  • 通过npm或yarn自动生成vue组件
  • 网络应用优化——时延与带宽
  • 在Unity中实现一个简单的消息管理器
  • 《天龙八部3D》Unity技术方案揭秘
  • 如何在招聘中考核.NET架构师
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • !!java web学习笔记(一到五)
  • # 达梦数据库知识点
  • #NOIP 2014# day.1 T2 联合权值
  • #window11设置系统变量#
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • ${factoryList }后面有空格不影响
  • (1)STL算法之遍历容器
  • (2)MFC+openGL单文档框架glFrame
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (C#)获取字符编码的类
  • (C++17) std算法之执行策略 execution
  • (Java入门)抽象类,接口,内部类
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (undone) MIT6.824 Lecture1 笔记