ESP-IoT-Solution BTHome 蓝牙调光器示例全解析:事件触发广播、加密载荷与 RTC IO 低功耗唤醒
ESP-IoT-Solution BTHome 蓝牙调光器示例全解析事件触发广播、加密载荷与 RTC IO 低功耗唤醒【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution导读本文以 esp-iot-solution 仓库中的bthome/dimmer示例为对象讲解如何基于 ESP-IDF 的bthome组件与ble_hci组件实现一个符合 BTHome 协议的加密蓝牙调光器通过按键与旋钮采集输入、仅在事件发生时广播 300 ms 即自动停播并借助动态调频、tickless idle 与 RTC IO 唤醒实现极低功耗运行。读完本文你将掌握 BTHome 广播载荷的构建方式、iot_button/iot_knob低功耗驱动的选型逻辑以及 ESP32-H2/H4 上 light sleep 与 GPIO 引脚约束的落地实践。BTHome Dimmer 示例概述该示例位于 examples/bluetooth/ble_adv/bthome/dimmer是基于仓库内bthome组件components/bluetooth/ble_adv/bthome实现的一个通用蓝牙调光器参考实现。它读取按键与旋钮的状态并通过 BLE 广播发送符合 BTHome 协议的加密广播包从而被 BTHome 生态如 Home Assistant 的 BTHome 集成直接识别。软件层面实现的效果可概括为三点事件采集与上报读取按键button与旋钮knob的值并通过 BLE ADV 发送事件触发式广播仅在按键按压或旋钮旋转时广播广播在最后一次事件后300 ms 自动停止避免持续广播耗电自动休眠唤醒支持 light sleep 自动休眠按键与旋钮通过RTC IO唤醒保证休眠期间仍能及时响应交互。工程结构与依赖组件目录组成examples/bluetooth/ble_adv/bthome/dimmer/ ├── main/ │ ├── CMakeLists.txt # 组件构建声明 │ ├── Kconfig.projbuild # 例程可调参数CPU 频率、GPIO 等 │ ├── app_main.c # 全部业务逻辑 │ └── idf_component.yml # 组件依赖清单 ├── CMakeLists.txt ├── README.md / README_CN.md ├── sdkconfig.defaults # 通用默认配置 └── sdkconfig.defaults.esp32h4 # ESP32-H4 低功耗优化配置依赖关系main/idf_component.yml 声明了示例的全部依赖均通过override_path指向仓库内的本地组件依赖指向仓库组件作用bthomecomponents/bluetooth/ble_adv/bthomeBTHome 协议编解码与加密ble_hcicomponents/bluetooth/ble_hci免 NimBLE/Bluedroid 的底层 HCI 广播接口buttoncomponents/button按键驱动含 GPIO/RTC 两种实现knobcomponents/knob旋钮旋转编码器驱动含 GPIO/RTC 两种实现idf—要求 ESP-IDF 版本5.0构建声明见 main/CMakeLists.txtPRIV_REQUIRES driver bthome ble_hci nvs_flash其中nvs_flash用于 BTHome 参数的持久化存储。值得注意本示例不依赖完整的 BLE 协议栈如 NimBLE 或 Bluedroid而是直接使用ble_hci组件通过 HCI 层下发广播参数与广播数据配合sdkconfig.defaults中的CONFIG_BT_CONTROLLER_ONLYy将系统资源占用与功耗降到最低。支持的芯片与硬件约束目标芯片ESP32-H2默认目标对应 ESP-Dimmer 硬件参考设计ESP32-H4低功耗优化版本选择该目标后会自动加载sdkconfig.defaults.esp32h4。GPIO 引脚约束这是最容易踩坑的部分示例在 main/Kconfig.projbuild 中针对不同芯片给出了不同的引脚范围限制ESP32-H4按键与旋钮引脚必须为 RTC GPIO 0–5。默认启用 RTC IO 驱动CONFIG_EXAMPLE_BUTTON_KNOB_USE_RTC_IO通过 RTC IO 实现 light sleep 唤醒ESP32-H2当启用 light sleep 外设掉电CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP时按键与旋钮引脚需使用RTC 唤醒 GPIO 7–14此时走 GPIO 驱动路径。Kconfig 中通过range指令直接约束可选引脚范围例如EXAMPLE_GPIO_KNOB_A在 ESP32-H4 上为range 0 5、在 ESP32-H2 上为range 0 27若选择了非法引脚menuconfig 会直接报错从配置源头规避唤醒引脚失效问题。编译与烧写进入示例目录后使用idf.py设置目标芯片并编译烧写cd ./esp-iot-solution/examples/bluetooth/ble_adv/bthome/dimmer # ESP32-H2默认硬件参考设计 idf.py set-target esp32h2 # ESP32-H4低功耗优化自动加载 sdkconfig.defaults.esp32h4 idf.py set-target esp32h4 # 编译并下载PORT 替换为实际串口 idf.py -p PORT build flash设置esp32h4目标时IDF 会按照命名规则自动加载sdkconfig.defaults.esp32h4无需手动合并配置。源码级工作流程解析初始化链路app_main()main/app_main.c 的启动顺序如下NVS 初始化nvs_flash_init()若发生页耗尽或版本更新则先擦除再初始化电源管理配置在CONFIG_PM_ENABLE下调用esp_pm_configure()以CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ/CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ配置动态调频DFS范围若启用了CONFIG_FREERTOS_USE_TICKLESS_IDLE则同时开启自动 light sleeplight_sleep_enable trueBTHome 对象创建与参数注入bthome_create()创建句柄注册 NVS 存储/加载回调设置 16 字节加密密钥app_main.c#L55与本地 MAC 地址最后bthome_load_params()从 NVS 恢复参数创建任务与定时器创建dimmer task栈 4096、优先级 10并创建一次性 300 ms 定时器app_main.c#L357定时器到点即关闭广播初始化外设power_ctrl_io_init()将电源控制引脚拉高并gpio_hold_en()保持app_main.c#L162-L181随后初始化旋钮与按键并注册回调。事件采集ISR 通知 任务消费按键与旋钮的回调均运行在 ISR 上下文通过xTaskNotifyFromISR向dimmer task发送事件TASK_EVENT_BTN/TASK_EVENT_KNOB见 app_main.c#L60-L82。其中按键回调还会读取esp_sleep_get_wakeup_cause()判断是否由 light sleep 唤醒而来——这是 RTC IO 唤醒路径的关键一环。dimmer_task主循环app_main.c#L89-L160通过xTaskNotifyWait阻塞等待事件收到事件后根据类型编码事件载荷按键事件BUTTON_SINGLE_CLICK时btn_evt_id 1否则为 0此时dim_evt {0, 0}无旋转旋钮事件读取iot_knob_get_count_value()的累计值正值编码为dim_evt {1, value}左旋负值编码为{2, -value}右旋。广播数据构建BTHome 载荷与加密dimmer task中先配置广播参数app_main.c#L98-L108广播间隔0x50约 50 msADV_TYPE_NONCONN_IND不可连接广播随机地址类型BLE_ADDR_TYPE_RANDOM使用ble_hci_set_random_address()设置示例中预定义的本地 MAC广播信道全开ADV_CHNL_ALL。随后通过 BTHome 组件 API 构建载荷app_main.c#L142-L144payload_length bthome_payload_adv_add_evt_data(payload_data, payload_length, BTHOME_EVENT_ID_BUTTON, btn_evt_id, 1); payload_length bthome_payload_adv_add_evt_data(payload_data, payload_length, BTHOME_EVENT_ID_DIMMER, dim_evt, 2); adv_len bthome_make_adv_data(s_dimmer-bthome, advertisement_data, name, sizeof(name), info, payload_data, payload_length);其中BTHOME_EVENT_ID_BUTTON 0x3A、BTHOME_EVENT_ID_DIMMER 0x3C为事件对象 ID见 components/bluetooth/ble_adv/bthome/include/bthome_v2.h#L110-L113name为{0x44, 0x49, 0x59}即 ASCII 的DIY——这也是手机 APP 中搜索到的设备名。设备信息字节bthome_device_info_t见 bthome_v2.h#L120-L129通过位域设置位字段示例取值含义bit 0encryption_flag1载荷已加密bit 2trigger_based_flag0非纯触发型设备携带事件数据bit 5–7bthome_version2BTHome 协议版本 v2bthome_make_adv_data()在内部完成服务数据段BTHome Service UUID 设备信息字节、设备名与加密载荷的拼装加密基于示例预置的 16 字节密钥与本地 MAC 地址bthome_set_encrypt_key()/bthome_set_local_mac_addr()。广播包构建成功后调用ble_hci_set_adv_data()下发数据、ble_hci_set_adv_enable(true)开启广播并启动/重置 300 ms 定时器app_main.c#L151-L157。定时器到点后执行ble_hci_set_adv_enable(false)停播app_main.c#L84-L87。由于每次新事件都会xTimerReset实际效果是最后一个事件后 300 ms 停播。参数持久化NVS 存储回调BTHome 组件允许注册store/load回调bthome_callbacks_t见 bthome_v2.h#L161-L164。示例在 app_main.c#L268-L308 中基于 NVS 的nvs_set_blob/nvs_get_blob实现namespace 为storage用于保存 BTHome 绑定/配对相关参数实现重启后免重新配对。低功耗设计从配置到驱动的完整链路两套 sdkconfig 的差异通用默认配置 sdkconfig.defaultsCONFIG_BT_ENABLEDy CONFIG_BT_CONTROLLER_ONLYy # 仅启用控制器不启用完整协议栈 CONFIG_BT_LE_SLEEP_ENABLEy # BLE 控制器睡眠 CONFIG_PM_ENABLEy # 电源管理 CONFIG_PM_DFS_INIT_AUTOy # 动态调频自动初始化 CONFIG_FREERTOS_HZ1000 CONFIG_FREERTOS_USE_TICKLESS_IDLEy # tickless idle自动 light sleep 前提 CONFIG_LOG_DEFAULT_LEVEL_WARNy # 默认 WARN 级别压低日志功耗 CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVEyESP32-H4 专属配置 sdkconfig.defaults.esp32h4 在通用配置之上追加CONFIG_BT_CTRL_SLEEP_ENABLEy # 控制器睡眠 CONFIG_BT_CTRL_LP_CLK_SRC_DEFAULTy CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEPy # light sleep 外设掉电 CONFIG_EXAMPLE_BUTTON_KNOB_USE_RTC_IOy # 按键/旋钮走 RTC IO 驱动 CONFIG_RTC_CLK_SRC_EXT_CRYSy # RTC 慢时钟使用外置 32 kHz 晶振动态调频与自动 light sleep在CONFIG_PM_ENABLE下示例通过esp_pm_configure()设定 CPU 频率区间。默认值按芯片区分见 Kconfig.projbuild#L3-L7 与 Kconfig.projbuild#L41-L46芯片最大 CPU 频率最小 CPU 频率ESP32-H432 MHz16 MHz依赖 32 MHz XTALESP32-H296 MHz32 MHz其他芯片如 ESP32/S2/S3/C580/120/160/240 MHz 可选与 XTAL 对应最小频率必须为 XTAL 频率或其整数分频这是 ESP-IDF DFS 的硬件约束。配合CONFIG_FREERTOS_USE_TICKLESS_IDLE系统在空闲时自动进入 light sleep再叠加CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEPlight sleep 期间外设电源被切断进一步降低漏电流。RTC IO 驱动 vs GPIO 驱动示例通过条件编译在两种驱动之间切换见 app_main.c#L217-L221 与 app_main.c#L236-L262CONFIG_EXAMPLE_BUTTON_KNOB_USE_RTC_IOy时旋钮走iot_knob_create_rtc()components/knob/knob_rtc.c按键走iot_button_new_rtc_device()components/button/button_rtc.c二者均通过 RTC IO 在 light sleep 期间保持唤醒能力关闭该选项时走iot_knob_create()与iot_button_new_gpio_device()components/button/button_gpio.c的 GPIO 驱动路径。两种路径都注册了按键/旋钮回调但唤醒机制不同RTC IO 驱动允许深度 light sleep 后被外设事件唤醒而普通 GPIO 驱动仅适用于未启用外设掉电的场景。此外当启用外设掉电且未使用 RTC IO 驱动时代码会调用validate_wakeup_gpio()校验旋钮两相引脚是否为合法的 light sleep 唤醒引脚app_main.c#L183-L192这是 ESP32-H2 上必须选择 RTC 唤醒 GPIO 7–14 的运行时保障。外置 32 kHz 晶振CONFIG_RTC_CLK_SRC_EXT_CRYS在 ESP32-H4 上默认启用RTC 慢时钟使用外置 32 kHz 晶振而非内部 RC 振荡器休眠电流显著更低。这是 H4 低功耗优化的重要一环。menuconfig 可调参数速查全部参数位于 menuconfig 的Example Configuration菜单下定义见 main/Kconfig.projbuild配置项默认值说明EXAMPLE_MAX_CPU_FREQ_MHZH4: 32 / H2: 96DFS 最大 CPU 频率EXAMPLE_MIN_CPU_FREQ_MHZH4: 16 / H2: 32DFS 最小 CPU 频率须为 XTAL 或其整数分频EXAMPLE_BUTTON_KNOB_USE_RTC_IOnH4 配置中开启按键/旋钮使用 RTC IO 驱动实现低功耗唤醒EXAMPLE_GPIO_KNOB_A2旋转编码器 A 相引脚H4 限 0–5H2 限 0–27EXAMPLE_GPIO_KNOB_B3旋转编码器 B 相引脚范围同上EXAMPLE_POWER_CTRL_IO_NUM9电源控制引脚上电后保持高电平EXAMPLE_BUTTON_IO_NUM0按键引脚范围同旋钮EXAMPLE_BUTTON_ACTIVE_LEVEL0按键有效电平0 低有效1 高有效注意旋钮两个引脚与按键引脚都必须满足对应芯片的 RTC 唤醒约束否则编译期 Kconfigrange或运行期validate_wakeup_gpio()会给出明确错误。运行验证与输出为优化功耗示例默认把日志级别设为CONFIG_LOG_DEFAULT_LEVEL_WARNsdkconfig 中为 WARN且示例内部关键日志使用ESP_LOG_BUFFER_HEX_LEVEL(..., ESP_LOG_WARN)打印广播包内容常规启动几乎无日志输出。验证方式烧写后按压按键或旋转旋钮使用任意 BLE 扫描工具如手机 APP搜索名为DIY的设备即可观察到加密的 BTHome 广播包将设备接入 Home Assistant 等支持 BTHome 协议的网关后事件即可被识别为调光/按键操作。该示例的 BTHome 协议实现细节可进一步查阅 components/bluetooth/ble_adv/bthome/README.md 与其单元测试 components/bluetooth/ble_adv/bthome/test_apps/main/bthome_test.c。总结bthome/dimmer示例完整展示了事件触发广播 加密载荷 低功耗休眠三合一的 BLE 外设实现范式协议层复用bthome组件的载荷构造、加密与设备信息编码能力仅需少量 API 即可产出符合 BTHome v2 规范的广播包传输层ble_hci组件绕过完整 BLE 协议栈以最精简的方式管理非连接广播配合 300 ms 定时器实现有事件才广播低功耗层DFS tickless idle light sleep 外设掉电 BLE 控制器睡眠 RTC IO 唤醒层层叠加并针对 ESP32-H4 做了外置 32 kHz 晶振的专项优化。该示例不仅是 BTHome 调光器的参考实现其ISR 通知 任务编码 定时停播 唤醒校验的工程结构也适合作为其他事件驱动型低功耗 BLE 广播设备传感器、遥控器、开关面板等的开发蓝本。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考