news 2026/9/19 3:29:10

ESP IoT Solution 蓝牙健康温度计 Profile(HTP)组件与示例深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP IoT Solution 蓝牙健康温度计 Profile(HTP)组件与示例深度解析

ESP IoT Solution 蓝牙健康温度计 Profile(HTP)组件与示例深度解析

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

本指南围绕 ESP IoT Solution 仓库中的ble_htp组件展开,讲解如何在 GATT Client 端通过该组件从符合蓝牙健康温度计服务(Health Thermometer Service,UUID 0x1809)的体温计设备获取温度数据。读完本文,你将掌握 HTP 服务的特征值构成、esp_htp组件的 API 与事件机制、底层 BLE 连接管理调用链,以及基于控制台命令的完整示例实操流程。

一、HTP 是什么:健康温度计服务的标准特征

Health Thermometer Profile(HTP,健康温度计配置文件)是蓝牙 SIG 定义的标准 BLE Profile,用于让数据收集设备(GATT Client)从体温计传感器(GATT Server)读取体温测量值。ESP IoT Solution 的ble_htp组件提供了一套简化 API,封装了 HTP 在 GATT Client 端的常用操作(见 组件 README)。

在 esp_htp.h 中定义了该服务及其特征值的 16 位 UUID:

名称UUID 宏数值用途
Health Thermometer ServiceBLE_HTP_UUID160x1809健康温度计服务
Temperature MeasurementBLE_HTP_CHR_UUID16_TEMPERATURE_MEASUREMENT0x2A1C最终体温测量值(Indication)
Temperature TypeBLE_HTP_CHR_UUID16_TEMPERATURE_TYPE0x2A1D测量部位类型(可读)
Intermediate TemperatureBLE_HTP_CHR_UUID16_INTERMEDIATE_TEMPERATURE0x2A1E测量过程中的中间温度(Notification)
Measurement IntervalBLE_HTP_CHR_UUID16_MEASUREMENT_INTERVAL0x2A21周期测量间隔(可读/可写)

其中0x2A1C0x2A1E共享同一套数据格式(温度测量值),均由esp_ble_htp_data_t结构体描述。

二、组件结构与依赖关系

2.1 仓库中的位置

