【低功耗蓝牙】① 蓝牙广播数据格式分析

2023-11-07

摘要

本文章主要讲解了蓝牙的发展史,蓝牙信号,蓝牙广播数据的格式。最后使用ESP32芯片MicroPython固件给出了蓝牙广播的具体代码,是蓝牙初学者很好的参考资料。

也可以参考下我在B站的蓝牙视频教程:

【ESP32教程】第二章: 低功耗蓝牙BLE相关概念及用法

如果您觉得这些资料有帮助,欢迎点击链接 让鹏老师恰口饭!

蓝牙发展史

蓝牙(Bluetooth)是一种无线通信协议,图标如下图所示:
蓝牙图标
蓝色的背景,中间像是一把白色的小剪刀,蓝牙的图标为什么是这样的呢?

这要从蓝牙的发展史说起!

1994-1997年之间,包括爱立信,英特尔,诺基亚在内的一些科技公司,想要制定一种短距离无线通信协议,用于各种电子设备之间通讯,取代当时的有线通信形式。
在这里插入图片描述
各个公司都推出了自己的通信协议,不同厂商的设备并不兼容。

在1997年的一次通信会议上,各个厂商希望制定一种统一的通信协议,使的他们的设备相互兼容。

来自英特尔的一位工程师 Jim Kardach 提议使用“Bluetooth”作为通信协议的名称。

他当时正在阅读有关维京人和哈拉尔国王的历史小说,由于哈拉尔国王以统一了因宗教战争和领土争议而分裂的挪威与丹麦而闻名于世,国王的成就与此次会议的的理念不谋而合,所以该工程师提议使用哈拉尔国王的绰号“Bluetooth”作为通信协议的名称。
在这里插入图片描述
传说哈拉尔国王有一个坏死的牙齿,变成的蓝色,所以世人就给他起了个绰号“Bluetooth”。 哈拉尔国王真名拼写“Harald”,蓝牙组织将国王的真名“Harald”和绰号“Bluetooth”的首字母拼合在一起,配以蓝牙的底图,就形成了蓝牙图标。
在这里插入图片描述

蓝牙技术演进史:

蓝牙技术演进史

蓝牙前言技术

目前蓝牙的最高版本是5.2,5.0以上新增的功能如下:

蓝牙5.0
引入 2Mbps 物理层,传输速率提升2倍
引入LongRang规范,传输距离提升4倍
蓝牙5.1
引入方向天线,实现高精度室内定位
蓝牙5.2
引入低功耗音频功能

低功耗蓝牙信道

蓝牙信道
蓝牙工作在2.4GHz频段,频率范围为 2402MHz – 2480 MHz,每 2MHz 一个信道,共40个信道,其中为3个广播信道,剩余的37为个数据信道。

蓝牙广播就是在这三个广播信道上,以一定的数据格式通过电磁波发射数据。

蓝牙广播数据格式

蓝牙广播包的最大长度是37个字节,其中设备地址占用了6个字节,只有31个字节是可用的。

31个可用的字节又按照一定的格式来组织,被分割为n个AD Structure。如下图所示:
蓝牙广播数据格式
每个AD Structure包含又包含三部分:

Length(1字节),AD Type(1字节),AD Data(n字节)

其中Length = AD Type 长度 + AD Data 长度

例如,如下广播数据:

0x04,0x09,0x41,0x42,0x43,0x03,0x19,0x80,0x01

按照蓝牙的广播数据格式可以解析为:
数据解析
通过上述方法,我们可以将蓝牙广播数据格式分割成若干个蓝牙广播结构体,但是先要知道每一个蓝牙广播结构体的含义,还必须知道广播结构体中AD Type 的含义。AD Type 由蓝牙组织联盟指定并发布,可以在蓝牙官方网站上下载相关文档,常用的AD Type及其含义如下:
常见的AD Type
那么现在,我们尝试分析下如下广播数据的含义:

0x05,0x09,0x31,0x32,0x33,0x34,0x02,0x0A,0x08,0x06,0xFF,0x41,0x50,0x50,0x4C,0x45

首先把他分割成一个个AD Structure,分割后如下图所示:

0x05,0x09,0x31,0x32,0x33,0x34
0x02,0x0A,0x08
0x06,0xFF,0x41,0x50,0x50,0x4C,0x45

