ESP32-C3 学习测试 蓝牙 篇(四、GATT Server 示例解析)
前言
上一篇文章我们学习了 蓝牙 GATT 相关概念,对于一些基本的专有名词也有了初步的认识,这给我们理解应用程序打下了概念基础 。
本文我们就来分析一下官方示例 GATT Server 的应用程序架构,通过对程序的分析,不仅能更好的理解蓝牙 GATT 的基本概念,还能进一步的明白一些上篇文章不曾深入说明的细节问题。
ESP32-C3 学习 蓝牙 篇系列博文连接:
自己画一块 ESP32-C3 的开发板(第一次使用立创 EDA)(PCB 到手)
https://xie.infoq.cn/article/30387388381a0d915b2494f91
开发环境是乐鑫官方的 ESP-IDF, 基于 VScode 插件搭建好的:
ESP32-C3 VScode 开发环境搭建(基于乐鑫官方 ESP-IDF——Windows 和 Ubuntu 双环境)
https://xie.infoq.cn/article/5b639e112cabba00cc1b8941a
蓝牙篇系列相关博文:
ESP32-C3 学习测试 蓝牙 篇(一、认识 ESP-IDF 的蓝牙框架、简单的了解蓝牙协议栈)
https://xie.infoq.cn/article/efbe5651b35c9d54c69bc0ab2
ESP32-C3 学习测试 蓝牙 篇(二、蓝牙调试 APP、开发板手机连接初体验)
https://xie.infoq.cn/article/a422913b3b0420b1ae7c1436d
ESP32-C3 学习测试 蓝牙 篇(三、认识蓝牙 GATT 协议)
一、GATT Server 示例分析
作为一个单独的应用程序,GATT Server 代码量也算是多的了,我们根据应用程序运行流程从 app_main 开始。
1.1 初始化
1、NVS 初始化,在使用 wifi 的时候我们也需要初始化 NVS ,用来存储一些比较信息:
2、释放一下 ESP_BT_MODE_CLASSIC_BT
,就是释放经典蓝牙资源,保证设备不工作在经典蓝牙下面:
3、按照默认配置BT_CONTROLLER_INIT_CONFIG_DEFAULT
,初始化 蓝牙控制器:
4、使能蓝牙控制器,工作在 BLE mode:
5、初始化蓝牙主机,使能蓝牙主机:
6、注册 GATT 回调函数,回调函数具体内容会在下文说明:
7、注册 GAP 回调函数,在前面的文章我们说过:蓝牙是通过 GAP 建立通信的,所以在这个回调函数中定义了在广播期间蓝牙设备的一些操作:
8、 注册 service :
9、设置 mtu ,mtu 相关说明如下:
1.2 回调函数
在示例中有好几个回调函数,我们依次来看:
gatts_event_handler
先来看第一个回调函数gatts_event_handler
:
这个函数的主要作用:导入 GATT 的 profiles。
这个函数注册完成之后,就会在 ble 协议任务函数中运行,将程序前面定义的 profiles 导入:
gatts_profile_a_event_handler
和 gatts_profile_b_event_handler
, 这也是我们本示例的关键函数,下面我们会来分析。.
gap_event_handler
第二个,GAP 事件回调函数gap_event_handler
,
我们在上一篇文章分析过,GAP 定义了在广播期间蓝牙设备的一些操作,蓝牙是通过 GAP 建立通信的(说明看代码注释,了解 GAP 各个事件的含义):
说明:GAP 的回调函数有很多,通过枚举esp_gap_ble_cb_event_t
可查看。这里我们只说明上面回调函数使用到的。
.
☆ gatts_profile_a_event_handler ☆
本示例的核心部分, GATT 回调函数gatts_profile_a_event_handler
,
理解了他将让自己在以后蓝牙 GATT 的开发中更加得心应手(说明看代码注释,了解 GATT 各个事件的含义):
除了上面代码中事件的简单注释,还有一些需要说明的地方:
1、 在ESP_GATTS_CREATE_EVT
事件中调用了函数:
该函数的作用是启动 GATT 服务。
再然后调用函数:
来添加特性(特征的 UUID, 特征值描述符属性权限, 特征属性、特征值、属性响应控制字节)。
上面的一系列操作会触发ESP_GATTS_START_EVT
和ESP_GATTS_ADD_CHAR_EVT
事件
2、上面事件中有 2 个写事件: ESP_GATTS_WRITE_EVT
和 ESP_GATTS_EXEC_WRITE_EVT
其中ESP_GATTS_EXEC_WRITE_EVT
事件在接收到写数据之后需要为 Client 回复数据 ,前者不需要。
.
GATT 事件流程
在没有连接之前:注册->创建->启动->添加特征->添加特征描述:
ESP_GATTS_REG_EVT
—>ESP_GATTS_CREATE_EVT
—>ESP_GATTS_START_EVT
—>ESP_GATTS_ADD_CHAR_EVT
—>ESP_GATTS_ADD_CHAR_DESCR_EVT
流程说明:
在 Demo 的ESP_GATTS_REG_EVT
事件中,调用esp_ble_gap_set_device_name(char *)
来设置蓝牙设备名字;调用esp_ble_gap_config_adv_data()
来配置广播数据;
最后调用esp_ble_gatts_create_service()
指定 gatts_if 和 service_id 来创建服务<实际调用 btc_transfer_context()
来完成服务的创建和调用回调函数>。
服务创建完成就会触发回调函数向 profile 报告状态和服务 ID。Service_id 对于后面添加 included serivces 和 characteristics 和 descriptor 都要用到。触发ESP_GATTS_CREATE_EVT
事件
在 Demo 的ESP_GATTS_CREATE_EVT
中调用esp_ble_gatts_start_service(uint16_t service_handle)
来启动服务;
再调用 esp_ble_gatts_add_char()
来添加特性(特征的 UUID, 特征值描述符属性权限, 特征属性、特征值、属性响应控制字节)。
触发ESP_GATTS_START_EVT
和ESP_GATTS_ADD_CHAR_EVT
事件,在ESP_GATTS_ADD_CHAR_EVT
事件中,获取特征值调用esp_err_tesp_ble_gatts_add_char_descr()
来添加特征描述符。
在连接之后:
CONNECT_EVT
—>ESP_GATTS_MTU_EVT
—>GATT_WRITE_EVT
—>ESP_GATTS_CONF_EVT
—>GATT_READ_EVT
参考博文:从ESP32 BLE应用理解GATT
esp_ble_gatts_create_service
在提一个函数,在上面介绍的回调函数时间中说到 ESP_GATTS_REG_EVT
最后回调用 esp_ble_gatts_create_service
来创建服务:
创建一个 service。当一个 service 创建成功后,ESP_CREATE_SERVICE_EVT
事件触发回调函数被调用,该回调函数报告了 profile 的 stauts 和 service ID。当要添加 include service 和 characteristics//descriptors 入服务 service,Service ID 在回调函数中用到。
二、示例测试
根据上面的代码分析和上一篇文章的内容,我们可以尝试一下对示例进行一定的测试修改。
当然目前来说,还是怎么简单怎么来。
2.1 Service 和 UUID
Service 个数,我们示例中是使用了注册了 2 个 Service ,首先说明一下上一篇文章中,我们说到示例连接后能够获取到的 Service 为 4 个,实际上前面 2 个是固有的,后面 2 个才是我们程序中注册的:
我们通过程序中定义的 UUID 也能够看出来:
在程序中其设置的位置如下:
正好讲到 UUID ,可以发现 characteristic 的 UUID 也和定义的一样:
在程序中其设置的位置如下:
2.2 characteristic
characteristic 的创建位置在程序中对应的位置如下:
2.3 数据收发
我们的蓝牙应用的最终目的还是数据的交互,数据收发,我们前面说了好几篇文章都没有切实的体会到数据的收发,现在终于要开始测试了。
与蓝牙设备的数据交互,可以认为就是对 Characteristci 进行读写即可达到与其通信的目的。
示例中在使用 esp_ble_gatts_add_char
函数添加 Characteristci 时就定义了可读可写属性:
我们下面就来通过手机与开发板进行数据的读写测试:
读数据:
我们通过手机端进行如下操作:
上图中,我们读取到了来自 Server 的数据,在程序中对应的实现部分为:
<3 所以可以想象,如果我们把传感器的数据放在这些 value 中,那么设备读取数据,是不是就可以读取到传感器的数据了。
另外说明:在 Client 端有一个按钮:接收通知数据,对其进行操作有如下 LOG:
这里的原因暂时不理解,等后期明白了会更新说明。
写数据:
除了读数据,我们通过手机端也可以对设备进行写数据(当然前提是这个 characteristic 添加的时候支持写):
对于写数据,在程序中对应的实现部分为:
和发送类似,这里我们可以添加一些相关的代码,收到 Client 发送的特定指令,进行特定的操作,简单的比如切换 LED,采集一次数据等。
结语
本文经过对示例程序的分析说明,然后通过对比手机端读取到的信息,进行了简单的数据读写测试,了解了程序的设计框架,也算是入门了 ESP-IDF 的蓝牙 GATT 开发。
当然我们还只停留在理论分析阶段,实际上到现在我们都不曾真正的动手修改添加过程序代码。对于我计划的以应用为目的来说,至少也需要使用蓝牙 BLE 通过手机能够接收到开发板上各种传感器的数据,然后通过手机可以对开发板进行一些控制操作。
接下来的文章我们的学习测试就会一步一步的朝着这个最终的目的而进行,加油↖(^ω^)↗!
版权声明: 本文为 InfoQ 作者【矜辰所致】的原创文章。
原文链接:【http://xie.infoq.cn/article/743c10571e00b2e895cecb5d1】。文章转载请联系作者。
评论