ESP32-连接参数/间隔更新

 连接间隔的设置是一个协商的过程,ESP32提供了一些协商的接口,按顺序分析一下。

Step 1:首先是Client连接时对Server要求的连接间隔(确定值)

在连接的时候,Client会把当前的连接间隔发送给Server。在Server的连接事件回调函数中,我们是可以看到这个Client要求的连接间隔的,主要是从这个结构体获得。

再具体些是这样一个结构体。

以下是在连接事件回调函数中查看Client要求的连接间隔的代码,适用于Arduino和ESP-IDF

// 在连接事件回调函数中查看Client要求的连接间隔
// 适用于Arduino和ESP-IDF
esp_gatt_conn_params_t conn_params;
memcpy(&conn_params, &param->connect.conn_params, sizeof(esp_gatt_conn_params_t));
Serial.println(conn_params.interval*1.25); // 换成ESP-IDF的LOG就行

Step 2:然后是Server请求更新间隔范围(是范围哦)

主要是调用这个函数,Server向Client发送的连接间隔更新请求。

esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params);

用的这样的一个结构体: 

 在ESP-IDF里面,在Server连接之后,在连接事件的回调函数里请求更新:

case ESP_GATTS_CONNECT_EVT:
    ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
    esp_log_buffer_hex(GATTS_TABLE_TAG, param->connect.remote_bda, 6);
    // 在这里把Step1的代码放进来可以看到Client在本次连接开始时要求的连接参数:
    // 以下时Step2的关键代码:
    esp_ble_conn_update_params_t conn_params = {0};
    memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
    conn_params.latency = 0;
    conn_params.max_int = 0x20;    // max_int = 0x20*1.25ms = 40ms
    conn_params.min_int = 0x10;    // min_int = 0x10*1.25ms = 20ms
    conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
    esp_ble_gap_update_conn_params(&conn_params);
    break;

而在Arduino ESP32里面,大佬们已经把这段话封装成了函数,就是下面这个:

 因此在Arduino里面,只需要在连接回调函数里调用这个函数就可以请求更新间隔了。


esp_bd_addr_t connectedAddress;  // 被连接的地址

class MyServerCallbacks: public BLEServerCallbacks 
{
    void onConnect(BLEServer* pServer,esp_ble_gatts_cb_param_t* param) {
    // 在这里把Step1的代码放进来可以看到Client在本次连接开始时要求的连接参数:
    // 以下时Step2的关键代码:
      memcpy(connectedAddress, param->connect.remote_bda, sizeof(esp_bd_addr_t));
      pServer->updateConnParams(connectedAddress,6,6,0,500);
    };

    void onDisconnect(BLEServer* pServer) {
    }
};

Step 3:最后是查看Client和Server的当前连接间隔

连接间隔是一个协商的过程,最开始,也就是刚连接上时,Server是可以看到Client要求的连接间隔的,然后Server请求更新一个更适合自己的参数范围,Client收到请求后,Client的协议栈会根据情况最终决定一个新的连接间隔,这个最终决定权在Client,那要怎么知道是否更新成功呢,或者说怎么知道当前的连接间隔呢。

法1,利用回调事件,仅适用于ESP-IDF的Server端(其实Arduino应该也会有这个事件啦,但是好像没有暴露接口给我们,就不去改源码了)。

主要是通过每次更新后产生的一个gap层的回调事件,通过回调的结构体参数打印:

case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
    ESP_LOGI(GATTS_TABLE_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
    param->update_conn_params.status,
    param->update_conn_params.min_int,
    param->update_conn_params.max_int,
    param->update_conn_params.conn_int,    //当前连接间隔可能不在范围内,因为是由Client决定的
    param->update_conn_params.latency,
    param->update_conn_params.timeout);
    break;

要注意,当前连接间隔可能不在Server请求的范围内,因为决定权最终是由Client决定的。

