目录
前言
蓝牙低能耗(Bluetooth Low Energy,简称BLE)作为现代物联网和智能设备通信的核心技术,以其低功耗、高效率的特点彻底改变了短距离无线通信的格局。本文将从BLE的基础概念出发,深入剖析其协议架构、数据格式和工作原理,并通过丰富的代码示例展示如何在实际项目中应用BLE技术。无论您是刚接触蓝牙开发的初学者,还是希望深入理解BLE内部机制的专业开发者,本文都将为您提供全面的技术指导和实践参考
BLE(蓝牙低能耗,Bluetooth Low Energy)是一种无线通信技术,主要用于短距离的数据传输。它的设计目的在于低功耗和高效率,适合于需要长时间运行而不频繁充电的设备。
参考链接:bluetooth — low-level Bluetooth — MicroPython v1.23.0 documentation
BLE的特点
- 低功耗:BLE设备在待机时消耗的电量非常少,这使得它们可以使用小型电池运行很长时间,甚至几年。
- 短距离:BLE通常在10米到100米的范围内工作,适合家庭、办公室等环境。
- 快速连接:BLE可以快速建立连接,减少了设备之间的响应时间。
- 数据传输:适合传输小量数据,比如传感器读取、健康监测数据等。
蓝牙协议栈
GAP(Generic Access Profile)和 GATT(Generic Attribute Profile)是蓝牙低功耗(BLE)中的两个核心协议。它们分别定义了设备之间的通信方式和访问规则。以下是这两个协议的简要介绍:
1. GAP 协议
GAP是蓝牙低功耗的通用访问配置文件,定义了设备之间如何发现、连接和交换数据的基本规则。GAP是BLE通信的基础,负责管理设备的发现和连接过程。
主要特点:
- 设备角色:GAP定义了设备在BLE通信中的角色,包括:
-
- 广播设备(Advertiser):发送广播包以进行设备发现。
- 扫描设备(Scanner):监听并响应广播包,发现其他设备。
- 主设备(Central):发起连接的设备(通常是手机或主控制器)。
- 从设备(Peripheral):被连接的设备(如传感器、穿戴设备)。
- 设备发现:GAP定义了设备如何通过广播和扫描发现其他设备。设备可以处于可发现模式或不可发现模式。
- 连接管理:GAP负责建立、管理和终止连接。它处理连接间隔、超时和其他连接参数。
应用场景:
GAP广泛应用于各种BLE设备之间的发现和连接过程,确保设备能够有效地找到并连接到彼此。
2. GATT 协议
GATT是蓝牙低功耗中的一种通用属性配置文件,主要用于定义如何在BLE设备之间传输数据。它提供了一种标准化的方式来组织和描述设备中的数据。
主要特点:
- 服务和特性:GATT基于服务和特性构建,服务是一组相关的特性。每个服务和特性都有唯一的UUID标识符。
- 数据模型:GATT使用层次结构的数据模型,设备通过服务和特性与其他设备进行交互。
- 数据传输方式:GATT支持读取、写入、通知和指示等操作:
-
- 读取(Read):客户端可以请求服务器读取特性值。
- 写入(Write):客户端可以向服务器写入特性值。
- 通知(Notify):服务器可以主动向客户端发送特性值的变化。
- 指示(Indicate):服务器向客户端发送特性值的变化,并等待客户端的确认。
应用场景:
GATT通常用于传感器、健康设备、智能家居设备等场景,如心率监测器、温度传感器等。这些设备通过GATT服务和特性与其他BLE设备(如手机应用)进行数据交换。
总结🙃🙃🙃
- GAP:负责设备发现和连接管理,定义设备的角色和连接过程。
- GATT:负责设备之间的数据交换和数据组织,通过服务和特性来定义如何读取、写入和通知数据。
这两个协议相辅相成,构成了蓝牙低功耗通信的基础,使得不同设备能够高效地进行数据交换和管理。
1. 蓝牙广播数据格式
蓝牙广播包的最大长度是37个字节,其中设备地址占用了6个字节,只有31个字节是可用的。这31个可用的字节又按照一定的格式来组织,被分割为n个AD Structure。
每个AD Structure包含3部分内容,分别是:
- Length(1字节): 广播数据包的长度
- AD Type(1字节): 广播的类型
- AD Data(n字节): 数据
下面有一条广播数据,你能把分析一下它所表示的含义吗?
02 01 06 08 09 69 63 68 65 69 6D 61 03 19 C1 03
arr = bytearray([
0x02, 0x01, 0x06,
0x08, 0x09, 0x69, 0x63, 0x68, 0x65, 0x69, 0x6D, 0x61,
0x03, 0x19, 0xC1, 0x03
])
常用的广播类型如下:
AD TYPE为0x01时,它的含义说明:
我们的设备只支持BLE, 不支持经典蓝牙, 并且它是处在普通可发现模式,
所以0x01对应的值我们填写为:0x0000 0110
发送蓝牙广播数据所使用的api如下:
# 发送广播
bt.gap_advertise(100, adv_data)
其中第1个参数是时间,单位为ms, 范围为20ms-625ms, 如果你设置的时间超过625ms, 其它设备可能就收不到你的广播了
from bluetooth import BLE
import bluetooth
bt = BLE() #创建蓝牙对象
bt.active(1)#打开蓝牙
SERVER_1_UUID = bluetooth.UUID(0x9011)
CHAR_A_UUID = bluetooth.UUID(0x9012)
CHAR_B_UUID = bluetooth.UUID(0x9013)
#设置特性的读写权限
CHAR_A = ( CHAR_A_UUID, bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
CHAR_B = ( CHAR_B_UUID, bluetooth.FLAG_READ | bluetooth.FLAG_WRITE,)
#把特性A和特性B放入服务1
SERVER_1 = (SERVER_1_UUID, (CHAR_A, CHAR_B),)
#把服务1放入 服务集合 中
SERVICES = (SERVER_1,)
#注册服务到gatts
((char_a, char_b),) = bt.gatts_register_services(SERVICES)
# BLE 广播包构建
def create_adv_data(name):
# 构建广播包
# 格式为:长度, 类型, 数据...
# 其中,类型 0x01 表示"Flags", 0x09 表示"Complete Local Name"
# Flags 数据通常设置为 0x06 (通用可发现模式和BR/EDR不支持)
# 更多类型可以在 Bluetooth SIG 的广告数据类型文档中找到
adv_data = bytearray([0x02, 0x01, 0x06, # Flags
len(name)*3+1, 0x09]) + bytearray(name.encode("utf-8"))
return adv_data
#设置广播名称 B站:宝安钢铁侠
adv_data = bytearray([0x02, 0x01, 0x06, # Flags
21, 0x09]) + bytearray([0x42, 0xe7, 0xab, 0x99, 0x3a, 0xe5, 0xae, 0x9d, 0xe5, 0xae, 0x89, 0xe9, 0x92, 0xa2, 0xe9, 0x93, 0x81, 0xe4, 0xbe, 0xa0])
#开启广播
bt.gap_advertise(100, adv_data)
#蓝牙中断复位函数
def ble_irq(event, data):
if event == 1:#蓝牙已经连接
print('bluetooth connection')
pass
elif event == 2:#蓝牙断开连接
print('Bluetooth disconnection')
bt.gap_advertise(100, adv_data)
elif event == 3:#写入事件
print('Write event')
#将data元素拆分为两个数据
conn_handle, chan_handle = data
#读取chan_handle的数据
buffer = bt.gatts_read(chan_handle)
#输出接收到的数据
print(buffer)
if buffer == b'A': #如果数据为单个字符A
print('fasong B\r\n')
#向手机通道(conn_handle)发送数据chan_handle 单个字符B
bt.gatts_notify(1, char_a, b'B')
bt.irq(ble_irq)
答案:🙃
02 01 06 // 0x06 默认值,可发现模式
08 09 69 63 68 65 69 6D 61 // 蓝牙名称为: "icheima"
03 19 C1 03 // 外观为键盘:3c1
1.1. 蓝牙外观查询表
Key | Value | Description |
0x0000 | Unknown | None |
0x0040 | Generic Phone | Generic category |
0x0080 | Generic Computer | Generic category |
0x00C0 | Generic Watch | Generic category |
0x00C1 | Watch: Sports Watch | Watch subtype |
0x0100 | Generic Clock | Generic category |
0x0140 | Generic Display | Generic category |
0x0180 | Generic Remote Control | Generic category |
0x01C0 | Generic Eye-glasses | Generic category |
0x0200 | Generic Tag | Generic category |
0x0240 | Generic Keyring | Generic category |
0x0280 | Generic Media Player | Generic category |
0x02C0 | Generic Barcode Scanner | Generic category |
0x0300 | Generic Thermometer | Generic category |
0x0301 | Thermometer: Ear | Thermometer subtype |
0x0340 | Generic Heart rate Sensor | Generic category |
0x0341 | Heart Rate Sensor: Heart Rate Belt | Heart Rate Sensor subtype |
0x0380 | Generic Blood Pressure | Generic category |
0x0381 | Blood Pressure: Arm | Blood Pressure subtype |
0x0382 | Blood Pressure: Wrist | Blood Pressure subtype |
0x03C0 | Human Interface Device (HID) | HID Generic |
0x03C1 | Keyboard | HID subtype |
0x03C2 | Mouse | HID subtype |
0x03C3 | Joystick | HID subtype |
0x03C4 | Gamepad | HID subtype |
0x03C5 | Digitizer Tablet | HID subtype |
0x03C6 | Card Reader | HID subtype |
0x03C7 | Digital Pen | HID subtype |
0x03C8 | Barcode Scanner | HID subtype |
0x0400 | Generic Glucose Meter | Generic category |
0x0440 | Generic: Running Walking Sensor | Generic category |
0x0441 | Running Walking Sensor: In-Shoe | Running Walking Sensor subtype |
0x0442 | Running Walking Sensor: On-Shoe | Running Walking Sensor subtype |
0x0443 | Running Walking Sensor: On-Hip | Running Walking Sensor subtype |
0x0480 | Generic: Cycling | Generic category |
0x0481 | Cycling: Cycling Computer | Cycling subtype |
0x0482 | Cycling: Speed Sensor | Cycling subtype |
0x0483 | Cycling: Cadence Sensor | Cycling subtype |
0x0484 | Cycling: Power Sensor | Cycling subtype |
0x0485 | Cycling: Speed and Cadence Sensor | Cycling subtype |
0x0C40 | Generic: Pulse Oximeter | Pulse Oximeter Generic Category |
0x0C41 | Fingertip | Pulse Oximeter subtype |
0x0C42 | Wrist Worn | Pulse Oximeter subtype |
0x0C80 | Generic: Weight Scale | Weight Scale Generic Category |
0x0CC0 | Generic Personal Mobility Device | Personal Mobility Device |
0x0CC1 | Powered Wheelchair | Personal Mobility Device |
0x0CC2 | Mobility Scooter | Personal Mobility Device |
0x0D00 | Generic Continuous Glucose Monitor | Continuous Glucose Monitor |
0x0D40 | Generic Insulin Pump | Insulin Pump |
0x0D41 | Insulin Pump, durable pump | Insulin Pump |
0x0D44 | Insulin Pump, patch pump | Insulin Pump |
0x0D48 | Insulin Pen | Insulin Pump |
0x0D80 | Generic Medication Delivery | Medication Delivery |
0x1440 | Generic: Outdoor Sports Activity | Outdoor Sports Activity Generic Category |
0x1441 | Location Display Device | Outdoor Sports Activity subtype |
0x1442 | Location and Navigation Display Device | Outdoor Sports Activity subtype |
0x1443 | Location Pod | Outdoor Sports Activity subtype |
0x1444 | Location and Navigation Pod | Outdoor Sports Activity subtype |
<Format>16bit</Format>
<Enumerations>
<Enumeration key="0" value="Unknown" description="None"/>
<Enumeration key="64" value="Generic Phone" description="Generic category"/>
<Enumeration key="128" value="Generic Computer" description="Generic category"/>
<Enumeration key="192" value="Generic Watch" description="Generic category"/>
<Enumeration key="193" value="Watch: Sports Watch" description="Watch subtype"/>
<Enumeration key="256" value="Generic Clock" description="Generic category"/>
<Enumeration key="320" value="Generic Display" description="Generic category"/>
<Enumeration key="384" value="Generic Remote Control" description="Generic category"/>
<Enumeration key="448" value="Generic Eye-glasses" description="Generic category"/>
<Enumeration key="512" value="Generic Tag" description="Generic category"/>
<Enumeration key="576" value="Generic Keyring" description="Generic category"/>
<Enumeration key="640" value="Generic Media Player" description="Generic category"/>
<Enumeration key="704" value="Generic Barcode Scanner" description="Generic category"/>
<Enumeration key="768" value="Generic Thermometer" description="Generic category"/>
<Enumeration key="769" value="Thermometer: Ear" description="Thermometer subtype"/>
<Enumeration key="832" value="Generic Heart rate Sensor" description="Generic category"/>
<Enumeration key="833" value="Heart Rate Sensor: Heart Rate Belt" description="Heart Rate Sensor subtype"/>
<!-- Added Blood pressure support on December 09, 2011 -->
<Enumeration key="896" value="Generic Blood Pressure" description="Generic category"/>
<Enumeration key="897" value="Blood Pressure: Arm" description="Blood Pressure subtype"/>
<Enumeration key="898" value="Blood Pressure: Wrist" description="Blood Pressure subtype"/>
<!-- Added HID Related appearance values on January 03, 2012 approved by BARB -->
<Enumeration key="960" value="Human Interface Device (HID)" description="HID Generic"/>
<Enumeration key="961" value="Keyboard" description="HID subtype"/>
<Enumeration key="962" value="Mouse" description="HID subtype"/>
<Enumeration key="963" value="Joystick" description="HID subtype"/>
<Enumeration key="964" value="Gamepad" description="HID subtype"/>
<Enumeration key="965" value="Digitizer Tablet" description="HID subtype"/>
<Enumeration key="966" value="Card Reader" description="HID subtype"/>
<Enumeration key="967" value="Digital Pen" description="HID subtype"/>
<Enumeration key="968" value="Barcode Scanner" description="HID subtype"/>
<!-- Added Generic Glucose Meter value on May 10, 2012 approved by BARB -->
<Enumeration key="1024" value="Generic Glucose Meter" description="Generic category"/>
<!-- Added additional appearance values on June 26th, 2012 approved by BARB -->
<Enumeration key="1088" value="Generic: Running Walking Sensor" description="Generic category"/>
<Enumeration key="1089" value="Running Walking Sensor: In-Shoe" description="Running Walking Sensor subtype"/>
<Enumeration key="1090" value="Running Walking Sensor: On-Shoe" description="Running Walking Sensor subtype"/>
<Enumeration key="1091" value="Running Walking Sensor: On-Hip" description="Running Walking Sensor subtype"/>
<Enumeration key="1152" value="Generic: Cycling" description="Generic category"/>
<Enumeration key="1153" value="Cycling: Cycling Computer" description="Cycling subtype"/>
<Enumeration key="1154" value="Cycling: Speed Sensor" description="Cycling subtype"/>
<Enumeration key="1155" value="Cycling: Cadence Sensor" description="Cycling subtype"/>
<Enumeration key="1156" value="Cycling: Power Sensor" description="Cycling subtype"/>
<Enumeration key="1157" value="Cycling: Speed and Cadence Sensor" description="Cycling subtype"/>
<!-- Added appearance values for Pulse Oximeter on July 30th, 2013 approved by BARB -->
<Enumeration key="3136" value="Generic: Pulse Oximeter" description="Pulse Oximeter Generic Category"/>
<Enumeration key="3137" value="Fingertip" description="Pulse Oximeter subtype"/>
<Enumeration key="3138" value="Wrist Worn" description="Pulse Oximeter subtype"/>
<!-- Added appearance values for Generic Weight Scale on May 21, 2014 approved by BARB -->
<Enumeration key="3200" value="Generic: Weight Scale" description="Weight Scale Generic Category"/>
<!-- Added additional appearance values on October 2nd, 2016 approved by BARB -->
<Enumeration key="3264" value="Generic Personal Mobility Device" description="Personal Mobility Device"/>
<Enumeration key="3265" value="Powered Wheelchair" description="Personal Mobility Device"/>
<Enumeration key="3266" value="Mobility Scooter" description="Personal Mobility Device"/>
<Enumeration key="3328" value="Generic Continuous Glucose Monitor" description="Continuous Glucose Monitor"/>
<!-- Added additional appearance values on February 1st, 2018 approved by BARB -->
<Enumeration key="3392" value="Generic Insulin Pump" description="Insulin Pump"/>
<Enumeration key="3393" value="Insulin Pump, durable pump" description="Insulin Pump"/>
<Enumeration key="3396" value="Insulin Pump, patch pump" description="Insulin Pump"/>
<Enumeration key="3400" value="Insulin Pen" description="Insulin Pump"/>
<Enumeration key="3456" value="Generic Medication Delivery" description="Medication Delivery"/>
<!-- Added appearance values for L&N on July 30th, 2013 approved by BARB -->
<Enumeration key="5184" value="Generic: Outdoor Sports Activity" description="Outdoor Sports Activity Generic Category"/>
<Enumeration key="5185" value="Location Display Device" description="Outdoor Sports Activity subtype"/>
<Enumeration key="5186" value="Location and Navigation Display Device" description="Outdoor Sports Activity subtype"/>
<Enumeration key="5187" value="Location Pod" description="Outdoor Sports Activity subtype"/>
<Enumeration key="5188" value="Location and Navigation Pod" description="Outdoor Sports Activity subtype"/>
<!-- Added appearance values for Generic Environmental Sensor on May 21, 2014 approved by BARB
<Enumeration key="5696" value="Generic: Environmental Sensor" description="Environmental Sensor Generic Category" /> -->
</Enumerations>
2. 蓝牙状态机
蓝牙链路层的状态机有五种状态,分别是就绪态,广播态,链接态,扫描态,发起链接态,各个状态间的转换路径如下图所示:
以手机连接ESP32模块为例, 手机为主设备, esp32为从设备。
- 上电之后,手机和esp32就都处于就绪态。
- esp32开启广播功能,它就处在了广播态。
- 手机打开蓝牙,扫描周围的设备,它就处在了扫描态。
- 手机尝试连接esp32设备,手机此时就处在了发起态。
- 连接成功之后,二者就都处于连接态。
3. 蓝牙事件处理
蓝牙设备通常有蓝牙连接成功,断开连接,收到数据等事件。 在micropython中,通过终端程序来处理这些事件。代码如下:
#蓝牙中断复位函数
def ble_irq(event, data):
if event == 1:#蓝牙已经连接
print('bluetooth connection')
pass
elif event == 2:#蓝牙断开连接
print('Bluetooth disconnection')
bt.gap_advertise(100, adv_data)
elif event == 3:#写入事件
print('Write event')
bt.irq(ble_irq)
上述代码其实就是一个中断函数,当中断事件产生的时候,我们根据事件的编号去处理对应的事件。
- 当事件1产生的时候,蓝牙处于连接态
- 当事件2产生的时候,断开了连接,它就进入到了就绪态,要想让它能继续被其它设备连接,则需要切换到广播态
- 当事件3产生的时候,说明可以进行数据处理了
4. 蓝牙服务和特性
蓝牙服务(Service)和特性(Characteristic)是**蓝牙低功耗(BLE)**通信中的核心概念,它们定义了蓝牙设备如何组织和传递数据 . 在开始学习这一节内容之前,我们先来补充一个小知识点UUID
4.1. UUID
UUID是 Universally Unique Identifier 的缩写,翻译成中文为 通用唯一标识符。是蓝牙组织联盟定义的用于区分蓝牙服务和特性的的标识符,总长度为128 Bit。
03B80E5A-EDE8-4B33-A751-6CE34EC4C700
7772E5DB-3868-4112-A1A9-F2669D106BF3
128Bit的UUID占用16个字节,在变成个传输的时候都很不方便,所以蓝牙联盟定义了一个UUID的基地址,允许在此基础上使用16Bit的UUID。
UUID基地址:0x0000xxxx-0000-1000-8000-00805F9B34FB
比如16Bit的UUID : 0x2A37 转换成128Bit的UUID为:
0x00002A37-0000-1000-8000-00805F9B34FB
4.2. 服务和特性
在洗脚城,服务员提供多种服务,比如洗脚、按摩、提供饮料等。每项服务都可以细分为多个特定的操作。
4.2.1. 服务(Service)
在这个例子中,洗脚城的每种服务可以看作是一个服务。例如:
- 洗脚服务(Foot Washing Service)
- 按摩服务(Massage Service)
每项服务都有其独特的目的和功能,类似于蓝牙中的服务。
4.2.2. 特性(Characteristic)
每个服务下面又包含具体的特性,表示该服务的不同方面或操作。以下是对每项服务的特性细分:
- 洗脚服务(Foot Washing Service)
-
- 特性:洗脚水温(Water Temperature)
-
-
- 描述:服务员可以读取水温,并确保适合客户。
-
-
- 特性:洗脚时间(Washing Duration)
-
-
- 描述:服务员可以记录洗脚的持续时间。
-
-
- 特性:洗脚方式(Washing Method)
-
-
- 描述:服务员可以选择不同的洗脚方式,如浸泡、擦洗等。
-
- 按摩服务(Massage Service)
-
- 特性:按摩类型(Massage Type)
-
-
- 描述:服务员可以选择不同的按摩类型,如舒缓按摩、深层按摩等。
-
-
- 特性:按摩时长(Massage Duration)
-
-
- 描述:服务员可以设置按摩的时间。
-
在这个洗脚城的例子中:
- 洗脚服务、按摩服务就相当于蓝牙服务,它们代表了洗脚城提供的不同功能。
- 每项服务下的洗脚水温、洗脚时间、按摩类型等特性就相当于蓝牙特性,它们代表了具体的、可操作的数据。
4.2.3. 类比到蓝牙中
- 服务(Service)是一个功能的集合(如心率监测、血糖监测)。
- 特性(Characteristic)是具体的数据项,可以进行读、写或通知(如心率值、血糖值)。
4.2.4. 实际例子
结合前面我们所讲的UUID, 我们以黑马洗脚城的例子来进行说明:
洗脚城有两个服务员,分别是0x9520号服务员和0x9521号服务员
0x9520服务员:你跟他说0x2030,就相当于是选定了按摩的类型
0x9521服务员:你跟他说0x1001,他就把水温调到45°
4.2.5. 代码演示
SERVER_1_UUID = bluetooth.UUID(0x9520)
CHAR_A_UUID = bluetooth.UUID(0x2030)
CHAR_B_UUID = bluetooth.UUID(0x2031)
#设置特性的读写权限
CHAR_A = ( CHAR_A_UUID, bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
CHAR_B = ( CHAR_B_UUID, bluetooth.FLAG_READ | bluetooth.FLAG_WRITE,)
#把特性A和特性B放入服务1
SERVER_1 = (SERVER_1_UUID, (CHAR_A, CHAR_B),)
#把服务1放入 服务集合 中
SERVICES = (SERVER_1,)
#注册服务到gatts
((char_a, char_b),) = bt.gatts_register_services(SERVICES)
4.3. 标准蓝牙UUID
对于一些常用的功能,蓝牙组织联盟已经定义号了UUID,我们在开发的时候,直接使用即可。大家都遵循蓝牙协议,这样其他人去解析数据也比较容易
4.3.1. 电池电量
例如电池电量服务的UUID是0x180F, 电池电量的特性UUID是0x2A19. 这样我们就可以直接使用这两个UUID来实现电量指示的功能。
from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE
#创建电池服务和特性的UUID
BATTERY_SERVER_UUID = ubluetooth.UUID(0x180F)
BATTERY_CHAR_UUID = ubluetooth.UUID(0x2A19)
#创建特性并设置特性的读写权限
BATTERY_CHAR = (BATTERY_CHAR_UUID, ubluetooth.FLAG_READ , )
BATTERY_SERVER = (BATTERY_SERVER_UUID, (BATTERY_CHAR, ) , ) #把电量特性放入电池服务
SERVICES = (BATTERY_SERVER, ) #把电池服务服务放入服务集和中
((battery_char,), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
ble.gatts_write(battery_char, b'\x50') #设置电池电量为80%
#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')
def ble_irq(event, data): # 蓝牙中断函数
if event == 1: #蓝牙已连接
print("BLE 连接成功")
elif event == 2: #蓝牙断开连接
print("BLE 断开连接")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')
elif event == 3: #收到数据
print("收到新消息")
ble.irq(ble_irq)
4.3.2. 温湿度传感器
在蓝牙组织联盟发布的16Bit UUID 中,定义了环境传感器服务的UUID是0x181A ,温度特性的UUID是0x2A6E,湿度特性的UUID是0x2A6F。使用如下代码可实现简单温湿度传感器功能:
from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE
#创建环境传感器服务和特性的UUID
ENV_SERVER_UUID = ubluetooth.UUID(0x181A) #环境传感器服务
TEM_CHAR_UUID = ubluetooth.UUID(0x2A6E) #温度特性
HUM_CHAR_UUID = ubluetooth.UUID(0x2A6F) #湿度特性
#创建特性并设置特性的读写权限
TEM_CHAR = (TEM_CHAR_UUID, ubluetooth.FLAG_READ , )
HUM_CHAR = (HUM_CHAR_UUID, ubluetooth.FLAG_READ , )
ENV_SERVER = (ENV_SERVER_UUID, (TEM_CHAR, HUM_CHAR, ) , ) #把温湿度特性放入环境服务
SERVICES = (ENV_SERVER, ) #把环境服务放入服务集和中
((tem_char, hum_char, ), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
ble.gatts_write(tem_char, b'\x06\x08') #设置温度为20.54度(0x0806 = 2054)
ble.gatts_write(hum_char, b'\x09\x07') #设置湿度为18.01%(0x0709 = 1801)
#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')
def ble_irq(event, data): # 蓝牙中断函数
if event == 1: #蓝牙已连接
print("BLE 连接成功")
elif event == 2: #蓝牙断开连接
print("BLE 断开连接")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')
elif event == 3: #收到数据
print("收到新消息")
ble.irq(ble_irq)
结语
通过本文的系统学习,我们不仅掌握了BLE技术的核心概念和工作原理,还实践了从广播数据构建到服务特性注册的完整开发流程。BLE技术以其独特的低功耗优势,正在智能穿戴、医疗设备、家居自动化等领域发挥着越来越重要的作用。希望本文能成为您BLE开发路上的实用指南,期待看到您利用这些知识创造出更多创新的物联网应用。技术的魅力在于分享与实践,愿您在BLE的世界里探索出更多可能!