ESP32的下的蓝牙应用笔记(1)——Beacon蓝牙信标
Beacon蓝牙信标简介
Beacon蓝牙信标是一种基于蓝牙低功耗(BLE)技术的设备,主要用于提供位置信息和数据传输服务。它通过周期性地广播信号,能够在一定范围内与其他蓝牙设备进行通信,从而提供精准的位置信息和相关服务。
工作原理:Beacon蓝牙信标作为蓝牙低功耗协议中的外围设备,持续向周围广播包含设备标识的特定数据包,但不能和中心设备建立连接。这些数据包通常包含UUID、广播名称、MAC地址、major、minor、电量信息等。简而言之,不需要建立蓝牙连接便可广播数据,如果设备想要接受数据,就必须对特特定的地址进行监听。
Beacon蓝牙信标广播标准下又分为了若干种广播格式,此次学习便以其中的一种Eddystone格式为例子(ESP32例程中有相关的,便于学习)。
Eddystone广播格式简介
Eddystone广播有四种帧格式,
可以根据配置,广播四种不同类型的数据,非常强大。
Eddystone广播包是装载于BLE通用广播包,PDU中的Playload。
引用一张网图如下(这个一整大块就是PDU中的一个Playload)。
第一个AD structure是有关于物理连接功能的配置。
第二个AD structure是有关UUID的配置。
第三个AD structure是有关服务数据的配置,这里的数据包含了UUID和Eddystone的数据。既len-1(类型占用的一个字节)=UUID+Eddystone Data;
代码实现
这部分网上有一些其他作者已经实现,就不再赘述,着重讲一下效果部分。以及我个人的一些理解分析和疑问。
主函数部分:
void app_main(void)
{//初始化ESP_ERROR_CHECK(nvs_flash_init());//释放经典蓝牙ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));//初始化并开启低功耗蓝牙控制器esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(&bt_cfg);//开启低功耗BLE控制器esp_bt_controller_enable(ESP_BT_MODE_BLE);//开启eddystone初始化esp_eddystone_init();/*<! set scan parameters *///设置扫描参数//esp_ble_gap_set_scan_params(&ble_scan_params);//服务数据封包esp_eddystone_frame_t uid = {0};int len = Eddystone_set_uid(&uid,0,(uint8_t *)"helloworld",(uint8_t *)"123456");if(len==-1){printf("erro\r\n");return;}adv_data.manufacturer_len = len;adv_data.p_manufacturer_data = (uint8_t *)&uid;//设置广播数据参数esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);if (ret){ESP_LOGE(DEMO_TAG, "config adv data failed, error code = %x", ret);}//开始广播}
数据封装:
int Eddystone_set_uid(esp_eddystone_frame_t *uid,uint8_t power,uint8_t *name_space,uint8_t *instance)
{if(uid==NULL||name_space==NULL||instance==NULL){return -1;}memset(uid,0,sizeof(esp_eddystone_frame_t));uid->len = sizeof(esp_eddystone_frame_t);uid->uuid = EDDYSTONE_SERVICE_UUID;uid->frame_type = EDDYSTONE_FRAME_TYPE_UID;uid->type = 0x16;uid->u.uid.ranging_data = power;memcpy(uid->u.uid.namespace_id,name_space,10);memcpy(uid->u.uid.instance_id,instance,6);return uid->len;
}
回调函数:
void app_main(void)
{//初始化ESP_ERROR_CHECK(nvs_flash_init());//释放经典蓝牙ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));//初始化并开启低功耗蓝牙控制器esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(&bt_cfg);//开启低功耗BLE控制器esp_bt_controller_enable(ESP_BT_MODE_BLE);//开启eddystone初始化esp_eddystone_init();/*<! set scan parameters *///设置扫描参数//esp_ble_gap_set_scan_params(&ble_scan_params);//服务数据封包esp_eddystone_frame_t uid = {0};int len = Eddystone_set_uid(&uid,0,(uint8_t *)"helloworld",(uint8_t *)"123456");if(len==-1){printf("erro\r\n");return;}adv_data.manufacturer_len = len;adv_data.p_manufacturer_data = (uint8_t *)&uid;//设置广播数据参数esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);if (ret){ESP_LOGE(DEMO_TAG, "config adv data failed, error code = %x", ret);}//开始广播}
参数配置:
static uint8_t adv_service_uuid[]={0xfb,0x34,0x9b,0x5f,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0xaa,0xfe,0x00,0x00
};
//广播数据
static esp_ble_adv_data_t adv_data={.set_scan_rsp = false,.include_name = false,.include_txpower =false,.min_interval = 0x0006,.max_interval = 0x000c,.appearance = 0x00,.manufacturer_len = 0,.p_manufacturer_data = NULL,.service_data_len = 0,.p_service_data = NULL,.service_uuid_len = 16,.p_service_uuid = adv_service_uuid,.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
//广播参数
static esp_ble_adv_params_t adv_params = {.adv_int_min = 0x20,.adv_int_max = 0x40,.adv_type = ADV_TYPE_IND,.own_addr_type = BLE_ADDR_TYPE_PUBLIC,//.peer_addr =//.peer_addr_type =.channel_map = ADV_CHNL_ALL,.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
效果展示
分析
以上图手机抓包的数据为例,第一包数据就是我们配置的物理连接功能基础参数。
对应的参数支持如下
着重讲一下这包数据,可以发现在抓包的数据中,并没有体现这一部分的数据。一开始我也很奇怪,后来经过细致的了解后才明白,这里的配置决定了设备在广告或后续连接过程中能够声明和提供的服务。注意,是能够声明和提供,并不是已经声明和提供,这部分的配置意味着,将BLE蓝牙配置为有哪些功能,至于是否把功能开放广播出来,又是另外一回事。所以如果没开放广播,在抓包的时候自然看不见这部分信息。
最后是
这一包数据,可能有人会好奇为什么是封包在这个manufacturer而不是service这里,我一开始也有疑问,细细了解以后发表一下我的理解。首先eddystone并非是官方的蓝牙协议,只是厂商制定的一种蓝牙广播协议标准,所以它包含的应该是厂家的特定信息,而这里的manufacture data的意为,制造商数据允许设备在广告中包含自定义信息,而这些信息对特定制造商有意义。就如eddystone,是谷歌制造的协议,属于厂家自定义的信息,而并不属于通用的。所以应该放在此处。而从我们蓝牙抓包的第二条数据也可以看到。类型是0xff。
也意为制造商特定数据。
因此eddystone的协议包放在类型为0xff的AD structure中也便好理解了。至于包中的内容,与eddystone的广播格式对应即可。
疑问
最后,查阅eddystone的协议规范发现,标准的eddystone协议包应该包含一位完整的16位的uuid既,len = 0x03 type = 0x03 UUID = 0xFEAA这样一包数据,但可以看到esp32发出的数据包并不包含,确不影响到设备的扫描,但同时在nRF Connect中也并没有把他识别为一个标准的eddystone设备,而是一个普通蓝牙设备,不过不影响数据的收发。协议中对于这一包数据的解析翻译如下:该列表必须包含Eddystone服务UUID(0xFEAA),以便iOS设备进行后台扫描。个人推测即便不加也不影响基础的广播功能。同时如果各位有啥办法能够加上,也不妨可以说一声完善一下(我是试了好多方法都没加上去)。
相关文章:

ESP32的下的蓝牙应用笔记(1)——Beacon蓝牙信标
Beacon蓝牙信标简介 Beacon蓝牙信标是一种基于蓝牙低功耗(BLE)技术的设备,主要用于提供位置信息和数据传输服务。它通过周期性地广播信号,能够在一定范围内与其他蓝牙设备进行通信,从而提供精准的位置信息和相关服…...

控制台安全内部:创新如何塑造未来的硬件保护
在 Help Net Security 的采访中,安全研究人员 Specter 和 ChendoChap 讨论了游戏机独特的安全模型,并强调了它与其他消费设备的不同之处。 他们还分享了对游戏机安全性的进步将如何影响未来消费者和企业硬件设计的看法。 斯佩克特 (Specter) 是本周在阿…...

如何选择适合自己的 Python IDE
集成开发环境(IDE)是指提供广泛软件开发能力的软件应用程序。IDE 通常包括源代码编辑器、构建自动化工具和调试器。大多数现代 IDE 都配备了智能代码补全功能。在本文中,你将发现目前市场上最好的 Python IDE。 什么是 IDE? IDE…...

Matlab车牌识别课程设计报告模板(附源代码)
目 录 一.课程设计目的……………………………………………3 二.设计原理…………………………………………………3 三.详细设计步骤……………………………………………3 四. 设计结果及分析…………………………………………18 五. …...
kubesphere jenkins自动重定向 http://ks-apiserver:30880/oauth/authorize
问题:登陆kubesphere的jenkins Nodeport IP :Port 46.XXX.XXX.16:30180 自动跳转失败 http://ks-apiserver:30880/oauth/authorize?client_idjenkins&redirect_urihttp://46.XXX.XXX.16:30180/securityRealm/finishLogin&response_typecode&scopeopen…...
Vue3访问页面时自动获取数据
1. 使用生命周期钩子函数 # 后端代码--使用pywebview class Api:def greet(self):greet_text pywebview and vue3response {}response[text] greet_textreturn responseif __name__ __main__:# 前后端通信测试api Api()window webview.create_window(Vue app in pywebvie…...
go语言回调函数的使用
前言 在 Go 语言中,回调函数是一种将一个函数作为参数传递给另一个函数,在特定的事件发生时被调用的编程模式。 一、回调函数的定义 type OnTaskHandler func(r []byte)type remoteTaskClient struct {sync.RWMutexonTask OnTaskHandler } 以上定义了…...
区块链学习笔记(一)
区块链技术实现了去中心化的货币系统,与中心化记账方式不同,它消除了中间第三方,允许用户进行点对点交易,并确保了货币的真正所有权。此外,区块链的代码完全公开且不可篡改,保障了系统的透明度和安全性。 …...
解决QT打包发布App Store时(90238)错误
Invalid signature. The main app bundle, xxxx at the “xxxx.app” path, has the following signing error(s): [a sealed resource is missing or invalid. In subcomponent: xxxx.app/Contents/Frameworks/QtWebEngineCore.framework]. For details about signing Mac cod…...

使用Vite构建现代化前端应用
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 使用Vite构建现代化前端应用 引言 Vite 简介 安装 Vite 创建项目 启动开发服务器 项目结构 配置 Vite 开发模式 生产构建 使用插…...
PyQt入门指南三十八 QWizard向导组件
在PyQt中,QWizard 是一个用于创建向导式应用程序的组件。向导是一种用户界面模式,它通过一系列逐步的页面引导用户完成某个任务。每个页面通常包含一些输入字段和选项,用户需要在每个页面上完成相应的操作,然后才能进入下一个页面…...
【数学二】线性代数-矩阵-矩阵的概念及运算
考试要求 1、理解矩阵的概念,了解单位矩阵、数量矩阵、对角矩阵、三角矩阵、对称矩阵、反对称矩阵和正交矩阵以及它们的性质. 2、掌握矩阵的线性运算、乘法、转置以及它们的运算规律,了解方阵的幂与方阵乘积的行列式的性质. 3、理解逆矩阵的概念&#x…...
近期学习前端的心得
1.如果你这一行的编辑权利在于你这一行的某个字段的值,你可以使用这样:disabled"scope.row.某字段 ! 某字段的值" 2.如果你不想使用弹出框的形式来修改数据库,可以采用 对“某字段”列使用了 el-input,并绑定了 v-model 到 sco…...

qt QMenu详解
1、概述 QMenu是Qt框架中的一个类,用于创建和管理菜单。它提供了丰富的接口来添加菜单项(通常是QAction对象)、子菜单以及分隔符。QMenu可以嵌入到菜单栏(QMenuBar)中,也可以作为弹出菜单(通过…...

HTMLCSS:旋转的动态卡片
效果演示 这段代码创建了一个具有动态背景和渐变效果的卡片。卡片背景有一个无限循环的旋转动画,增加了视觉吸引力。这种效果可以用于展示个人信息、项目介绍或其他需要吸引用户注意的内容。 HTML <div class"card"><h3>前端Hardy</h3&…...

通过自然语言表达你的想法。GitHub Spark让任何人都能使用人工智能,为自己创建软件...
我们能否让任何人都能使用人工智能,为自己创建软件?尽管开发者喜欢定制自己的开发环境以提高效率和趣味性,但创建个性化应用程序的复杂性常常阻止他们这样做。 如何使个性化软件的创建变得像定制开发环境一样简单?并让更多人能够轻松实现这种…...

c++的list类
本篇将讲述list类中的各种重要和常用函数(begin()、end()、rbegin()、rend()、empty()、size()、front(&#…...

uniapp数据缓存
利用uniapp做开发时,缓存数据是及其重要的,下面是同步缓存和异步缓存的使用 同步缓存 在执行同步缓存时会阻塞其他代码的执行 ① uni.setStorageSync(key, data) 设置缓存,如: uni.setStorageSync(name, 张三) ② uni.getSt…...
HarmonyOS-权限管理
一. 权限分类 1. system_grant system_grant 为系统授权,无需询问用户,常用的权限包括网络请求、获取网络信息、获取wifi信息、获取传感器数据等。 /* system_grant(系统授权)*/static readonly INTERNET ohos.permission.INTE…...

Github 2024-11-02 Rust开源项目日报 Top10
根据Github Trendings的统计,今日(2024-11-02统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Python项目2Dart项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero Genera…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...