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

自定义杰理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数据发送函数&#xff0c;就是将数据发送、数据发送前的检查、以及conn_handle查询等封装在一起&#xff0c;脱离SDK中的相关回调函数&#xff0c;在程序任意位置实现发送数据功能。 1. SDK中的BLE数据发送函数 BLE的数据发送函数定义在apps\common\third_party_pro…...

Jenkins结合gitee自动化部署SpringBoot项目

安装 安装教程 插件选择 Gitee Plugin 配置 源码管理 填写源码地址 注意&#xff1a;请确保genkins所在的服务器有权限git拉取远程仓库代码&#xff0c;如果不可以请参考ssh配置centos 配置ssh拉取远程git代码 源码管理 构建触发器 1.勾选Gitee webhook 触发构建 2.生成we…...

声强级和声压级之间的转换举例

声强级和声压级之间的转换举例 在学习声学时候&#xff0c;经常会遇到声强级和声压级的概念&#xff0c;而且它们的单位都是分贝(dB),很容易混淆这两个概念。而且&#xff0c;更容易在计算时候&#xff0c;不知如何转换&#xff0c;如何使用&#xff0c;本文将举例说明两者之间…...

16 粒子滤波

文章目录 16 粒子滤波16.1 背景介绍16.1.1 Particle Filter是什么&#xff1f;16.1.2 Patricle Filter的状态如何转移&#xff1f;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 &#xff08;返回当前会话中的上下文&#xff0c;使用后可以识别 H5 页面的控件&#xff09; 2.current_context &#xff08;返回当前会话的当前上下文 &#xff09; 3. context &#xff08;返回当前会话的当前上下文&#xff09; 4.find_e…...

开发改了接口,经常忘通知测试的解决方案!

目录 前言&#xff1a; Apifox解决方案 Apifox对此给出的解决方案是&#xff1a; 用Apifox怎么处理接口变更 接口代码实现逻辑修改 接口参数修改 前言&#xff1a; 在开发过程中&#xff0c;接口变动十分频繁&#xff0c;测试人员没有及时获得相关通知的情况也很普遍。这…...

Beyond Compare 4 无法打开

解决办法&#xff1a; 1.修改注册表。WINR呼出开始菜单&#xff0c;在搜索栏中输入 regedit&#xff0c;点击确定。 2.删除项目&#xff1a;\HKEY_CURRENT_USER\Software\ScooterSoftware\Beyond Compare 4\CacheId 根据这个路径找到cacheid 右击删除掉就可以...

MySQL高级数据操作

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;MySQL &#x1f96d;本文内容&a…...

硬件设计电源系列文章-DCDC转换器基础知识

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 本文主要接着上篇&#xff0c;上篇文章主要讲述了LDO的相关基础知识&#xff0c;本节开始分享DCDC基础知识 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 以下是…...

XdsObjects .NET 8.45.1001.0 Crack

XdsObjects 是一个工具包&#xff0c;允许开发人员使用 IHE XDS 和 XDS-I 配置文件开发应用程序&#xff0c;只需花费最少的时间和精力&#xff0c;因为遵守配置文件和 ebXML 规则的所有艰苦工作都由该工具包处理。 它为所有角色提供客户端和服务器支持&#xff0c;包括&#…...

数据安全--17--数据安全管理之数据传输

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/131061729 一、数据传输概述 数据传输有两个主体&#xff0c;一个是数据发送方&#xff0c;另一个是数据接收方。数据在通过不可信或者较低安全性的网络进行传输时&#xff0c;容易发生数据被窃取、伪…...

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&#xff0c;Element Plus简单增删改查 代码&#xff1a;https://github.com/xiaoming12318/Vue3_ElementPlus_CRUD.git 环境&#xff1a; Visual Studio Code Node.js 16.0或更高版本&#xff0c;https://nodejs.org/en axios 快速上手&#xff1a; 如果已经有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 进行头部姿态估计

写在前面 工作中遇到&#xff0c;简单整理博文内容涉及基于 OpenCV 和 Dlib头部姿态评估的简单Demo理解不足小伙伴帮忙指正 庐山烟雨浙江潮&#xff0c;未到千般恨不消。到得还来别无事&#xff0c;庐山烟雨浙江潮。 ----《庐山烟雨浙江潮》苏轼 https://github.com/LIRUILONGS…...

24个Jvm面试题总结及答案

1.什么是Java虚拟机&#xff1f;为什么Java被称作是“平台无关的编程语言”&#xff1f; Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台&#xff0c;而不需要程序员为每…...

freemarker 生成前端文件

Freemarker是一种模板引擎&#xff0c;它允许我们在Java应用程序中分离视图和业务逻辑。在Freemarker中&#xff0c;List是一种非常有用的数据结构&#xff0c;它允许我们存储一组有序的元素。有时候&#xff0c;我们需要判断一个List是否为空&#xff0c;这在程序设计中有许多…...

Pycharm+pytest+allure打造高逼格的测试报告

目录 前言&#xff1a; 1、安装allure 2、安装allure-pytest 3、一个简单的用例test_simpe.py 4、在pycharm底部打开terminal 5、用allure美化报告 6、查看报告 总结&#xff1a; 前言&#xff1a; 今天分享的内容&#xff1a;在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.程序计数器&#xff1a;当前线程正在执行的字节码的行号指示器&#xff0c;线程私有&#xff0c;唯一一个没有规定任何内存溢出错误的情况的区域。 2.Java虚拟机栈&#xff1a;线程私有&#xff0c;描述Java方法执行的内存模型&#xff0c;每个方法运行时都会…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

WebRTC调研

WebRTC是什么&#xff0c;为什么&#xff0c;如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

FTXUI::Dom 模块

DOM 模块定义了分层的 FTXUI::Element 树&#xff0c;可用于构建复杂的终端界面&#xff0c;支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...