一共可以分割成三个AD Structure:
第一个AD Structure的长度为0x05,类型为0x09(完成的设备名称),那么余下的数据含义就是完整的设备名称,0x31,0x32,0x33,0x34 按照UTF-8编码,就是1234。

第二个AD Structure的长度为0x02,类型为0x0A(发射功率),那么后面的数据0x08表示的就是发射功率。

第三个AD Structure 的长度为 0x06,类型为0xFF(厂商自定义数据),余下的数据0x41,0x50,0x50,0x4C,0x45就是厂商自定义的内容。

通过上面的示例,我想大部分读者应该都理解蓝牙广播数据格式了吧!接下来,我们就通过实践验证下上面的理论。

蓝牙广播实验

本实现使用的是ESP32芯片平台,Micro Python编程语言,uPyCraft开发环境,nRF Connect 手机 APP:
实践平台简介

开发环境的大家可以参考下我之前的这篇文章:自制教学用ESP32开发板【ESP32_Py_Board】① 开发环境搭建

我们在开发环境中键入如下代码,并运行:

from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块

ble = ubluetooth.BLE()  #创建BLE设备
ble.active(True)  #打开BLE

#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')

打开手机APP(开启蓝牙和定位的权限),可以搜索到蓝牙名称为AB的设备,如下图所示:
在这里插入图片描述
上面的代码很简单,仅仅是导入蓝牙功能,创建BLE实体,打开BLE,设置BLE的广播参数。

广播参数主要设置了蓝牙的广播时间间隔为100mS,广播数据为0x02,0x01,0x06,0x03,0x09,0x41,0x42

特别地

ADType 0x01 表示的是设备标识,其含义如下:

数据位 含义
Bit0 LE 有限可发现模式
Bit1 LE 普通可发现模式
Bit2 不支持BR/EDR(经典蓝牙)
BIt3 控制器端同时支持BR/EDR和LE
Bit4 主机端同时自持BR/EDR和LE
Bit5-7 保留
我们的设备只支持LE(低功耗蓝牙),不支持BR/EDR(经典蓝牙),一般我们都处于普通发现模式,所以我们只设置Bit1和Bit2,及0x06(b00000110)。

直播的时候,有家人问,能否将蓝牙设备名称改为中文呢?

当然是可以的,蓝牙名称采用的是UTF-8编码,理论上可以编码出任意国家的文字和字符。

python语言中,可以使用.encode("UTF-8")将字符串传换成UTF-8编码的数组,需要注意的是,一个汉字转换成UTF-8编码后,将占用三个字节的存储空间。

比如,要将蓝牙设备的名称改为,可以使用如下代码:

from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块

ble = ubluetooth.BLE()  #创建BLE设备
ble.active(True)  #打开BLE

#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x04\x09' + "中".encode("UTF-8"))

扫描到的蓝牙设备如下图:
在这里插入图片描述

蓝牙扫描请求和扫描响应

蓝牙设备除了可以主动的发射广播数据外,还可以接受其他设备的扫描请求,从而响应额外的数据,二者的区别如下:

广播是蓝牙从机设备主动发出的数据。

而扫描响应是, 当蓝牙主机收到从机的广播数据后,如果想要进一步了解从机的信息,可以向从机发送扫描请求,从机收到扫描请求后,向对应的主机回复扫描响应。
蓝牙扫描响应
扫描响应的数据格式和蓝牙广播的数据格式完全一样,其作用也基本一样,那为什么还要设置这么一个扫描响应数据呢?

我们前文中讲到,蓝牙的广播数据最多是31个字节,如果广播数据太多,这31个字节装不下时,我们就可以将一部分不太重要的数据放到扫描响应数据里面,来分担广播数据的工作。

蓝牙广播类型

按照蓝牙设备是否支持被链接,是否支持扫描响应,广播类型可以分为如下四类:

可连接的非定向广播: Connectable Undirected Event Type):

最常用的广播方式,可以被扫描,可以被连接。被连接后将进入连接状态。

可连接的定向广播:

主要用于快速连接的需求,其广播的数据中只包含自身地址和对方地址,对方收到发送给自己的定向广播后,会立即发起连接请求,达到快速建立连接的目的。定向广播在广播时会占满整个信道,造成信道拥堵,所以协议规定定向广播广播的最长时间不得超过1.28秒

