资讯动态

ESP-IoT-Solution BLE WSS 示例实战:基于 NimBLE 与 ble_conn_mgr 构建体重秤 GATT 服务端

发布时间:2026/9/19 17:02:03 来源:尧图企业网站定制
ESP-IoT-Solution BLE WSS 示例实战基于 NimBLE 与 ble_conn_mgr 构建体重秤 GATT 服务端【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本篇技术指南围绕 esp-iot-solution 仓库中的examples/bluetooth/ble_services/ble_wss示例展开讲解如何在乐鑫 ESP32 系列芯片上基于 NimBLE 协议栈与 ble_conn_mgr 连接管理组件以最少样板代码实现一个符合蓝牙 SIG 规范的 Weight Scale ServiceWSS体重秤服务UUID 0x181DGATT 服务端。读完本文你将掌握该示例的工程结构、编译烧录步骤、menuconfig 配置项以及从服务注册、测量值打包到主动 Indicate 上报的完整源码级实现链路。示例定位一个开箱即用的 BLE 体重秤服务端ble_wss示例的核心作用是在设备端创建一个 GATT 服务器GATT Server启动广播后等待 GATT 客户端如手机上的 BLE 调试 App连接。设备通过 Weight Scale Service 对外暴露体重测量能力客户端可以读取设备的 Weight Feature体重秤特性UUID 0x2A9E并订阅 Weight Measurement体重测量值UUID 0x2A9D的 Indicate 通知实时获取体重、时间戳、用户索引、BMI 与身高数据。该示例在架构上复用了两个关键组件ble_conn_mgrBLE 连接管理器封装了 NimBLE 的 GAP/GATT 细节通过事件驱动模型BLE_CONN_MGR_EVENTS与应用交互ble_services/wssWeight Scale Service 的标准服务实现直接向 ble_conn_mgr 注册服务与特征。因此示例的app_main.c非常精简——应用层只需要完成初始化与事件回调服务逻辑全部收敛在组件内部。支持的芯片与软硬件前提根据示例 README 的说明本示例支持以下芯片目标支持的芯片ESP32ESP32-C3ESP32-C2ESP32-S3ESP32-H2硬件上只需一块搭载上述任一 SoC 的开发板一根用于供电与程序烧录的 USB 线用于测试的手机 BLE 扫描/连接 App任意支持 GATT 的 BLE 调试工具即可。软件方面main/idf_component.yml 声明了依赖约束idf 4.3组件ble_conn_mgr版本~1.*组件ble_services版本~1.*并统一通过override_path指向仓库内的本地组件目录保证示例与仓库源码同步。工程结构速览examples/bluetooth/ble_services/ble_wss/ ├── CMakeLists.txt # 顶层工程文件project(ble_wss) ├── README.md # 示例说明文档 ├── sdkconfig.defaults # 默认 sdkconfig启用 BT/NimBLE/WSS ├── sdkconfig.ci.nimble # CI 配置强制 NimBLE └── main/ ├── CMakeLists.txt # 组件注册仅含 app_main.c ├── Kconfig.projbuild # 示例级配置项广播名等 ├── app_main.c # 应用入口与事件回调 └── idf_component.yml # 组件依赖声明顶层 CMakeLists.txt 是标准的 ESP-IDF 工程骨架project(ble_wss)声明工程名main/CMakeLists.txt 只注册了一个源文件app_main.c可见全部业务逻辑都集中在此。配置工程三步完成设置第一步设置目标芯片在工程目录下先用idf.py set-target指定目标芯片根据你的开发板从支持列表中选择idf.py set-target chip_name例如 ESP32-S3 开发板执行idf.py set-target esp32s3。第二步打开菜单配置idf.py menuconfig第三步按需修改配置项Example Configuration 菜单下有两个示例级配置项定义于 main/Kconfig.projbuildAdvertisement name设备广播名。README 中记录的默认值为BLE_WSS需要说明的是当前仓库快照的 Kconfig 文件中实际默认值为BLE_CTS该字段沿用了同目录其他服务示例的模板如果你在复现时希望广播名为BLE_WSS可在此处手动修改Subsequent advertisement data后续广播数据默认SUB_ADV对应源码中esp_ble_conn_config_t.broadcast_data字段见 app_main.c。BLE Standard Services 菜单下GATT Weight Scale Service是否启用 WSS 服务。其底层开关为组件 Kconfig.in 中定义的menuconfig BLE_WSS默认为关闭本示例的 sdkconfig.defaults 中已预置CONFIG_BLE_WSSy将其打开。此外示例的 sdkconfig.defaults 预置了运行所需的关键开关编译时无需手工逐个打开# 启用蓝牙协议栈 CONFIG_BT_ENABLEDy CONFIG_BT_NIMBLE_ENABLEDy # 启用 ble_conn_mgr 的外设角色 CONFIG_BLE_CONN_MGR_ROLE_PERIPHERALy # 启用 Weight Scale Service 组件 CONFIG_BLE_WSSy其中CONFIG_BLE_CONN_MGR_ROLE_PERIPHERALy指定本设备作为 GATT 外设Peripheralsdkconfig.ci.nimble 则用于 CI 场景强制启用 NimBLE。编译、烧录与运行一条命令完成编译、烧录并打开串口监视器idf.py -p PORT flash monitor将PORT替换为开发板的串口设备名如/dev/ttyUSB0。退出串口监视器请按Ctrl-]。运行输出解读设备上电后串口会输出类似下面的日志节选自示例 READMEI (330) BLE_INIT: BT controller compile version [9359a4d] I (340) system_api: Base MAC address is not set I (340) system_api: read default base MAC address from EFUSE I (350) BLE_INIT: Bluetooth MAC: 58:cf:79:1e:9e:de I (350) phy_init: phy_version 1150,7c3c08f,Jan 24 2024,17:32:21 I (410) blecm_nimble: BLE Host Task Started I (410) blecm_nimble: No characteristic(0x2a00) found I (410) blecm_nimble: No characteristic(0x2a01) found I (410) blecm_nimble: No characteristic(0x2a05) found I (420) NimBLE: GAP procedure initiated: stop advertising. I (430) NimBLE: GAP procedure initiated: advertise; I (430) NimBLE: disc_mode2 I (440) NimBLE: adv_channel_map0 own_addr_type0 adv_filter_policy0 adv_itvl_min256 adv_itvl_max256 I (450) NimBLE: I (450) main_task: Returned from app_main()解读要点BLE Host Task StartedNimBLE 主机任务已启动blecm_nimble组件完成 GATT 数据库初始化三行No characteristic(...)表示 ble_conn_mgr 在注册服务前会尝试查找 GATT 通用特征如 Device Name 0x2a00、Appearance 0x2a01、Service Changed 0x2a05本例未注册这些特征属正常提示GAP procedure initiated: advertise设备已进入广播状态disc_mode2 为可发现模式此时即可用手机 BLE 工具扫描到设备并连接main_task: Returned from app_main()app_main正常返回后续逻辑全部由事件驱动。源码级原理剖析1. 应用入口事件驱动 三步初始化app_main.c 的初始化流程清晰可分四步NVS 初始化nvs_flash_init()并在 NVS 空间不足/版本变更时先擦除再初始化ESP-IDF 标准范式事件循环与回调注册esp_event_loop_create_default()创建默认事件循环esp_event_handler_register(BLE_CONN_MGR_EVENTS, ESP_EVENT_ANY_ID, ...)注册连接管理事件回调连接管理器初始化esp_ble_conn_init(config)其中device_name取自CONFIG_EXAMPLE_BLE_ADV_NAMEbroadcast_data取自CONFIG_EXAMPLE_BLE_SUB_ADV服务注册与启动esp_ble_wss_init()注册 WSS 服务esp_ble_conn_start()启动广播启动失败时依次执行stop → deinit → unregister的清理回退。2. WSS 服务注册特征查找表驱动WSS 组件通过 esp_wss.c 定义了一张特征查找表nu_lookup_table并通过esp_ble_conn_add_svc()将服务注册进 ble_conn_mgrstatic const esp_ble_conn_character_t nu_lookup_table[] { { weight feature, BLE_CONN_UUID_TYPE_16, BLE_CONN_GATT_CHR_READ , { BLE_WSS_CHR_UUID16_WEIGHT_FEATURE }, wss_feature_cb }, { weight measurement, BLE_CONN_UUID_TYPE_16, BLE_CONN_GATT_CHR_INDICATE , { BLE_WSS_CHR_UUID16_WEIGHT_MEASUREMENT }, NULL }, };对照 esp_wss.h 中的 UUID 定义服务 UUIDBLE_WSS_UUID16 0x181DWeight Feature 特征0x2A9E可读带回调Weight Measurement 特征0x2A9DIndicate无回调、由应用主动上报。esp_ble_wss_init()的实现即一行return esp_ble_conn_add_svc(svc);。3. Weight Feature可读特征与位域编码Weight Feature 特征在客户端读取时触发wss_feature_cb回调esp_wss.c回调将内部维护的s_wss_feature拷贝返回。其数据结构esp_ble_wss_feature_t按位域紧凑编码esp_wss.htimestamp/user_id/bmi/weight/height各 1 bit标记对应能力是否支持w_resolution3 bit体重分辨率取值定义见 esp_wss.h从0x0无到0x70.005 kgh_resolution2 bit身高分辨率取值从0x0无到0x30.001 m见 esp_wss.h。组件默认将全部能力置 1esp_wss.c并在每次设置测量值时依据测量值的 Flag 动态重建 Feature 位见下节。4. 测量值结构Flag 可选字段esp_ble_wss_measurement_tesp_wss.h是核心数据载体采用蓝牙 SIG 规定的紧凑布局flag位域决定可选字段是否出现在报文中measurement_unit0 表示 kg/m 单位1 表示按分辨率解释、time_present是否含时间戳、user_present是否含用户索引、bmi_height_present是否含 BMI 与身高weightuint16体重值timestamp打包结构体年 1582~9999、月 1~12、日 1~31、时 0~23、分/秒 0~59user_iduint8用户索引bmiuint8与heightuint16BMI 与身高weight_resolution/height_resolution当measurement_unit1时引用。5. 测量值打包与主动上报应用在连接建立后调用esp_ble_wss_set_measurement(wss_measurement, true)app_main.c第二个参数need_sendtrue表示同时通过 Indicate 上报给客户端。该函数esp_wss.c做三件事保存测量值副本到静态变量s_wss_measurement根据测量值的 Flag 重建s_wss_feature例如time_present1则置timestamp位bmi_height_present1则置bmi与height位调用内部build_wss_ind_buf()esp_wss.c按 Flag 顺序依次写入 Flag4 字节、weight2 字节、可选 timestamp、可选 user_id、可选 BMIheight生成符合规范的 Indicate 报文最后通过esp_ble_conn_write()发送给远端客户端。esp_ble_wss_get_measurement()esp_wss.c则提供对称的读取接口供应用查询最近一次测量值。6. 连接事件驱动模型app_main.c 中的事件回调app_ble_conn_event_handler监听BLE_CONN_MGR_EVENTSESP_BLE_CONN_EVENT_CONNECTED客户端连入立即用一份预置的演示测量数据年份 2024、用户 ID 1、BMI 0x18、身高 0x33 等调用esp_ble_wss_set_measurement(..., true)主动向客户端 Indicate 一次体重测量ESP_BLE_CONN_EVENT_DISCONNECTED连接断开仅打日志等待下一次连接。这就是连接即上报的典型 BLE 外设交互模式——实测中手机 BLE 工具连接设备后即可直接收到一条 Weight Measurement 通知。常见问题与排查思路扫描不到设备确认idf.py set-target的芯片与开发板一致检查CONFIG_BT_ENABLED与CONFIG_BT_NIMBLE_ENABLED是否打开本示例 sdkconfig.defaults 已预置连接后收不到测量通知确认手机端已订阅 Weight Measurement 特征的 Indicate客户端需先写 CCCD并检查CONFIG_BLE_CONN_MGR_ROLE_PERIPHERALy是否生效广播名与预期不符在Example Configuration → Advertisement name中核对配置值注意当前仓库 Kconfig 的默认模板值为BLE_CTS如需BLE_WSS请手动修改服务未出现确认menuconfig中GATT Weight Scale ServiceCONFIG_BLE_WSS已启用该开关控制 esp_wss.c 是否参与编译。如需进一步深入可直接阅读 ble_conn_mgr 与 ble_services 两个组件的文档对比ble_services目录下其他标准服务如 UDS、BCS、HRS 等的实现会发现它们共享完全相同的服务注册模式——掌握本示例后即可快速移植出任意一个自定义 GATT 服务。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价