ble_htp位于 BLE 标准 Profile 组件目录下:

  • 组件入口:components/bluetooth/ble_profiles/std/ble_htp(含include/esp_htp.hsrc/esp_htp.cCMakeLists.txtKconfigidf_component.yml
  • 配套示例:examples/bluetooth/ble_profiles/ble_htp

按 idf_component.yml 的描述,该组件即 "BLE standard profile support Health Thermometer"。

2.2 添加组件依赖

与仓库内其他 Profile 组件一致,可以通过 ESP-IDF 组件管理器添加依赖(编译时自动下载):

idf.py add-dependency "espressif/ble_htp=*"

也可直接从示例模板创建工程:

idf.py create-project-from-example "espressif/ble_htp=*:ble_htp"

组件 README 特别提示:如果执行create-project-from-example时提示CMakeLists.txt not found in project directory,说明使用的是旧版组件管理器,需在 ESP-IDF 环境中执行pip install -U idf-component-manager升级。

2.3 对底层连接管理组件的依赖

从源码看,esp_htp.c直接依赖esp_ble_conn_mgr.h#include "esp_ble_conn_mgr.h",见 esp_htp.c),所有 GATT 读写操作都通过esp_ble_conn_mgresp_ble_conn_read/esp_ble_conn_write完成。因此使用该组件时,工程需同时具备ble_conn_mgr的初始化与连接管理逻辑(示例中由 app_main.c 完成)。

三、核心数据结构:温度测量值格式

3.1 esp_ble_htp_data_t 结构体

esp_ble_htp_data_t(定义于 esp_htp.h)以紧凑位域方式还原了蓝牙规范中 Temperature Measurement 特征的数据布局:

typedef struct { struct { uint8_t temperature_unit: 1; /*!< 温度单位标志位 */ uint8_t time_stamp: 1; /*!< 时间戳标志位 */ uint8_t temperature_type: 1; /*!< 温度类型标志位 */ uint8_t reserved: 5; /*!< 保留位 */ } flags; union { uint32_t celsius; /*!< 摄氏温度值 */ uint32_t fahrenheit; /*!< 华氏温度值 */ } temperature; struct { uint16_t year; /*!< 公历年,有效范围 1582~9999 */ uint8_t month; /*!< 月,1(一月)~ 12(十二月) */ uint8_t day; /*!< 日,1~31 */ uint8_t hours; /*!< 小时,0~23 */ uint8_t minutes; /*!< 分钟,0~59 */ uint8_t seconds; /*!< 秒,0~59 */ } __attribute__((packed)) timestamp; /*!< 测量时间 */ uint8_t location; /*!< 温度测量部位 */ } __attribute__((packed)) esp_ble_htp_data_t;

各标志位掩码(esp_htp.h):

掩码宏含义
BLE_HTP_FLAGS_BM_TEMPERATURE_UNITS0x01Bit0:0 为摄氏度,1 为华氏度
BLE_HTP_FLAGS_BM_TIME_STAMP0x02Bit1:数据中是否携带时间戳
BLE_HTP_FLAGS_BM_TEMPERATURE_TYPE0x04Bit2:数据中是否携带温度类型

需要说明的是,规范中温度值字段本身是 IEEE 11073 标准的 32 位浮点编码,组件以uint32_t原始值原样保存,示例中直接打印该原始值(如日志中的62212°C),实际业务如需按摄氏度/华氏度显示,需要按 IEEE 11073 格式解析该 32 位字段。

3.2 温度类型枚举

location字段(Temperature Type)的取值定义在 esp_htp.h:

测量部位
BLE_HTP_CHR_TEMPERATURE_TYPE_RFU0保留
BLE_HTP_CHR_TEMPERATURE_TYPE_ARMPIT1腋下
BLE_HTP_CHR_TEMPERATURE_TYPE_BODY2身体(体表)
BLE_HTP_CHR_TEMPERATURE_TYPE_EAR3耳朵
BLE_HTP_CHR_TEMPERATURE_TYPE_FINGER4手指
BLE_HTP_CHR_TEMPERATURE_TYPE_GAST_TRACT5胃肠道
BLE_HTP_CHR_TEMPERATURE_TYPE_MOUTH6口腔
BLE_HTP_CHR_TEMPERATURE_TYPE_RECTUM7直肠
BLE_HTP_CHR_TEMPERATURE_TYPE_TOE8脚趾
BLE_HTP_CHR_TEMPERATURE_TYPE_TYMPANUM9鼓膜
BLE_HTP_CHR_TEMPERATURE_TYPE_MAX10枚举上界

3.3 数据解析流程

esp_htp.c 中的静态函数esp_ble_htp_get_temp_data()按规范顺序逐字段解析原始字节流:

  1. 先复制 1 字节 Flags 字段;
  2. 依据temperature_unit标志选择拷贝温度字段到temperature.celsiustemperature.fahrenheit
  3. time_stamp标志置位,拷贝 7 字节时间戳;
  4. temperature_type标志置位,读取温度类型到location

函数首先检查inbuf有效性且inlen >= 5(Flags + 温度值的理论最小长度),否则返回ESP_ERR_INVALID_ARG

四、API 一览:初始化、读写与事件

4.1 组件提供的五个接口

全部声明于 esp_htp.h:

函数说明返回值
esp_ble_htp_init(void)初始化 HTP,注册底层连接管理事件回调ESP_OK/ESP_ERR_INVALID_ARG/ESP_FAIL
esp_ble_htp_deinit(void)反初始化,注销事件回调同上
esp_ble_htp_get_temp_type(uint8_t *temp_type)读取设备的温度类型特征值(0x2A1D)ESP_OK/ESP_ERR_INVALID_ARG(入参为空指针)
esp_ble_htp_get_measurement_interval(uint16_t *interval_val)读取测量间隔特征值(0x2A21)同上
esp_ble_htp_set_measurement_interval(uint16_t interval_val)写入测量间隔特征值(0x2A21)ESP_OK/ 底层写失败错误码

初始化与反初始化的实现非常轻量(esp_htp.c):

esp_err_t esp_ble_htp_init(void) { return esp_event_handler_register(BLE_CONN_MGR_EVENTS, ESP_EVENT_ANY_ID, esp_ble_htp_event, NULL); } esp_err_t esp_ble_htp_deinit(void) { return esp_event_handler_unregister(BLE_CONN_MGR_EVENTS, ESP_EVENT_ANY_ID, esp_ble_htp_event); }

即:注册/注销一个针对BLE_CONN_MGR_EVENTS全部事件的回调,将连接管理层的接收数据转发为 HTP 上层事件。

4.2 事件机制:按特征 UUID 分发

组件声明了独立的事件基BLE_HTP_EVENTSESP_EVENT_DECLARE_BASE/ESP_EVENT_DEFINE_BASE)。在 esp_htp.c 的回调中:

case ESP_BLE_CONN_EVENT_DATA_RECEIVE: esp_ble_conn_data_t *conn_data = (esp_ble_conn_data_t *)event_data; esp_ble_htp_data_t ble_htp_data; memset(&ble_htp_data, 0, sizeof(esp_ble_htp_data_t)); esp_ble_htp_get_temp_data(&ble_htp_data, conn_data->data, conn_data->data_len); esp_event_post(BLE_HTP_EVENTS, conn_data->uuid.uuid16, &ble_htp_data, sizeof(esp_ble_htp_data_t), portMAX_DELAY);

