ESP32 BLE实战:5分钟搞定自定义GATT服务端(附完整代码解析)
ESP32 BLE实战:5分钟搞定自定义GATT服务端(附完整代码解析)
在智能手环、医疗设备等物联网应用中,BLE(低功耗蓝牙)技术因其低功耗特性成为首选通信方案。本文将带你快速实现一个带心率监测功能的BLE服务端,解决开发者最头疼的通知延迟和数据分包问题。
1. 环境准备与基础配置
先确保已安装ESP-IDF开发环境(建议v4.4以上版本)。创建工程后,在menuconfig中启用蓝牙支持:
idf.py menuconfig # 选择 Component config → Bluetooth → Bluetooth → Bluedroid Enable关键初始化代码段(200字精简版):
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_init(&bt_cfg); esp_bt_controller_enable(ESP_BT_MODE_BLE); esp_bluedroid_init(); esp_bluedroid_enable();提示:初始化顺序不可颠倒,否则会出现"invalid state"错误
2. 服务架构设计
健康监测服务采用标准心率Profile(0x180D),包含三个核心组件:
| 组件类型 | UUID | 权限 | 功能描述 |
|---|---|---|---|
| 主服务 | 0x180D | - | 心率监测服务容器 |
| 特征值 | 0x2A37 | 读/通知 | 存储心率测量值 |
| 描述符(CCCD) | 0x2902 | 写 | 启用/禁用通知功能 |
特征值属性配置示例:
esp_attr_value_t heart_rate_val = { .attr_max_len = 2, .attr_len = 2, .attr_value = {0x00, 0x00} // 初始心率值 };3. 服务端实现关键步骤
3.1 注册GATT回调
事件处理是BLE通信的核心,主要处理以下事件:
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { switch(event) { case ESP_GATTS_REG_EVT: // 服务注册成功 break; case ESP_GATTS_CREATE_EVT: // 服务创建成功 break; case ESP_GATTS_WRITE_EVT: // 处理客户端写入 handle_write_event(param); break; } }3.2 实现心率通知功能
当客户端启用CCCD描述符的通知位时,服务端应定期发送心率数据:
void send_heart_rate_notification(uint16_t conn_id, uint16_t char_handle) { uint8_t hr_data[2] = {0x06, random() % 100 + 60}; // 模拟60-160bpm esp_ble_gatts_send_indicate(gatts_if, conn_id, char_handle, sizeof(hr_data), hr_data, false); }注意:indicate(需确认)和notify(无需确认)的区别在于数据可靠性
4. 性能优化技巧
4.1 MTU大小协商
默认23字节MTU会导致大数据分包,建议在连接后协商更大MTU:
case ESP_GATTS_MTU_EVT: ESP_LOGI(TAG, "MTU size: %d", param->mtu.mtu); break; // 连接后主动协商 esp_ble_gatt_set_local_mtu(247); // 最大支持247字节4.2 连接参数优化
合理的连接间隔可平衡功耗和实时性:
esp_ble_conn_update_params_t conn_params = { .min_int = 16, // 20ms (单位1.25ms) .max_int = 32, // 40ms .latency = 0, .timeout = 400 // 4s超时 }; esp_ble_gap_update_conn_params(&conn_params);5. 完整代码解析
核心服务创建流程:
注册应用:
esp_ble_gatts_app_register(HEART_RATE_APP_ID);创建服务:
esp_ble_gatts_create_service(gatts_if, &heart_rate_service_id, HANDLE_NUM);添加特征值:
esp_ble_gatts_add_char(service_handle, &char_uuid, ESP_GATT_PERM_READ, ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY, &heart_rate_val, NULL);启动服务:
esp_ble_gatts_start_service(service_handle);
实测发现,在ESP32-C3上启用1500ms通知间隔时,平均电流仅12μA,非常适合电池供电设备。