法2:调用查询函数,这个函数可以用在Server和Client,用在连接后的任意地方,这个函数是:
esp_err_t esp_ble_get_current_conn_params(esp_bd_addr_t bd_addr, esp_gap_conn_params_t *conn_params);

它用到这样一个结构体变量,但是只要新建这个变量就行,然后把指针传到上面这个函数,函数会把结果放进这个结构体

就是下面这段代码

esp_gap_conn_params_t conn_params;
esp_err_t ret = esp_ble_get_current_conn_params(connectedAddress, &conn_params);
Serial.println(ret);
Serial.println(conn_param2.interval*1.25);

好了,这样就可以知道当前实际的连接间隔了。

Step 4:回到最初的设置

回到最初,说的是一开始Client会给Server发送一个初始的连接间隔,那这个初始的间隔俺们能不能自己设置呢。我找了一个这个接口,这个应该是在连接建立之前让Client调用来进行设置的,很奇怪,设置的是一个范围而不是一个具体的值。

esp_err_t esp_ble_gap_set_prefer_conn_params(esp_bd_addr_t bd_addr, uint16_t min_conn_int, uint16_t max_conn_int, uint16_t slave_latency, uint16_t supervision_tout);

由于没有对这个函数进行测试,这里简单说说我的总结(猜想),最开始,用这个函数设置了Client的连接间隔范围,协议栈从中选定一个初始连接间隔对Server发起连接,Server通过Step1可以看到这个初始连接间隔,Server通过Step2发来一个它需要的连接间隔范围,Client的协议栈在两个范围内取交集,如果没有交集则优先满足Client的范围。我们最后通过Step3可以查到最终的连接间隔是什么。也就是说,Client的协议栈才是最终的老大。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/71935.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【腾讯云 Cloud studio 实战训练营】云端 IDE 构建移动端H5

🐱 个人主页:不叫猫先生,公众号:前端舵手 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步…

第一百二十五天学习记录:C++提高:STL-deque容器(下)(黑马教学视频)

deque插入和删除 功能描述: 向deque容器中插入和删除数据 函数原型: 两端插入操作: push_back(elem); //在容器尾部添加一个数据 push_front(elem); //在容器头部插入一个数据 pop_back(); //删除容器最后一个数据 pop_front(); //删除容器…

【torch.nn.PixelShuffle】和 【torch.nn.UnpixelShuffle】

文章目录 torch.nn.PixelShuffle直观解释官方文档 torch.nn.PixelUnshuffle直观解释官方文档 torch.nn.PixelShuffle 直观解释 PixelShuffle是一种上采样方法,它将形状为 ( ∗ , C r 2 , H , W ) (∗, C\times r^2, H, W) (∗,Cr2,H,W)的张量重新排列转换为形状为…

Spring Boot配置文件中的配置项加密jasypt使用

在Spring Boot中,有很多口令需要加密,如数据库连接密码、访问第三方接口的Token等。常见的方法就是用jasypt对口令进行加密。 实际上,jasypt可以对配置文件中任意配置项的值进行加密,不局限于对密码的加密。 1.在pom.xml中添加ja…

Centos操作系统新安装的Python3中安装mysqlclient库

问题简介: mysqlclient 是python中的一个连接MySQL数据库的重要的三方库,但是在centos中使用pip3 install mysqlclient 方法安装一直报错,经过两天时间的排查,终于找到了解决问题的方法。 [rootd3acd2b8211d /]# pip3 install mysqlclient Co…

LeetCode 周赛上分之旅 #39 结合中心扩展的单调栈贪心问题

⭐️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度…

2.若依前后端分离版第一个增删查改

1.介绍 若依提供了代码生成功能,单表的CRUD可以直接用若依框架提供的代码生成进行创建。 2.实现 2.1 在数据库创建业务表test_teacher 2.2 生成代码 运行系统,进入菜单[系统工具]-》[代码生成],点击导入按钮,选择需要生成代码的表进行导…

【Linux】程序地址空间