关键设计是:事件 ID 直接使用来源特征值的 16 位 UUID。上层应用监听BLE_HTP_EVENTS时,只需把事件 ID 与BLE_HTP_CHR_UUID16_TEMPERATURE_MEASUREMENT(0x2A1C,最终温度,Indication)或BLE_HTP_CHR_UUID16_INTERMEDIATE_TEMPERATURE(0x2A1E,中间温度,Notification)比较,即可区分两类温度数据,收到的event_data即解析好的esp_ble_htp_data_t

从 esp_ble_conn_mgr.h 的注释可知,ESP_BLE_CONN_EVENT_DATA_RECEIVE事件中的data字段由 ble_conn_mgr 堆上分配,组件在解析后随即 post 到 HTP 事件,上层无需关心底层缓冲生命周期。

4.3 底层读写调用链

三个读写接口均通过ble_conn_mgr执行 GATT 操作,以 16 位 UUID 定位特征值(BLE_CONN_UUID_TYPE_16):

  • 读操作构造esp_ble_conn_data_t后调用esp_ble_conn_read(),成功后将返回缓冲区数据拷贝给调用方(温度类型取首字节,测量间隔按MIN(data_len, sizeof(uint16_t))拷贝);
  • 写操作将 2 字节uint16_t小端值填入esp_ble_conn_write()的入参,成功时打印十六进制日志ESP_LOG_BUFFER_HEX_LEVEL

esp_ble_conn_read/esp_ble_conn_write在 esp_nimble.c(NimBLE 后端)与 esp_bluedroid.c(Bluedroid 后端)中均有实现,因此ble_htp组件对两种经典蓝牙主机协议栈均透明兼容。

五、示例实操:连接体温计并收发温度数据

示例位于 examples/bluetooth/ble_profiles/ble_htp,支持 ESP32 / ESP32-C3 / ESP32-C2 / ESP32-S3 目标芯片。其行为是:创建 GATT Client 并被动扫描,若对端广播且声明主服务 UUID 为 0x1809,则发起连接;连接后自动发现服务、特征与描述符;同时启动交互式串口控制台,用于模拟 HTP 的读写操作。

5.1 构建与运行

idf.py set-target <chip_name> # 例如 esp32c3 idf.py menuconfig # Example Configuration 菜单下可配置广播名 idf.py -p PORT flash monitor # 编译、烧录并打开监视器

Example Configuration菜单(见 Kconfig.projbuild)默认配置为:

  • EXAMPLE_BLE_ADV_NAME:广播名,默认BLE_HTS
  • EXAMPLE_BLE_SUB_ADV:后续广播数据,默认SUB_ADV

测试对端可使用任意宣称支持健康温度计服务(0x1809)并在 GATT 数据库中包含该服务的 BLE GATT Server App。若对端声称支持 HTP 服务却不提供所需特征/描述符,或 GATT 流程失败,示例会立即断开连接。

5.2 控制台命令

控制台注册了htp命令(参数定义见 app_htp.c):

htp [-t <01~03>] [-i <0~65535>] -t, --type=<01~03> 01 读取温度类型特征值 02 读取测量间隔特征值 03 写入测量间隔特征值 -i, --interval=<0~65535> 0: 不进行周期测量;其他值: 测量间隔时长

典型操作:

# 读取温度类型 htp -t 1 # 读取测量间隔 htp -t 2 # 设置测量间隔为 0(关闭周期 Indication) htp -t 3 -i 0 # 设置测量间隔为 10 秒 htp -t 3 -i 10

app_htp_run()(app_htp.c)将命令类型 1/2/3 分别映射到esp_ble_htp_get_temp_type/esp_ble_htp_get_measurement_interval/esp_ble_htp_set_measurement_interval

5.3 应用层事件处理

示例通过esp_event_handler_register(BLE_HTP_EVENTS, ESP_EVENT_ANY_ID, app_htp_event_handler, NULL)订阅温度数据(app_htp.c)。回调按事件 ID(即特征 UUID)分流:

  • BLE_HTP_CHR_UUID16_TEMPERATURE_MEASUREMENT:打印时间戳(若带)、温度类型(若带)与Measurement Temperature(按标志位输出°C°F);
  • BLE_HTP_CHR_UUID16_INTERMEDIATE_TEMPERATURE:同样解析并打印Intermediate Temperature

5.4 运行日志解读

以 ESP32-C3 上成功连接后的日志为例(节选自 示例 README):

