1. BLE协议栈深度解析:GAP与GATT的协同工作机制
1.1 GAP层:蓝牙设备的"社交礼仪"
在低功耗蓝牙(BLE)的世界里,GAP(Generic Access Profile)相当于设备间的社交礼仪规范。它定义了设备如何广播自己的存在、如何被发现以及如何建立连接。就像参加社交活动时,你需要先自我介绍(广播),然后才能与他人建立联系。
GAP层主要处理四种角色:
- 广播者(Broadcaster):只发送广播数据,不建立连接(如iBeacon)
- 观察者(Observer):只扫描广播,不发起连接(如室内定位接收器)
- 外围设备(Peripheral):可广播且可被连接(多数IoT设备)
- 中央设备(Central):扫描并发起连接(如手机)
实际开发中,ESP32通常作为外围设备,通过以下典型代码启动广播:
cpp复制BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
pServer->getAdvertising()->start();
1.2 GATT层:结构化数据交换的基石
当设备通过GAP建立连接后,GATT(Generic Attribute Profile)就开始接管数据传输工作。GATT采用树状数据结构组织数据,包含三个核心概念:
-
服务(Service):完成特定功能的逻辑集合
- 例如心率服务(0x180D)、电池服务(0x180F)
-
特征(Characteristic):服务中的具体数据点
- 包含一个值(value)和若干描述符(descriptor)
- 例如心率测量特征(0x2A37)
-
描述符(Descriptor):描述特征的元数据
- 例如客户端特征配置描述符(0x2902)用于启用/禁用通知
GATT事务遵循严格的客户端-服务器模型:
- 服务器(Server)存储数据(如ESP32)
- 客户端(Client)读写数据(如手机APP)
1.3 GAP与GATT的协同工作流程
典型BLE交互分为两个阶段:
-
连接建立阶段(GAP):
- 外设广播广告包(Advertising Data)
- 中央设备扫描并发送连接请求
- 协商连接参数(间隔、延迟等)
-
数据交互阶段(GATT):
- 客户端发现服务/特征
- 根据特征属性进行读写操作
- 可能启用通知/指示功能
关键区别:GAP处理"物理层"连接,GATT管理"逻辑层"数据交换。就像打电话时,GAP负责拨号建立连接,GATT则规范通话内容的结构。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. GATT服务与特征的实战配置
2.1 服务与特征的创建流程
创建完整的GATT服务需要遵循以下步骤:
cpp复制// 1. 创建服务
BLEService *pService = server->createService(SERVICE_UUID);
// 2. 创建特征
BLECharacteristic *pChar = pService->createCharacteristic(
CHAR_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
// 3. 设置特征值
pChar->setValue("Initial Value");
// 4. 添加描述符(如需要)
pChar->addDescriptor(new BLE2902());
// 5. 启动服务
pService->start();
// 6. 开始广播
server->getAdvertising()->start();
2.2 特征属性详解与选择策略
特征属性(properties)决定了客户端如
