自定义杰理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方法执行的内存模型,每个方法运行时都会…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...