程序地址空间 首先引入地址空间的作用什么是地址空间为什么要有地址空间 首先引入地址空间的作用 1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 int g_val 100;6 int main()7 {8 pid_t id fork();9 if(id 0)10 {11 int cn…

设备工单管理系统如何实现工单流程自动化?

设备工单管理系统属于工单系统的一种&#xff0c;基于其丰富的功能&#xff0c;它可以同时处理不同的多组流程&#xff0c;旨在有效处理发起人提交的事情&#xff0c;指派相应人员完成服务请求和记录全流程。该系统主要面向后勤管理、设备维护、物业管理、酒店民宿等服务行业设…

城市最短路

题目描述 下图表示的是从城市A到城市H的交通图。从图中可以看出&#xff0c;从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。 输入输出格式 输入格式&#xff1a; 无 输出格式&#xff1a; 倒序输出经过城市最少的一条路线 输入输出样例 输入样例…

运维监控学习笔记4

系统监控&#xff1a; CPU&#xff1a; 内存&#xff1a; IO INPUT/OUTPUT&#xff08;网络、磁盘&#xff09; CPU三个重要概念&#xff1a; 上下文切换&#xff1a;CPU调度器实施的进程的切换过程&#xff0c;称为上下文切换。CPU寄存器的作用。 上下文切换越频繁&#…

【图像去噪的扩散滤波】基于线性扩散滤波、边缘增强线性和非线性各向异性滤波的图像去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

网络安全(黑客)自学路线/笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…

有没有推荐的golang的练手项目?

前言 下面是github上的golang项目&#xff0c;适合练手&#xff0c;可以自己选择一些项目去练习&#xff0c;整理不易&#xff0c;希望能多多点赞收藏一下&#xff01;废话少说&#xff0c;我们直接进入正题>>> 先推荐几个教程性质的项目&#xff08;用于新手学习、巩…

欧拉公式之证明

首先&#xff0c;我们考虑复数函数的泰勒级数展开式。对于任意一个复数函数f(z)&#xff0c;我们可以将其在za处进行泰勒级数展开&#xff1a; f(z) f(a) f(a)(z-a) f(a)(z-a)^2/2! f(a)(z-a)^3/3! ... 其中f(a)表示f(z)在za处的导数&#xff0c;f(a)表示f(z)在…

Ctfshow web入门 XXE 模板注入篇 web373-web378 详细题解 全

CTFshow XXE web373 学习资料&#xff1a; &#xff08;梭哈~&#xff09; https://www.cnblogs.com/20175211lyz/p/11413335.html https://www.cnblogs.com/zhaijiahui/p/9147595.html https://www.cnblogs.com/r00tuser/p/7255939.html https://mp.weixin.qq.com/s?__bizMz…

python中yield关键字

yield和return 理解一个东西最好的办法就是找一个和它类似的东西&#xff0c;然后再搞清楚它们之间的区别。 yield最类似的东西就是return&#xff0c;因为他们起到了同样的作用&#xff1a;返回值。 看这个return的函数&#xff1a; def have_some_wine():print(先开一瓶酒&a…

虚幻5中Lumen提供哪些功能以及如何工作的

虚幻引擎 5 中的 Lumen 是一个完全动态的全局照明和反射系统。它可以在虚幻引擎 5 中使用&#xff0c;因此创作者无需自行设置。它是为下一代控制台和建筑可视化等高端可视化而设计的。那么它提供了哪些功能以及如何工作&#xff1f; 全局照明 当光离开光源时&#xff0c;它会…

【TI毫米波雷达笔记】MMWave配置流程避坑

【TI毫米波雷达笔记】MMWave配置流程避坑 在TI SDK目录下的mmwave.h文档说明中 强调了要按以下配置&#xff1a; mmWave API The mmWave API allow application developers to be abstracted from the lower layer drivers and the mmWave link API.The mmWave file should b…

【设计模式】适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式&#xff0c;它结合了两个独立接口的功能。 这种模式涉及到一个单一的类&#xff0c;该类负责加入独立的或不兼容的接口功能。举个真实的例子&#xff…