什么是BLE?深入了解蓝牙低功耗技术

在当今物联网(IoT)时代,各种智能设备需要高效、低功耗的无线通信技术来保持连接。蓝牙低功耗(Bluetooth Low Energy,简称BLE)正是在这种需求下应运而生的技术,它彻底改变了我们对短距离无线通信的认知。

什么是BLE?

BLE,全称为Bluetooth Low Energy(蓝牙低功耗),也被称为Bluetooth Smart,是蓝牙4.0规范的一部分,于2010年正式发布。与传统蓝牙相比,BLE专门为需要长电池寿命、低成本、低复杂度的设备而设计。

BLE的核心特点

  1. 超低功耗:BLE设备可以使用一节纽扣电池运行数月甚至数年
  2. 快速连接:连接建立时间通常在几毫秒内
  3. 低成本:芯片成本相对较低,适合大规模部署
  4. 简化的设备发现:支持广播模式,无需配对即可传输数据
  5. 良好的互操作性:与现代智能手机、平板电脑等设备兼容性好

BLE vs 经典蓝牙

特性 BLE 经典蓝牙
功耗 极低 相对较高
数据传输速率 1-3 Mbps 1-24 Mbps
连接建立时间 3ms 100ms
工作范围 10-100米 10-100米
应用场景 传感器、健康监测、信标 音频、文件传输
电池寿命 数月到数年 数小时到数天

BLE的工作原理

BLE采用分层的协议栈架构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+------------------+
| 应用层 |
+------------------+
| 主机层 |
| - GAP |
| - GATT |
| - ATT |
| - SMP |
| - L2CAP |
+------------------+
| 控制器层 |
| - 链路层 |
| - 物理层 |
+------------------+

关键概念

GAP (Generic Access Profile)

  • 定义设备如何被发现和连接
  • 管理广播和扫描过程
  • 定义设备角色(中心设备、外围设备)

GATT (Generic Attribute Profile)

  • 定义数据的组织和交换方式
  • 基于服务(Service)和特征(Characteristic)的模型
  • 支持读取、写入、通知等操作

服务(Services)

  • 一组相关功能的集合
  • 每个服务有唯一的UUID标识
  • 包含一个或多个特征

特征(Characteristics)

  • 实际的数据值容器
  • 定义了数据的属性(可读、可写、可通知等)
  • 包含值、描述符等

ATT (Attribute Protocol)

  • 属性协议:定义了客户端和服务器间的通信规则
  • 属性模型:将数据组织成属性(包含句柄、类型、值)
  • 请求-响应机制:支持读取、写入、通知等操作
  • 错误处理:定义了标准的错误码和处理机制
  • MTU协商:协商最大传输单元大小
  • 是GATT的基础:GATT在ATT之上提供更高级的服务抽象

SMP (Security Manager Protocol)

  • 安全管理协议:负责BLE设备间的安全功能
  • 密钥生成和分发:创建和交换加密密钥
  • 设备配对:管理设备间的安全配对过程
  • 身份验证:验证通信设备的合法性
  • 数据加密:对传输的数据进行加密保护
  • 隐私保护:支持设备地址随机化等隐私功能
  • 逻辑链路控制和适配协议:位于蓝牙协议栈的中间层
  • 数据包分片和重组:处理大数据包的分割和组装
  • 流量控制:管理数据传输速率,防止缓冲区溢出
  • 错误检测和重传:确保数据传输的可靠性
  • 多路复用:允许多个应用同时使用蓝牙连接

通信模式

广播模式

1
外围设备 ----广播数据----> 中心设备(被动接收)

连接模式

1
2
外围设备 <----建立连接----> 中心设备
<----数据交换---->

BLE的应用场景

健康与健身

  • 智能手环/手表:心率监测、步数统计、睡眠分析
  • 体重秤:体重、体脂率数据传输
  • 血糖仪:血糖数据实时上传
  • 体温计:体温监测和记录

智能家居

  • 温湿度传感器:环境监测
  • 智能门锁:安全控制
  • 智能灯泡:亮度和颜色控制
  • 智能插座:远程电器控制

资产追踪

  • Beacon标签:室内定位和导航
  • 钥匙追踪器:防丢失设备
  • 宠物定位器:宠物位置追踪

工业物联网

  • 设备状态监控:机器运行状态
  • 环境监测:工厂环境参数
  • 库存管理:货物追踪

BLE的技术优势

能耗管理

BLE通过以下机制实现超低功耗:

  • 间歇性工作:设备大部分时间处于休眠状态
  • 快速连接:减少活跃时间
  • 自适应频率调整:根据需要调整通信频率
  • 智能功率控制:动态调整发射功率

安全性

  • AES-128加密:数据传输加密
  • 认证和授权:设备身份验证
  • 密钥管理:安全的密钥交换机制
  • 隐私保护:MAC地址随机化

扩展性

  • 多设备连接:一个中心设备可连接多个外围设备
  • 网状网络:Bluetooth Mesh支持
  • 互操作性:标准化的协议栈

BLE开发实践

开发环境搭建

