自定义杰理AC63系列BLE数据发送函数
自定义BLE数据发送函数,就是将数据发送、数据发送前的检查、以及conn_handle查询等封装在一起,脱离SDK中的相关回调函数,在程序任意位置实现发送数据功能。
1. SDK中的BLE数据发送函数
BLE的数据发送函数定义在apps\common\third_party_profile\jieli\gatt_common\le_gatt_common.c文件里。
int ble_comm_att_send_data(u16 conn_handle, u16 att_handle, u8 *data, u16 len, att_op_type_e op_type)
{gatt_op_ret_e ret = GATT_OP_RET_SUCESS;u16 tmp_16;if (!conn_handle) {return GATT_CMD_PARAM_ERROR;}switch (op_type) {case ATT_OP_READ:tmp_16 = 0x55A1;//fixedret = ble_op_multi_att_send_data(conn_handle, att_handle, &tmp_16, 2, op_type);break;case ATT_OP_READ_LONG:tmp_16 = 0x55A2;//fixedret = ble_op_multi_att_send_data(conn_handle, att_handle, &tmp_16, 2, op_type);break;default:ret = ble_op_multi_att_send_data(conn_handle, att_handle, data, len, op_type);break;}if (ret) {const char *err_string;int error_id = (int)0 - (int)GATT_CMD_RET_BUSY + (int)ret;if (error_id >= 0 && error_id < sizeof(gatt_op_error_string) / sizeof(char *)) {err_string = gatt_op_error_string[error_id];} else {err_string = "UNKNOW GATT_ERROR";}log_error("att_send_fail: %d!!!,%s", ret, err_string);log_error("param:%04x, %04x, %02x,len= %d", conn_handle, att_handle, op_type, len);/* put_buf(data,len); */}return ret;
}
该数据发送函数出现在apps\spp_and_le\examples\trans_data\ble_trans.c文件下的write_callback 回调函数里。写入回调函数如下,注意,无关代码已经省略。
2. ATT写入回调函数
在手机或其他设备(Client角色)发送数据到AC63时,会进入注册过的回调函数trans_att_write_callback( );SDK例程中在该回调函数里执行了自动收发测试代码。
static int trans_att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
{int result = 0;u16 tmp16;u16 handle = att_handle;switch (handle) {//...此处省略1万字case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE:log_info("\n-ae01_rx(%d):", buffer_size);put_buf(buffer, buffer_size); //收发测试,自动发送收到的数据;for testif (ble_comm_att_check_send(connection_handle, buffer_size) &&ble_gatt_server_characteristic_ccc_get(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE)) {log_info("-loop send1\n");ble_comm_att_send_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC);}break;//...此处省略1万字default:break;}return 0;
}
自动收发测试代码里使用ble_comm_att_check_send( )函数检查发送缓存够不够用,同时使用ble_gatt_server_characteristic_ccc_get( )函数检查特征的NOTIFY属性是否得到了Client端的许可。如果任意一个条件不满足,均不会发送数据。
3. 发送缓存检查
为了避免内存溢出,导致不可预见的异常发生,必须检查数组长度是否超出了可用缓存大小。
/********************************************************************/
/*!* \brief 检查预备发送的数据包长度是否能填入
/*******************************************************/
bool ble_comm_att_check_send(u16 conn_handle, u16 pre_send_len)
{if (ble_comm_cbuffer_vaild_len(conn_handle) >= pre_send_len) {return true;} else {return false;}
}/******************************************************************/
/*!* \brief 获取配置的cbuffer 可以填入数据长度*/
/**************************************************************/
u32 ble_comm_cbuffer_vaild_len(u16 conn_handle)
{u32 vaild_len = 0;ble_op_multi_att_get_remain(conn_handle, &vaild_len);return vaild_len;
}
4. NOTIFY属性是否得到许可检查
NOTIFY属性是需要在建立连接后,由手机端写入1许可通知的。该函数用于检查是否得到Client许可。
/*************************************************************************************************/
/*!* \brief 获取 notify or indicate 通知使能值** \param [in]** \return returnGATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONEGATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATIONGATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION** \note*/
/*************************************************************************************************/
u16 ble_gatt_server_characteristic_ccc_get(u16 conn_handle, u16 att_ccc_handle)
{return multi_att_get_ccc_config(conn_handle, att_ccc_handle);
}
5. 查询当前连接的handle
该函数返回值为连接的句柄。如果当前没有连接,则返回0。index是句柄在数组里的序号,默认从0开始。如果只有一个连接,则index为0。role是连接状态下的角色,分为server和client两种。
/*************************************************************************************************/
/*!- \brief 获取index对应的连接 handle*/
/*************************************************************************************************/
u16 ble_comm_dev_get_handle(u8 index, u8 role)
{u16 *group_handle;u8 count;if (GATT_ROLE_SERVER == role) {group_handle = gatt_server_conn_handle;count = SUPPORT_MAX_GATT_SERVER;} else {group_handle = gatt_client_conn_handle;count = SUPPORT_MAX_GATT_CLIENT;}if (index < count) {return group_handle[index];} else {return 0;}
}
6. 自定义BLE发送数据函数
- 先查询当前是否建立了BLE连接,如果无连接,则直接返回。
- 检查发送缓存是否够用,如果不够,则直接返回。
- 检查NOTIFY值是否被Client开启,如未开启,则直接返回。
/*****************************************************************************/
/*!- \brief user defined ble data send fun- u8* sdata point of data to be send - u8 len the size of data to be send */
/***************************************************************************/void my_ble_send_data(u8* sdata,u8 len)
{//先查明当前连接的conn_handleu16 connection_handle = ble_comm_dev_get_handle(0, GATT_ROLE_SERVER);printf("connection_handle: %04x\n",connection_handle);if(connection_handle==0)//无连接{return;}//检查预备发送的数据包长度是否能填入,并且获取 notify or indicate 通知使能值if (ble_comm_att_check_send(connection_handle, len) &&ble_gatt_server_characteristic_ccc_get(connection_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE)){printf("permit send...\n");//使用notify方式发送ble_comm_att_send_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, sdata, len, ATT_OP_NOTIFY);}
}
7. 小结
自定义BLE数据发送函数是将原来SDK中分散的几个函数集合到一起,完成独立的数据发送功能。其中 ble_comm_att_send_data( )函数是最主要的,其他几个是辅助该函数完成任务的。
BLE发送函数里,有个需要注意的地方是ATT的handle,这个值是由BLEprofile里的服务特征表里的数值决定的,如果该值不一致,数据发送会失败。
BLE的profile文件在:apps\spp_and_le\examples\trans_data\ble_trans_profile.h。服务特征表如下:
static const uint8_t trans_profile_data[] = {////// 0x0001 PRIMARY_SERVICE 1800////0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18,/* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */// 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a,// 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a,////// 0x0004 PRIMARY_SERVICE 1801////0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x01, 0x18,/* CHARACTERISTIC, 2a05, INDICATE, */// 0x0005 CHARACTERISTIC 2a05 INDICATE0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x20, 0x06, 0x00, 0x05, 0x2a,// 0x0006 VALUE 2a05 INDICATE0x08, 0x00, 0x20, 0x00, 0x06, 0x00, 0x05, 0x2a,// 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION0x0a, 0x00, 0x0a, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00,////// 0x0008 PRIMARY_SERVICE ae30////0x0a, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x28, 0x30, 0xae,/* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */// 0x0009 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC0x0d, 0x00, 0x02, 0x00, 0x09, 0x00, 0x03, 0x28, 0x04, 0x0a, 0x00, 0x31, 0xae,// 0x000a VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC0x08, 0x00, 0x04, 0x01, 0x0a, 0x00, 0x31, 0xae,/* CHARACTERISTIC, ae02, NOTIFY, */// 0x000b CHARACTERISTIC ae02 NOTIFY0x0d, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x28, 0x10, 0x0c, 0x00, 0x32, 0xae,// 0x000c VALUE ae02 NOTIFY0x08, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x32, 0xae,// 0x000d CLIENT_CHARACTERISTIC_CONFIGURATION0x0a, 0x00, 0x0a, 0x01, 0x0d, 0x00, 0x02, 0x29, 0x00, 0x00,//...此处省略1万字// END0x00, 0x00,
};
相关文章:
自定义杰理AC63系列BLE数据发送函数
自定义BLE数据发送函数,就是将数据发送、数据发送前的检查、以及conn_handle查询等封装在一起,脱离SDK中的相关回调函数,在程序任意位置实现发送数据功能。 1. SDK中的BLE数据发送函数 BLE的数据发送函数定义在apps\common\third_party_pro…...
Jenkins结合gitee自动化部署SpringBoot项目
安装 安装教程 插件选择 Gitee Plugin 配置 源码管理 填写源码地址 注意:请确保genkins所在的服务器有权限git拉取远程仓库代码,如果不可以请参考ssh配置centos 配置ssh拉取远程git代码 源码管理 构建触发器 1.勾选Gitee webhook 触发构建 2.生成we…...
声强级和声压级之间的转换举例
声强级和声压级之间的转换举例 在学习声学时候,经常会遇到声强级和声压级的概念,而且它们的单位都是分贝(dB),很容易混淆这两个概念。而且,更容易在计算时候,不知如何转换,如何使用,本文将举例说明两者之间…...
16 粒子滤波
文章目录 16 粒子滤波16.1 背景介绍16.1.1 Particle Filter是什么?16.1.2 Patricle Filter的状态如何转移?16.1.3 如何通过采样求解Particle Filter 16.2 重要性采样16.2.1 重要性采样方法16.2.2 Sequential Importance Sampling16.2.3 Resampling16.2.4…...
【appium】appium自动化入门之API(下)——两万字API长文,建议收藏
目录 Appium API 前言 1.contexts (返回当前会话中的上下文,使用后可以识别 H5 页面的控件) 2.current_context (返回当前会话的当前上下文 ) 3. context (返回当前会话的当前上下文) 4.find_e…...
开发改了接口,经常忘通知测试的解决方案!
目录 前言: Apifox解决方案 Apifox对此给出的解决方案是: 用Apifox怎么处理接口变更 接口代码实现逻辑修改 接口参数修改 前言: 在开发过程中,接口变动十分频繁,测试人员没有及时获得相关通知的情况也很普遍。这…...
Beyond Compare 4 无法打开
解决办法: 1.修改注册表。WINR呼出开始菜单,在搜索栏中输入 regedit,点击确定。 2.删除项目:\HKEY_CURRENT_USER\Software\ScooterSoftware\Beyond Compare 4\CacheId 根据这个路径找到cacheid 右击删除掉就可以...
MySQL高级数据操作
✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。 🍎个人主页:Hhzzy99 🍊个人信条:坚持就是胜利! 💞当前专栏:MySQL 🥭本文内容&a…...
硬件设计电源系列文章-DCDC转换器基础知识
文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示:这里可以添加技术概要 本文主要接着上篇,上篇文章主要讲述了LDO的相关基础知识,本节开始分享DCDC基础知识 整体架构流程 提示:这里可以添加技术整体架构 以下是…...
XdsObjects .NET 8.45.1001.0 Crack
XdsObjects 是一个工具包,允许开发人员使用 IHE XDS 和 XDS-I 配置文件开发应用程序,只需花费最少的时间和精力,因为遵守配置文件和 ebXML 规则的所有艰苦工作都由该工具包处理。 它为所有角色提供客户端和服务器支持,包括&#…...
数据安全--17--数据安全管理之数据传输
本博客地址:https://security.blog.csdn.net/article/details/131061729 一、数据传输概述 数据传输有两个主体,一个是数据发送方,另一个是数据接收方。数据在通过不可信或者较低安全性的网络进行传输时,容易发生数据被窃取、伪…...
SpringSecurity实现前后端分离登录token认证详解
目录 1. SpringSecurity概述 1.1 权限框架 1.1.1 Apache Shiro 1.1.2 SpringSecurity 1.1.3 权限框架的选择 1.2 授权和认证 1.3 SpringSecurity的功能 2.SpringSecurity 实战 2.1 引入SpringSecurity 2.2 认证 2.2.1 登录校验流程 2.2.2 SpringSecurity完整流程 2.2.…...
Vue3_ElementPlus_简单增删改查(2023)
Vue3,Element Plus简单增删改查 代码:https://github.com/xiaoming12318/Vue3_ElementPlus_CRUD.git 环境: Visual Studio Code Node.js 16.0或更高版本,https://nodejs.org/en axios 快速上手: 如果已经有16.0及…...
vue中重写并自定义console.log
0. 背景 在vue2项目中自定义console.log并输出文件名及行、列号 1. 实现 1.1 自定义console.log export default {// 输出等级: 0-no, 1-error, 2-warning, 3-info, 4-debug, 5-loglevel: 5,// 输出模式: 0-default, 1-normal, 2-randommode: 1,// 是否输出图标hasIcon: fal…...
基于OpenCV 和 Dlib 进行头部姿态估计
写在前面 工作中遇到,简单整理博文内容涉及基于 OpenCV 和 Dlib头部姿态评估的简单Demo理解不足小伙伴帮忙指正 庐山烟雨浙江潮,未到千般恨不消。到得还来别无事,庐山烟雨浙江潮。 ----《庐山烟雨浙江潮》苏轼 https://github.com/LIRUILONGS…...
24个Jvm面试题总结及答案
1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每…...
freemarker 生成前端文件
Freemarker是一种模板引擎,它允许我们在Java应用程序中分离视图和业务逻辑。在Freemarker中,List是一种非常有用的数据结构,它允许我们存储一组有序的元素。有时候,我们需要判断一个List是否为空,这在程序设计中有许多…...
Pycharm+pytest+allure打造高逼格的测试报告
目录 前言: 1、安装allure 2、安装allure-pytest 3、一个简单的用例test_simpe.py 4、在pycharm底部打开terminal 5、用allure美化报告 6、查看报告 总结: 前言: 今天分享的内容:在Pycharmpytest基础上使用allure打造高逼格…...
Mybatis-Plus中update更新操作用法
目录 一、前言二、update1、关于修改的4个条件构造器2、UpdateWrapper【用法示例】3、LambdaUpdateWrapper【用法示例】4、UpdateChainWrapper【 用法示例】5、LambdaUpdateChainWrapper【 用法示例】6、updateById 和 updateBatchById7、Mybatis-plus设置某个字段值为null的方…...
16道JVM面试题
1.jvm内存布局 1.程序计数器:当前线程正在执行的字节码的行号指示器,线程私有,唯一一个没有规定任何内存溢出错误的情况的区域。 2.Java虚拟机栈:线程私有,描述Java方法执行的内存模型,每个方法运行时都会…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
