esp-iot-solution 蓝牙心率服务(BLE HRP)GATT 客户端示例详解:从连接管理到特征读写
发布时间:2026/9/19 19:28:01 锦皓数字建站
GATT 客户端示例详解:从连接管理到特征读写`)
物联网嵌入式驱动开发硬件开发【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址https://gitcode.com/GitHub_Trending/es/esp-iot-solution点击查看免费下载本文以 esp-iot-solution 仓库中的 BLE Heart Rate ProfileHRP示例为对象完整讲解该示例如何基于 BLE 连接管理ble_conn_mgr构建一个 GATT 客户端它通过被动扫描发现广播心率服务Heart Rate ServiceUUID 0x180D的外设并自动连接同时借助串口交互式控制台模拟对心率特征0x2A37/0x2A38/0x2A39的读取与写入操作。读完本文你将掌握心率服务的特征与数据格式解析、hrp 控制台命令的用法、ble_conn_mgr 的事件驱动 API 调用链以及该示例在 ESP32/ESP32-C3/ESP32-C2/ESP32-S3 上的编译、配置与联调方法。示例定位与工作原理示例位于 examples/bluetooth/ble_profiles/ble_hrp支持的芯片目标为 ESP32、ESP32-C3、ESP32-C2、ESP32-S3。其核心工作流程如下示例创建一个GATT 客户端执行被动扫描passive scan当扫描到某个外设广播可连接connectable且其广播数据中将心率服务0x180D声明为主服务 UUID时客户端自动发起连接连接建立后由ble_conn_mgrBLE 连接管理器驱动完成服务/特征/描述符发现并持续接收外设推送的心率测量通知Heart Rate Measurement notification与此同时示例在串口上创建交互式控制台基于 esp_console linenoise通过hrp命令模拟 HRP 行为——读取 Body Sensor Location 特征、向 Heart Rate Control Point 特征写入命令字。示例还内置了严格的健壮性处理如果对端设备在广播中声称支持心率服务但其 GATT 数据库中实际上缺少所需的服务、特征或描述符即说谎了那么一旦某个 GATT 过程失败程序会立即终止该连接避免进入不确定状态。用官方描述来说该示例的目的是帮助开发者理解心率服务HRP的特征操作以及BLE 连接管理 API的使用方式。要测试这个 Demo可以使用任何支持广播心率服务0x180D并将其包含在 GATT 数据库中的 BLE GATT 服务器 App如手机上的 BLE 调试工具作为对端设备。心率服务核心概念服务、特征与 UUID心率服务是蓝牙 SIG 定义的 GATT 标准服务其 UUID 与特征定义在 components/bluetooth/ble_profiles/std/ble_hrp/include/esp_hrp.h 中可直接复用名称UUID类型说明Heart Rate Service0x180D服务心率服务的服务 UUIDHeart Rate Measurement0x2A37特征Notify心率测量值外设主动通知Body Sensor Location0x2A38特征Read传感器佩戴位置Heart Rate Control Point0x2A39特征Write心率控制点用于写入命令对应的宏定义如下#define BLE_HRP_UUID16 0x180D #define BLE_HRP_CHR_UUID16_MEASUREMENT 0x2A37 #define BLE_HRP_CHR_UUID16_BODY_SENSOR_LOC 0x2A38 #define BLE_HRP_CHR_UUID16_HEART_RATE_CNTL_POINT 0x2A39Heart Rate Measurement 数据格式心率测量特征0x2A37的载荷由一个Flags 字段和若干可选字段组成。esp-iot-solution 用位域结构体esp_ble_hrp_data_t描述见 esp_hrp.htypedef struct { struct { uint8_t format: 1; /*! 心率值格式标志0UINT81UINT16 */ uint8_t detected: 1; /*! 皮肤接触检测标志 */ uint8_t supported: 1; /*! 皮肤接触检测功能支持标志 */ uint8_t energy: 1; /*! 能量消耗字段存在标志 */ uint8_t interval: 1; /*! RR 间期字段存在标志 */ uint8_t reserved: 3; /*! 保留位 */ } flags; union { uint8_t u8; /*! 8 位分辨率心率值 */ uint16_t u16; /*! 16 位分辨率心率值 */ } heartrate; uint16_t energy_val; /*! 累计消耗能量值 */ uint16_t interval_buf[BLE_HRP_CHR_MERSUREMENT_RR_INTERVAL_MAX_NUM]; /*! RR 间期数组最多 7 个 */ } esp_ble_hrp_data_t;Flags 字段各位的比特掩码同样在头文件中给出便于按位判断掩码名称含义0x00BLE_HRP_FLAGS_BM_NONE无标志0x01BLE_HRP_FLAGS_BM_FORMAT心率值格式0UINT81UINT160x02BLE_HRP_FLAGS_BM_SENSOR_CONTACT_DETECTED是否检测到皮肤接触0x04BLE_HRP_FLAGS_BM_SENSOR_CONTACT_SUPPOTRED是否支持皮肤接触检测功能0x08BLE_HRP_FLAGS_BM_ENERGY载荷中是否含能量消耗字段0x10BLE_HRP_FLAGS_BM_RR_INTERVAL载荷中是否含 RR 间期字段0x70BLE_HRP_FLAGS_BM_RFU保留给未来使用载荷解析的源码实现数据解析在 components/bluetooth/ble_profiles/std/ble_hrp/src/esp_hrp.c 的esp_ble_hrp_get_data()中完成严格按规范顺序解析先拷贝Flags 字段根据flags.format决定心率值占用 1 字节u8还是 2 字节u16小端若flags.supported与flags.detected组合异常未声明支持却检测到接触打印告警日志若flags.energy置位解析 2 字节的能量消耗值若flags.interval置位解析 RR 间期数组。应用层通过事件拿到解析后的结构体在 app_hrp.c 的事件处理函数中打印心率值、皮肤接触状态、能量消耗与 RR 间期原始数据。工程结构与启动流程示例目录结构如下examples/bluetooth/ble_profiles/ble_hrp/ ├── main/ │ ├── CMakeLists.txt │ ├── Kconfig.projbuild # 示例配置菜单广播名、广播数据 │ ├── app_main.c # 应用入口初始化并启动连接管理 │ ├── app_console.c # 串口交互式控制台esp_console linenoise │ ├── app_hrp.c # hrp 命令注册与 HRP 事件处理 │ ├── app_hrp.h │ └── idf_component.yml ├── CMakeLists.txt ├── README.md ├── sdkconfig.ci.nimble # CI 环境强制 NimBLE └── sdkconfig.defaults # 默认启用 BT/NimBLE/连接管理/HRPapp_main()app_main.c的启动顺序非常清晰是典型的 ble_conn_mgr 使用范式初始化NVS若 NVS 分区损坏或版本不匹配则擦除后重试创建默认esp_event 事件循环并注册连接管理器事件监听调用app_console_init()创建控制台任务调用register_hrp()注册hrp命令并初始化 HRP 组件构造esp_ble_conn_config_t配置设备名取CONFIG_EXAMPLE_BLE_ADV_NAME广播数据取CONFIG_EXAMPLE_BLE_SUB_ADV调用esp_ble_conn_init(config)与esp_ble_conn_start()启动连接管理若启动失败则依次执行esp_ble_conn_stop()、esp_ble_conn_deinit()并注销事件监听做资源清理。连接管理器的核心事件BLE_CONN_MGR_EVENTS包括ESP_BLE_CONN_EVENT_CONNECTED已连接、ESP_BLE_CONN_EVENT_DISCONNECTED已断开、ESP_BLE_CONN_EVENT_DISC_COMPLETE服务发现完成、ESP_BLE_CONN_EVENT_DATA_RECEIVE收到通知数据示例均在app_main.c中打印对应日志。esp_ble_hrp_init()的实现本质上是把 HRP 组件的内部事件处理函数挂到BLE_CONN_MGR_EVENTS上见 esp_hrp.c当收到ESP_BLE_CONN_EVENT_DATA_RECEIVE时解析数据并通过esp_event_post()转发为BLE_HRP_EVENTS事件应用层再在app_hrp.c中监听BLE_HRP_CHR_UUID16_MEASUREMENT事件打印结果——形成连接管理器 → HRP 组件 → 应用层的完整事件链。编译、配置与烧录设置目标芯片编译前必须先设置芯片目标idf.py set-target chip_name其中chip_name支持 ESP32、ESP32-C3、ESP32-C2、ESP32-S3。硬件要求一块搭载 ESP32 或 ESP32-C3 系列 SoC 的开发板如 ESP32-DevKitC、ESP-WROVER-KIT 等一根用于供电和程序烧录的 USB 线。菜单配置打开项目配置菜单idf.py menuconfig在Example Configuration菜单下可以修改Advertisement nameEXAMPLE_BLE_ADV_NAME设备广播名来源见 Kconfig.projbuild实际默认值为BLE_HRS注意README 正文写的是BLE_HTS应为从体温服务示例复制时遗留的笔误以 Kconfig 源码为准Subsequent advertisement dataEXAMPLE_BLE_SUB_ADV后续广播携带的数据默认值为字符串SUB_ADV。关键 sdkconfig 默认项sdkconfig.defaults中预置了本示例运行所需的开关构建时无需手动逐个打开CONFIG_BT_ENABLEDy # 启用蓝牙控制器与主机 CONFIG_BT_NIMBLE_ENABLEDy # 使用 NimBLE 蓝牙协议栈 CONFIG_BLE_CONN_MGR_ROLE_CENTRALy # 连接管理器角色为中央设备客户端 CONFIG_BLE_HEART_RATE_PROFILESy # 使能 HRP 配置文件组件其中CONFIG_BLE_CONN_MGR_ROLE_CENTRAL对应 ble_conn_mgr 组件components/bluetooth/ble_conn_mgr的中央角色编译开关本示例作为 GATT 客户端必须开启。CI 环境则通过 sdkconfig.ci.nimble 额外强制CONFIG_BT_NIMBLE_ENABLEDy。编译、烧录与监控idf.py -p PORT flash monitor该命令会完成编译、烧录并打开串口监视器按Ctrl-]退出监视器。hrp 交互命令详解示例启动后会进入交互式控制台提示符形如esp32c3输入help可查看全部命令hrp命令的帮助如下hrp [-t 01~02] [-c 0~255] Heart Rate Profile -t, --type01~02 01 Gets Body Sensor Location Characteristic 02 Set Heart Rate Control Point Characteristic -c, --cmd0~255 1: Reset Energy Expended, Other: Reserved for Future Use命令参数说明参数是否必选取值范围含义-t/--type必选01~0201读取 Body Sensor Location02写入 Heart Rate Control Point-c/--cmd可选0~255控制点命令字1重置累计能量消耗Reset Energy Expended其余保留命令在 app_hrp.c 中通过 argtable3 注册-t为必填arg_int0中type-count为 0 时直接返回 1未给-c时cmd_id取 0。读取 Body Sensor Locationhrp -t 1该命令会触发一次 GATT 读操作读取特征 0x2A38。控制台将打印I (16587) esp_nimble: characteristic read; conn_handle1 attr_handle16 len1 value I (16587) app_hrp: Gets the Value of Body Sensor Location 4适用条件该命令在连接中 Body Sensor Location 特征保持静态时有效。从源码看esp_hrp.c 的esp_ble_hrp_get_location()当最近一次心率测量数据不满足支持皮肤接触检测且未检测到接触的前提时函数会直接返回ESP_ERR_INVALID_ARG对应日志 Invalid option。重置累计能量消耗hrp -t 2 -c 1 # 向 0x2A39 写入命令字 1Reset Energy Expended hrp -t 2 -c 10 # 命令字 10 属于保留值会被拒绝适用条件该命令仅在对端服务端支持 Energy Expended 特征时有效。源码中esp_ble_hrp_set_ctrl()做了双重校验命令字必须等于BLE_HRP_CMD_RESET_ENERGY_EXPENDED即 1且最近一次收到的心率测量数据中 energy 标志必须置位否则返回ESP_ERR_INVALID_ARG——这正是示例输出中第二次hrp -t 2 -c 1与hrp -t 2 -c 10都报 Invalid option错误码 0x102的原因前者因最新一帧通知未携带能量字段后者因命令字非法。底层 API 与连接管理调用链HRP 组件对外提供 4 个标准 API定义于 esp_hrp.hAPI功能esp_ble_hrp_init()/esp_ble_hrp_deinit()初始化/反初始化 HRP 组件注册/注销连接管理器事件esp_ble_hrp_get_location(uint8_t *location)读取 Body Sensor Location 特征值esp_ble_hrp_set_ctrl(uint8_t cmd_id)向 Heart Rate Control Point 写入命令字esp_ble_hrp_get_ctrl(uint8_t *cmd_id)读取控制点值预留其中读取与写入最终都调用连接管理器提供的统一读写接口读构造esp_ble_conn_data_ttypeBLE_CONN_UUID_TYPE_16、uuid.uuid160x2A38后调用esp_ble_conn_read()写构造同样的数据结构并携带 1 字节命令字调用esp_ble_conn_write()。也就是说应用层无需关心 NimBLE 的 GATT 句柄与过程细节只需按UUID 指定特征 数据缓冲的方式描述请求连接管理器负责扫描、连接、服务发现以及按 UUID 定位特征句柄并完成读写——这正是该示例强调理解 BLE 连接管理 API的意义所在。控制台输出的start_handle/end_handle分段发现日志如discover all characteristics; start_handle1 end_handle5即由连接管理器内部驱动 NimBLE 完成。运行输出解读连接成功时的典型串口输出节选自 README.md大致分为以下几个阶段协议栈启动BTDM_INIT、phy_init打印蓝牙控制器与射频初始化信息随后esp_nimble: BLE Host Task Started被动扫描GAP procedure initiated: discovery; passive1 filter_duplicates1 durationforever持续监听广播自动连接发现广播 0x180D 的可连接外设后GAP procedure initiated: connect随后打印扫描/连接参数scan_itvl、itvl_min/max、supervision_timeout等服务发现discover all services→ 多段discover all characteristics→ 多段discover all descriptors最终Service discovery complete; rc0, conn_handle1并触发ESP_BLE_CONN_EVENT_CONNECTED与ESP_BLE_CONN_EVENT_DISC_COMPLETE事件接收通知外设持续推送心率测量数据app_hrp依次打印W (4347) esp_hrp: Sensor Contact Feature is Supported W (4357) esp_hrp: Skin Contact is Detected I (4357) app_hrp: Heart Rate Value 12098 W (4357) app_hrp: The Energy Expended feature is supported and accumulated 27125kJ I (4377) app_hrp: The multiple time between two R-Wave detections I (4377) app_hrp: ec 75 00 00 00 00 00 00 00 00 00 00 00 00这些日志分别对应心率值Heart Rate Value、皮肤接触状态Sensor Contact Feature is Supported/Skin Contact is/ isnt Detected、能量消耗accumulated 27125kJ当 energy 标志置位时以及 RR 间期原始字节hex dump当 interval 标志置位时。常见问题与调试建议对端设备要求务必使用真实包含 0x180D 服务 GATT 数据库的设备或 App若对端仅在广播中声明支持心率服务但数据库中缺失特征/描述符示例会因 GATT 过程失败而立即断开连接命令被拒Invalid option / 0x102hrp -t 2 -c 1与hrp -t 2 -c 10被拒是正常的边界行为分别源于最新一帧未携带 energy 字段与命令字为保留值可更换支持 Energy Expended 的对端再试广播名默认值以 Kconfig.projbuild 中BLE_HRS为准README 正文的BLE_HTS属笔误如需自定义在idf.py menuconfig中修改即可观察链路细节连接后留意start_handle/end_handle分段日志可帮助理解 GATT 句柄布局与发现流程esp_ble_conn_read/write的底层实现可在 components/bluetooth/ble_conn_mgr 组件源码中继续深入。总结本示例以心率服务为最小可运行的业务载体完整演示了 esp-iot-solution 蓝牙体系下连接管理器ble_conn_mgr 标准 Profile 组件ble_hrp 交互式控制台的三层协作模式应用层通过esp_ble_conn_init/start启动连接通过 UUID 描述特征请求完成读写通过事件循环消费解析后的 HRP 数据。掌握该示例后你可以很容易地将其推广到其他标准 BLE 服务如温度、电池、血压等 Profile 组件见 components/bluetooth/ble_profiles/std 目录快速搭建自己的 BLE 客户端应用。赞分享物联网嵌入式驱动开发硬件开发【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址https://gitcode.com/GitHub_Trending/es/esp-iot-solution点击查看免费下载相关推荐esp-iot-solution 蓝牙体成分服务BLE BCS开发指南从 GATT 特性设计到示例集成esp iot solution 蓝牙体成分服务BLE BCS开发指南从 GATT 特性设计到示例集成 导读 本文基于 Espressif esp iot物联网嵌入式驱动开发硬件开发ESP IoT Solution BLE Heart Rate ProfileHRPGATT 客户端组件实战指南ESP IoT Solution BLE Heart Rate ProfileHRPGATT 客户端组件实战指南 导读 本文基于 esp iot solut物联网嵌入式驱动开发硬件开发ESP IoT Solution 实战基于 esp-iot-solution 的 BLE 健康温度计服务HTSGATT 服务端示例详解ESP IoT Solution 实战基于 esp iot solution 的 BLE 健康温度计服务HTSGATT 服务端示例详解 导读 本指南围绕物联网嵌入式驱动开发硬件开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。