不可连接的非定向广播:

仅仅发送广播数据,而不能被扫描或者连接。这也是唯一可用于只有发射机而没有接收机设备的广播类型。不可连接广播设备不会进入连接态。

(不可连接)可扫描的非定向广播(Scannable Undirected Event Type):

又称可发现广播,这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描回应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。
广播类型
如果有不清楚的地方,欢迎在下方留言!

下一篇:【低功耗蓝牙】② 蓝牙状态切换和事件处理

作者:我是鹏老师

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【低功耗蓝牙】① 蓝牙广播数据格式分析 的相关文章

  • ESP32/ESP8266使用MicroPython控制DHT11/DHT22

    本教程介绍了如何使用MicroPython固件将DHT11或DHT22温度和湿度传感器与ESP32和ESP8266开发板一起使用 DHT模块 刷新MicroPython固件 要遵循本教程 您需要在ESP32或ESP8266板上安装Micro
  • nRF52832学习记录(一、外设初识之 GPIOTE)

    添加GPIO和GPIOTE寄存器表 对于应用的理解对着寄存器查看会比较明了 这个不管是在哪款芯片上都是如此 2021 9 27 这些年蓝牙5 0的应用越来越多 最近也是想着把以前Enocean的低功耗设备有过的产品 用蓝牙做一套匹配的版本
  • ESP32 的esp_http_client详解

    说明 我使用的是esp idf V3 1 3 官方给我们封装好了 HTTP 使用起来还是很方便 一 wifi连接 在main函数里面主要是做了wifi连接的初始化和HTTP任务的创建 如下是main的全部内容 void app main e
  • Android 蓝牙开发基本流程

    http blog csdn net q610098308 article details 45248423 此例子基于 Android demo 对于一般的软件开发人员来说 蓝牙是很少用到的 尤其是Android的蓝牙开发 国内的例子很少
  • esp32-S3专题二:内存1之RAM使用

    esp32 S3模块内部的存储分为ROM RAM SPRAM RTC内存 FLASH 种类很多 几乎可以不使用外接存储器的情况下 可以进行很多业务场景 十分有用 现在我们逐一讲解一下他们的作用和使用方法 一 ROM 384 KB 内部 RO
  • 蓝牙协议规范--L2CAP

    L2CAP 分析 记住一点 软件和硬件分开理解 数据经由物理通道交互 上层通道由各层协议打通 L2CAP 全称为逻辑链路控制与适配协议 Logical Link Control and Adaptation Protocol 位于基带层之上
  • HFP协议

    通话专题HFP协议学习总结 一 配置和角色 二 HFP的连接 2 1服务级连接建立 2 1 1 服务发现和RFCOMM的连接 2 1 2 支持的特性交换 2 1 3 codec协商 2 1 4 HF指示器 2 1 5 AG指示器 2 1 6
  • SimpleFOC无刷电机平衡小车

    前言 本科毕业于自动化 期间学习了各种电机运动控制原理 自动控制原理 但是只会考试而未究其理 最近接触到simplefoc这个基于arduino的开源无刷电机驱动库 想正好借此机会将本科学到的内容用于实际 于是就有了这个小项目 基于无刷电机
  • 蓝牙设备中的Device UUID 与 Service UUID

    Device UUID也可以被称作为DeviceID Android 设备上扫描获取到的 deviceId 为外围设备的 MAC 地址 相对固定 iOS 设备上扫描获取到的 deviceId 是系统根据外围设备 MAC 地址及发现设备的时间
  • OPENV接收和发送串口的数据

    import sensor image time from pyb import UART from pyb import Pin Timer LED import re sensor reset sensor set pixformat
  • 【Android系统蓝牙开发】蓝牙基础知识-蓝牙核心系统架构

    什么是蓝牙 在开启基于蓝牙Spec v5 2的学习前 我们先了解下什么是蓝牙 蓝牙在我们日常生活中又存在哪些实际应用呢 蓝牙无线技术是一种短距离无线通信系统 其核心特性主要是以下三点 robustness 鲁棒性 抗干扰能力强 Low po
  • ESP32开发阶段启用 Secure Boot 与 Flash encryption

    Secure Boot 与 Flash encryption详情 请参考 https blog csdn net espressif article details 79362094 1 开发环境 AT版本 2 4 0 0 发布 IDF 与
  • Micropython开发篇三--基于F411 CE的移植编译

    Micropython开发篇三 基于F411 CE的移植编译 最近在学操作系统 RTOS与Linux 对Micropython有些新的认知 回头又复习了一下Micropython 简直要不要这么优秀 希望通过这篇文章能带给大家不一样的Mic
  • VSCode 上的 PlatformIO 未编译:collect2.exe:错误:ld 返回 1 退出状态

    我最近不得不擦拭我的计算机 在一切准备就绪并运行之后 是时候打开我之前正在处理的一些 ESP32 程序了 发现 VSCode 上的 Platform IO 将不再编译 运行编译器后 我收到以下错误 Compiling pio build e
  • Google iot MQTT - ESP32 首次连接,仅在 30m 后重新连接

    我正在使用 ESP32 与谷歌物联网云合作 我发送假值只是为了使用 MQTT 数据 PUB SUB 进行测试 显然我成功发布了值 有时 我无法重新连接到谷歌物联网 我不知道为什么它不断检查 wifi publishing 并且不检查 JWT
  • 使用什么 ffmpeg 命令将无符号整数列表转换为音频文件?

    我有一个文件 其中包含大约四万个整数的列表 这些整数以空格分隔 每个整数的值都在 0 到 255 之间 这里是这个文件 https github com johnlai2004 sound project blob master integ
  • ESP32 上的 Web 服务器:如何自动更新和显示来自服务器的传感器值?

    我在 ESP32 上有一个网络服务器 在该服务器上有一个主页 我想每隔 x 秒自动更新主页上的传感器值 无需用户输入 我无法访问文件系统 该传感器直接连接到 ESP32 传感器值位于我的 C 程序中 存储在变量中并定期更新 变量是全局的 以
  • ESP32 Arduino-ide如何获取唯一id

    我试图自动为每个 esp32 设置一个唯一的 id 在我使用提供该方法的 ESP IDF 框架对设备进行编程之前esp efuse mac get default 这将返回一个 8 字节值 该值在我手上的所有设备上都是唯一的 在arduin
  • 函数内部导入:函数退出时是否回收内存?

    相关问题 python 在文件顶部导入与在函数内部导入 https stackoverflow com questions 46813425 python import at top of file vs inside a function
  • 使用 re.match 或 re.search 返回多个匹配项

    我正在将一些代码转换为微型蟒蛇 http micropython org我陷入了一个特定的正则表达式 在Python中我的代码是 import re line 0 1 24 2 1 180108205500W 00001 290 m3 be