esp32c3> htp -t 1 I (12397) esp_nimble: characteristic read; conn_handle=1 attr_handle=16 len=1 I (12397) app_htp: Gets the current temperature type value 7 esp32c3> htp -t 2 I (14477) esp_nimble: characteristic read; conn_handle=1 attr_handle=23 len=2 I (14477) app_htp: Gets the measurement interval value 2068 esp32c3> htp -t 3 -i 0 I (23707) esp_htp: Sets the measurement interval value Success! I (23717) esp_htp: ESP_BLE_CONN_EVENT_DATA_RECEIVE I (23727) app_htp: Measurement Temperature 62212°C I (23727) app_htp: Sets the measurement interval value 0 I (23797) esp_htp: ESP_BLE_CONN_EVENT_DATA_RECEIVE I (23817) app_htp: Intermediate Temperature 50762℉ esp32c3> htp -t 3 -i 10 I (27307) esp_htp: Sets the measurement interval value Success! I (27337) app_htp: Temperature Type 7 I (27337) app_htp: Measurement Temperature 7873°C I (27337) app_htp: Sets the measurement interval value 10 I (27417) app_htp: Intermediate Temperature 13545°C

日志清晰展示了完整数据流:写测量间隔成功后,对端随即通过 Indication(0x2A1C)上报最终温度、通过 Notification(0x2A1E)上报中间温度;ESP_BLE_CONN_EVENT_DATA_RECEIVE由底层连接管理触发,esp_htp完成解析,app_htp负责打印展示。

5.5 主程序初始化顺序

app_main.c 给出了标准的接入顺序,可作为二次开发模板:

  1. nvs_flash_init()初始化 NVS(失败且为ESP_ERR_NVS_NO_FREE_PAGES/ESP_ERR_NVS_NEW_VERSION_FOUND时先擦除再初始化);
  2. esp_event_loop_create_default()创建默认事件循环;
  3. 注册BLE_CONN_MGR_EVENTS的全局连接状态回调(CONNECTED / DISCONNECTED / DISC_COMPLETE / DATA_RECEIVE);
  4. app_console_init()初始化控制台,register_htp()注册htp命令并调用esp_ble_htp_init()
  5. esp_ble_conn_init(&config)传入esp_ble_conn_config_t(含device_namebroadcast_data),esp_ble_conn_start()启动扫描连接流程;失败时依次esp_ble_conn_stop()esp_ble_conn_deinit()并注销事件。

六、小结

ble_htp组件在 ESP IoT Solution 中属于“BLE 标准 Profile”组件族(与ble_hrpble_anpble_otp并列于 components/bluetooth/ble_profiles/std)。它并不直接管理扫描、连接与 GATT 发现,而是依赖ble_conn_mgr完成这些底层工作,自身专注于两件事:把 HTP 特征的原始字节解析为结构化的esp_ble_htp_data_t,以及以“特征 UUID 即事件 ID”的方式向应用层分发温度数据。这种分层设计使开发者只需调用 5 个 API 并订阅BLE_HTP_EVENTS,即可快速接入符合蓝牙规范的体温计设备,可用于健康监测、医疗数据采集等物联网应用场景。

【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 3:28:44

Java后端与微信小程序打造的电脑DIY配置交流平台全解析

这标题一看就是典型的计算机毕业设计题&#xff0c;Java后端加微信小程序前端&#xff0c;再套一个"电脑DIY配置与交流平台"的业务壳子。说实话&#xff0c;这类题目在毕业设计里属于"看着不难、做起来全是坑"的类型。为什么&#xff1f;因为它的难点根本不…

作者头像 李华
网站建设 2026/9/19 3:28:06

开发者高效截图指南:从工具选型到AI辅助开发实战

做开发这行&#xff0c;打开频率最高的除了IDE&#xff0c;我敢说就是截图工具了。不管是接需求、对UI、提Bug、写文档&#xff0c;还是远程帮同事排查问题&#xff0c;截图几乎贯穿了开发流程的每一个环节。但很多人对截图软件的理解还停留在“能截个图就行”&#xff0c;功能…

作者头像 李华
网站建设 2026/9/19 3:28:02

寒武纪MLU370部署YOLOv5实战:从模型转换到INT8量化全流程

1. 为什么要在寒武纪 MLU370 上跑 YOLOv5先说结论&#xff1a;如果你手头有一块寒武纪 MLU370 加速卡&#xff0c;又恰好要做一个工业级的目标检测项目&#xff0c;比如工地安全帽佩戴检测&#xff0c;那么把 YOLOv5 部署上去是一个非常务实的选择。原因不复杂——MLU370 的 IN…

作者头像 李华
网站建设 2026/9/19 3:24:52

大疆上云API 1.10.0设备位置数据实时处理与WebSocket推送实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 3:22:09

平面向量数乘坐标表示:从公式到共线判定与编程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华