ESP32 BLE服务器端开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEUtils.h"
#include "BLE2902.h"

// 定义服务和特征的UUID
#define SERVICE_UUID "12345678-1234-1234-1234-123456789abc"
#define CHARACTERISTIC_UUID "87654321-4321-4321-4321-cba987654321"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;

class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println("设备已连接");
};

void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("设备已断开连接");
BLEDevice::startAdvertising(); // 重新开始广播
}
};

class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();

if (rxValue.length() > 0) {
Serial.println("接收到数据:");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
}
}
};

void setup() {
Serial.begin(115200);
Serial.println("ESP32 BLE服务器启动中...");

// 初始化BLE设备
BLEDevice::init("ESP32-BLE-Server");

// 创建BLE服务器
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// 创建BLE服务
BLEService *pService = pServer->createService(SERVICE_UUID);

// 创建BLE特征
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);

// 设置特征回调
pCharacteristic->setCallbacks(new MyCallbacks());

// 添加描述符(用于通知功能)
pCharacteristic->addDescriptor(new BLE2902());

// 启动服务
pService->start();

// 开始广播
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0);
BLEDevice::startAdvertising();

Serial.println("BLE服务器已启动,等待客户端连接...");
}

void loop() {
// 如果设备已连接,每秒发送一次数据
if (deviceConnected) {
String data = "Hello from ESP32! Time: " + String(millis());
pCharacteristic->setValue(data.c_str());
pCharacteristic->notify();
Serial.println("发送数据: " + data);
delay(1000);
}

// 处理断开连接的情况
if (!deviceConnected && deviceConnected) {
delay(500);
pServer->startAdvertising();
Serial.println("重新开始广播");
}
}

ESP32 BLE客户端开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "BLEDevice.h"
#include "BLEClient.h"

// 目标服务器的服务和特征UUID
static BLEUUID serviceUUID("12345678-1234-1234-1234-123456789abc");
static BLEUUID charUUID("87654321-4321-4321-4321-cba987654321");

static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;

// 通知回调函数
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("接收到通知数据: ");
for(int i = 0; i < length; i++) {
Serial.print((char)pData[i]);
}
Serial.println();
}

class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
Serial.println("客户端已连接");
}

void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("客户端已断开连接");
}
};

bool connectToServer() {
Serial.print("正在连接到设备: ");
Serial.println(myDevice->getAddress().toString().c_str());

BLEClient* pClient = BLEDevice::createClient();
Serial.println("创建客户端成功");

pClient->setClientCallbacks(new MyClientCallback());

// 连接到远程BLE服务器
pClient->connect(myDevice);
Serial.println("连接到服务器成功");

// 获取远程服务的引用
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("获取服务失败,UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println("找到目标服务");

// 获取远程特征的引用
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("获取特征失败,UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println("找到目标特征");

// 读取特征值
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
Serial.print("特征值: ");
Serial.println(value.c_str());
}

// 注册通知回调
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);

connected = true;
return true;
}

// 扫描回调类
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("发现BLE设备: ");
Serial.println(advertisedDevice.toString().c_str());

// 检查是否是我们要找的设备
if (advertisedDevice.haveServiceUUID() &&
advertisedDevice.isAdvertisingService(serviceUUID)) {

BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
Serial.println("找到目标设备!");
}
}
};

void setup() {
Serial.begin(115200);
Serial.println("ESP32 BLE客户端启动中...");

BLEDevice::init("");

// 创建扫描器
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
}

void loop() {
// 如果找到设备且需要连接
if (doConnect == true) {
if (connectToServer()) {
Serial.println("连接成功!");
} else {
Serial.println("连接失败");
}
doConnect = false;
}

// 如果已连接,可以发送数据
if (connected) {
// 每5秒向服务器发送一次数据
String newValue = "Client message: " + String(millis());
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
delay(5000);
} else if (!connected) {
// 重新开始扫描
BLEDevice::getScan()->start(0);
delay(1000);
}
}

特斯拉 Ble 实践

  1. 调节连接参数可以降低延迟
  2. 调大功率貌似也能有一些优化
  3. 耗时大概在 260ms~400ms.不确定特斯拉接收端是否有固定的延迟

设备端开发考虑

硬件选择

  • ESP32

BLE的发展趋势

Bluetooth 5.0及以后版本的改进

  • 更长的传输距离:4倍传输距离提升
  • 更快的速度:2倍速度提升
  • 更大的广播容量:8倍广播消息容量
  • 更好的互操作性:改进的互操作性和共存性

Mesh网络支持

  • Bluetooth Mesh:支持多对多设备通信
  • 大规模网络:支持数千个设备的网络
  • 自愈能力:网络拓扑自动恢复

新兴应用领域

  • 音频应用:LE Audio,低功耗音频传输
  • 定位服务:精确室内定位
  • 医疗设备:更多医疗级应用

结语

BLE作为现代物联网的重要基础技术,以其低功耗、低成本、易部署的特点,正在推动着各种创新应用的发展。从智能穿戴设备到工业物联网,从智能家居到医疗健康,BLE的应用场景越来越广泛。