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…...
一文搞懂:Agent、Harness Engineering、MCP、Skill 到底是什么
🧭 你是否被这些词搞晕过? Agent Harness Engineering MCP Skill Tool Workflow…… 大模型时代,新概念层出不穷。它们分别是什么?又如何协同工作? 这篇文章是你的概念地图。 大模型生态:四个核心概…...
SeqGPT-560M开源可部署安全实践:SELinux策略配置与容器最小权限原则
SeqGPT-560M开源可部署安全实践:SELinux策略配置与容器最小权限原则 1. 引言:为什么企业级AI部署必须关注安全? 当你把像SeqGPT-560M这样强大的智能信息抽取系统部署到生产环境时,兴奋之余,一个严肃的问题必须摆在首…...
避坑指南:glmnet做lasso回归时分类变量的3个常见错误及解决方法
避坑指南:glmnet做lasso回归时分类变量的3个常见错误及解决方法 在生物信息学和临床数据分析领域,lasso回归因其出色的变量选择能力而广受欢迎。R语言中的glmnet包是实现lasso回归的利器,但许多初学者在处理分类变量时频频踩坑。本文将揭示三…...
如何用OpenClaw的cron定时任务功能,每天自动发送待办清单
要实现“每天自动发送待办清单”,你需要将 Cron 定时触发器、待办管理 Skills 和消息推送渠道三者打通。这里提供两套最实用的方案,推荐优先使用 CLI 命令方案,它更稳定且易于调试。🚀 方案一:CLI 命令配置ÿ…...
探秘含齿根裂纹的超高自由度斜齿 - 轴承复合故障特性
含齿根裂纹——轴承内圈,外圈,滚动体的超高自由度斜齿–轴承复合故障特性分析!才用残差法突出故障时域响应,采用包络谱对故障特征频率进行分析,模型难度巨大在机械系统的复杂世界里,含齿根裂纹以及轴承内圈、外圈、滚动…...
KeyPass深度解析:打造完全离线的现代密码管理解决方案
KeyPass深度解析:打造完全离线的现代密码管理解决方案 【免费下载链接】KeyPass KeyPass: Open-source & offline password manager. Store, manage, take control securely. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyPass 在数字时代࿰…...
新手必看:5分钟学会用Visio绘制PAD图和N-S图(附实例解析)
零基础掌握Visio绘制PAD图与N-S图的实战指南 在软件设计领域,可视化工具的重要性不言而喻。对于刚入门的开发者来说,掌握如何将抽象的逻辑思维转化为直观的图表是一项必备技能。Visio作为微软旗下的专业绘图工具,以其友好的界面和强大的功能&…...
Cursor Pro功能优化工具:提升AI编程体验的完整指南
Cursor Pro功能优化工具:提升AI编程体验的完整指南 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your trial …...
Realistic Vision V5.1 生态工具集成展示:与Cursor等AI编程助手联动工作流
Realistic Vision V5.1 生态工具集成展示:与Cursor等AI编程助手联动工作流 最近在尝试把各种AI工具串起来用,发现了一件挺有意思的事。以前我们做开发,写代码是一个工具,画界面图是另一个工具,做流程图还得再开一个软…...
Flux 图像生成 API 集成指南
在本篇文章中,我们将为您介绍 Flux 图像生成 API 的集成步骤。通过该 API,您可以输入自定义参数以生成官方的 Flux 图像。Flux 图像生成 API 是一个强大的工具,适用于需要图像生成的应用场景,如内容创作、游戏开发和广告设计等。 …...