随机推荐

  • 如何实现概率性事件

    游戏中经常会遇到概率性的问题 比如装备升级的成功率 合成宝石的成功率 洗装备时出现随机属性条数的概率等 这些概率性事件具体是怎么实现的呢 在网上看了一些相关的文章 总结一下 首先需要了解两个函数rand 和srand 下面是百科里面的解释
  • 如何存储Ajax请求的响应值

    如何存储Ajax请求的响应值 一 背景 二 代码部分 三 总结 一 背景 开发者使用Ajax请求网络 获取到了返回的结果 但开发者不想将回调函数写的过于冗长 因此希望将Ajax请求的返回值存储到一个变量中 方便后期取用 二 代码部分 代码部
  • Qt简介以及工程创建

    Qt是一种跨平台应用程序和UI开发框架 只需要一次性开发应用程序 可应用于不同的系统 Qt不是一个严格的前后端 而是一种框架 Qt Creator是一种全新跨平台 Qt IDE集成开发环境 可以单独使用 也可以与Qt库和开发工具组成一套完整
  • Unhandled exception at 0x00291422 in x.exe: 0xC0000005: Access violation writing location 0x37ACCE08

    源码如下 include
  • 线性表顺序存储の介绍、应用 与 实践(第二章: 线性表 )

    一 线性表的介绍 线性表 线性表 linear list 是n个具有相同特性的数据元素的有限序列 线性表是一种在实际中广泛使用的数据结构 常见的线性表 顺序表 链表 栈 队列 字符串 线性表在逻辑上是线性结构 也就说是连续的一条直线 但是在
  • 代码覆盖度工具OpenCppCoverage(cpp)、EclEmma(java)、Coverage(python)使用

    一 OpenCppCoverage cpp OpenCppCoverage是一个运行在windows上的程序 其不是在编译时进行插桩 而是在运行时 因此保证了代码和测试的一致性 参考文档 https github com OpenCppCo
  • 【c/c++】#pragma once 与 #ifndef 的区别解析

    原文地址 http blog csdn net hkx1n article details 4313303 作用 为了避免同一个文件被include多次 C C 中有两种方式 一种是 ifndef方式 一种是 pragma once方式 在
  • 智能指针使用陷阱

    智能指针使用陷阱 1 不能把一个原生指针交给多个智能指针管理 int x new int 10 unique ptr
  • android同步目录,如何使用FolderSync在安卓手机上同步文件夹到坚果云?

    FolderSync 是一款Android 端的文件同步工具 可以将手机中的文件自动同步到云端空间或者PC端 支持包括 FTP WebDAV Dropbox Amazon S3 FTP FTPS SFTP WebDAV等 可以使用WebDA
  • 几种图像的分割方法汇总

    图像分割指的是将原图像按照灰度 纹理 颜色 形状等划分成不同的区域 因此 在同一个区域间 呈现出具备一些相同的特点 而在不同的区域间 分割出的各个图像会有一定的差别 1 基于阈值的分割方法 基于阈值的分割方法是按照原图像的灰度特征划分出一个
  • k8s——kubectl

    目录 一 k8s管理操作方法 二 陈述式资源管理方法 1 基本信息查看 1 1 查看k8s版本信息 1 2 查看资源对象简写 1 3 查看集群信息 1 4 配置kubectl自动补全 1 5 node节点查看日志 2 基本信息查看 2 1
  • 大数据高频面试题【目录】

    大数据高频面试题 目录 小标题既超链接 点击可直接跳转 手写代码 Linux Shell Hadoop Flume Kafka Hive HBase Sqoop Scala Spark 项目中的常见问题 JavaSE Redis MySQL
  • LM393 电压比较器及其典型电路介绍

    这几天都在看一些开源项目 好多代码都没有什么注释 看烦了 看看小芯片吧 LM393 主要用途 限幅器 脉冲发生器 方波发生器 延时发生器 数字逻辑门电路 多频振荡器等等 引脚分布图 等效电路图 同相端电压大于反向端电压时 输出高电平 同相端
  • 【python】使用matplotlib绘制柱状图

    在制作图标时需要绘制柱状图 下面对其进行了绘制 主要就是使用matplotlib的bar函数 bar函数官方API为 matplotlib pyplot bar 下面是从一篇论文中随意截取的一段话 进行后续的绘制图像 import matp
  • 服务器故障排查方法总结

    服务器故障排查方法总结 问题描述 查找步骤 1 查找top检查服务器负载是否有问题 2 在服务器中查看网站的访问记录 3 这个时候先对数据库进行重启 对apache进行重启 4 查找数据库错误日志 问题描述 每当出现网站访问不了的时候 估计
  • Java list修改某个元素值的方法

    修改list中下标为index对象的值 set index element 增添 add index element
  • 在Android上修改读取IMEI码的方法

    我们知道 如果是移动设备 厂家都提供了IMEI码写入及读出的方法 但由于我们的是非移动设备 可是我们也需要写入IMEI码 供第三方的软件读取 如正版地图等 我们找到frameworks base telephony java android
  • selenium 隐式等待如何使用_selenium 中使用等待的三种方法

    现在很多的 web 网站使用 AJAX 技术 当页面加载到浏览器 这个页面的很多元素显示出来的可能不一致 如果一个元素还未加载出来 在定位的时候 就会抛出异常 ElementNotVisibleException 这个时候就要使用等待方法解
  • 【转】latex常见错误对照表

    原文链接 http www cs utexas edu witchel errorclasses html Latex Error Classes Ambiguous Errors This is a list of error class
  • 【低功耗蓝牙】① 蓝牙广播数据格式分析

    摘要 本文章主要讲解了蓝牙的发展史 蓝牙信号 蓝牙广播数据的格式 最后使用ESP32芯片MicroPython固件给出了蓝牙广播的具体代码 是蓝牙初学者很好的参考资料 也可以参考下我在B站的蓝牙视频教程 ESP32教程 第二章 低功耗蓝牙B