- 物联网
- 嵌入式
- 驱动开发
- 硬件开发
【免费下载链接】esp-iot-solution
Espressif IoT Library. IoT Device Drivers, Documentations and Solutions.
本指南以
examples/bluetooth/ble_services/ble_ots示例为核心,介绍如何在 ESP32 系列芯片上通过 esp-iot-solution 的 OTS 组件构建一个实现 BLE Object Transfer Service(对象传输服务,OTS)的 GATT 服务端:从硬件准备、工程配置、编译烧录,到应用层事件处理与底层 OTS 服务 API 的完整剖析。读完本文,你将掌握在 ESP-IDF + NimBLE 环境下启用 OTS 服务、配置广播参数、处理 Object Name / Object Properties 写入事件,并通过通用 BLE 扫描工具进行连接与基础验证的完整实战流程。
1. 示例概述与功能边界
BLE Object Transfer Service(OTS,服务 UUID0x1825)是 Bluetooth SIG 定义的标准服务,用于在设备之间传输二进制对象(文件、固件、配置数据等)。本示例在 ESP32 上创建一个实现了 OTS 的 GATT 服务器,并启动广播等待 GATT 客户端连接,用于演示BLE 连接管理与OTS 相关的 GATT 流程。
需要注意的是,该示例聚焦于验证 OTS 服务的基础通信能力,属于"基础 OTS GATT 流程"演示,并未实现完整的 OTS 功能,例如:
- 对象操作(创建、删除、读、写);
- OACP(Object Action Control Point,对象动作控制点)与 OLCP(Object List Control Point,对象列表控制点)流程;
- 对象元数据处理。
在功能评估与二次开发时,这一点至关重要——它更适合作为 OTS 服务接入与底层 API 使用的起点,而非开箱即用的对象传输应用。
支持的芯片目标
示例通过 CI 配置验证的支持范围如下(源自 README.md):
| 支持的芯片 | ESP32 | ESP32-C3 | ESP32-C2 | ESP32-S3 | ESP32-H2 |
|---|
示例工程位置
- 示例工程:examples/bluetooth/ble_services/ble_ots
- 底层 OTS 服务组件:components/bluetooth/ble_services/ots
- 同目录下其他标准 BLE 服务示例可参考 components/bluetooth/ble_services/README.md
2. 工程结构与依赖关系
该示例是一个标准的 ESP-IDF 工程,目录结构非常精简:
examples/bluetooth/ble_services/ble_ots/ ├── main/ │ ├── CMakeLists.txt # 声明源文件与依赖(bt、nvs_flash) │ ├── Kconfig.projbuild # Example Configuration 菜单(广播名、副广播数据) │ ├── app_main.c # 应用主逻辑 │ └── idf_component.yml ├── CMakeLists.txt ├── README.md ├── sdkconfig.ci.nimble # CI 使用的 NimBLE 配置 └── sdkconfig.defaults # 默认配置(开启 BT 栈与 OTS)从 main/CMakeLists.txt 可以看到,应用层直接依赖bt与nvs_flash:
idf_component_register(SRCS "app_main.c" REQUIRES bt nvs_flash)在代码层面,app_main.c 引用了两个关键头文件:
esp_ble_conn_mgr.h:来自连接管理组件 components/bluetooth/ble_conn_mgr,负责 BLE 初始化、广播、连接与断开的事件管理;esp_ots.h:来自 OTS 服务组件 components/bluetooth/ble_services/ots/include/esp_ots.h,提供 OTS 各特征值的读写 API 与事件定义。
这种"连接管理 + 标准服务"的分层设计,使应用代码只需聚焦业务逻辑,无需直接操作 GATT 表与 NimBLE 底层接口。
3. 硬件准备与快速上手
硬件需求
- 一块搭载 ESP32 / ESP32-C3 / ESP32-C2 / ESP32-S3 / ESP32-H2 SoC 的开发板;
- 一根 USB 数据线,用于供电与程序烧录。
设置芯片目标
工程配置与编译前,必须先设置正确的芯片目标:
idf.py set-target <chip_name>例如 ESP32-S3:
idf.py set-target esp32s3编译、烧录与监视
构建工程并烧录到开发板,随后打开串口监视器查看输出:
idf.py -p PORT flash monitor退出串口监视器使用快捷键Ctrl-]。
4. 配置项详解:广播参数与 OTS 服务开关
4.1 通过 menuconfig 配置
打开工程配置菜单:
idf.py menuconfigExample Configuration菜单(定义于 main/Kconfig.projbuild):
Example Configuration --> Advertisement name:设备广播名称,默认BLE_OTS。Kconfig 帮助信息说明其最大长度为 29 个字符;Example Configuration --> Subsequent advertisement data:后续广播数据,默认值为SUB_ADV,用于填充广播包中的制造商/附加数据字段。
BLE Standard Services菜单(定义于 components/bluetooth/ble_services/ots/Kconfig.in):
BLE Standard Services --> GATT Object Transfer Service(即CONFIG_BLE_OTS):总开关,默认通过 sdkconfig.defaults 启用。
启用 OTS 后,还可按需裁剪以下三个可选的 OTS 特征:
| Kconfig 选项 | 默认值 | 作用 |
|---|---|---|
BLE_OTS_FIRST_CREATED_CHARACTERISTIC_ENABLE | y | 是否启用 Object First Created 特征(0x2AC1) |
BLE_OTS_LAST_MODIFIED_CHARACTERISTIC_ENABLE | y | 是否启用 Object Last Modified 特征(0x2AC2) |
BLE_OTS_OBJECT_CHANGE_CHARACTERISTIC_ENABLE | y | 是否启用 Object Change 特征(0x2AC8) |
从 Kconfig 定义可以看出(Kconfig.in),这三个特征均为布尔开关,默认开启。在资源受限的芯片上,可以关闭不需要的特征以减小 GATT 表体积。
4.2 sdkconfig.defaults:默认启用的关键配置
sdkconfig.defaults 中预先开启了四组关键配置,保证开箱即用:
# Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y # 启用蓝牙控制器与主机栈 CONFIG_BT_NIMBLE_ENABLED=y # 使用 NimBLE 作为蓝牙协议栈 CONFIG_BLE_CONN_MGR_ROLE_PERIPHERAL=y # 连接管理器以外围设备(Peripheral)角色运行 CONFIG_BLE_OTS=y # 启用 GATT Object Transfer Service其中:
CONFIG_BT_ENABLED/CONFIG_BT_NIMBLE_ENABLED:覆盖 ESP-IDF 默认配置,启用蓝牙并选择体积更小、适合 SoC 场景的 NimBLE 协议栈;CONFIG_BLE_CONN_MGR_ROLE_PERIPHERAL:示例作为 GATT 服务器(外围设备)运行,故连接管理器配置为 Peripheral 角色;CONFIG_BLE_OTS:将 OTS 标准服务纳入构建。
另外,sdkconfig.ci.nimble 仅保留CONFIG_BT_NIMBLE_ENABLED=y,用于 CI 流水线中针对 NimBLE 配置的专项验证。
5. 应用逻辑源码解析:从启动到事件回调
app_main.c 是示例的全部应用代码,核心流程可拆解为四步。
5.1 应用初始化流程(app_main)
app_main()(app_main.c)按以下顺序完成启动:
- 初始化 NVS:调用
nvs_flash_init();若返回ESP_ERR_NVS_NO_FREE_PAGES或ESP_ERR_NVS_NEW_VERSION_FOUND,则先擦除再重新初始化,保证首次烧录或版本升级时 NVS 分区可用; - 创建默认事件循环:
esp_event_loop_create_default(); - 注册连接管理事件回调:
esp_event_handler_register(BLE_CONN_MGR_EVENTS, ESP_EVENT_ANY_ID, app_ble_conn_event_handler, NULL); - 初始化连接管理器:构造
esp_ble_conn_config_t配置(设备名取CONFIG_EXAMPLE_BLE_ADV_NAME,广播数据取CONFIG_EXAMPLE_BLE_SUB_ADV),调用esp_ble_conn_init(&config); - 初始化 OTS 服务:调用
app_ble_ots_init(); - 启动广播:
esp_ble_conn_start(),失败时依次执行esp_ble_conn_deinit()、esp_ble_ots_deinit()等清理动作并打印错误日志。
5.2 OTS 服务初始化与事件注册
app_ble_ots_init()(app_main.c):
static void app_ble_ots_init(void) { ESP_ERROR_CHECK(esp_ble_ots_init()); ESP_ERROR_CHECK(esp_event_handler_register(BLE_OTS_EVENTS, ESP_EVENT_ANY_ID, app_ble_ots_event_handler, NULL)); }esp_ble_ots_init()负责在 GATT 表中注册 OTS 服务及其全部特征(底层实现见 components/bluetooth/ble_services/ots/src/esp_ots.c)。初始化完成后,应用通过BLE_OTS_EVENTS事件基类订阅 OTS 相关事件。
5.3 OTS 事件处理:Object Name 与 Object Properties
app_ble_ots_event_handler()(app_main.c)处理两类写入事件:
switch (id) { case BLE_OTS_CHR_UUID16_OBJECT_NAME: ESP_LOGI(TAG, "Object Name write event"); break; case BLE_OTS_CHR_UUID16_OBJECT_PROP: recv_obj_prop = (esp_ble_ots_prop_t *)event_data; ESP_LOGI(TAG, "Object prop = 0x%x", recv_obj_prop->delete_prop); break; default: break; }BLE_OTS_CHR_UUID16_OBJECT_NAME(0x2ABE):客户端写入对象名时触发,示例仅打印日志;BLE_OTS_CHR_UUID16_OBJECT_PROP(0x2AC4):客户端写入对象属性时触发,event_data携带esp_ble_ots_prop_t结构体,示例读取其中的delete_prop位段并打印。
5.4 连接事件处理:连接后设置 Object Size
app_ble_conn_event_handler()(app_main.c)监听BLE_CONN_MGR_EVENTS:
ESP_BLE_CONN_EVENT_CONNECTED:客户端连接成功后,调用esp_ble_ots_set_size(&obj_size)设置 Object Size 特征值,失败则打印告警;ESP_BLE_CONN_EVENT_DISCONNECTED:断开连接时打印日志,不做额外处理。
示例声明的 Object Size 特征值(app_main.c)为"已分配 256 字节、当前 0 字节"的空对象:
static esp_ble_ots_size_t obj_size = { .allocated_size = 256, .current_size = 0 };这一设计表明示例在连接建立后即向客户端暴露一个可容纳 256 字节内容的空对象——这正是"基础 OTS 通信验证"的典型行为。
6. 深入 OTS 组件:特征 UUID、操作码与 API 全貌
OTS 组件的公共接口定义在 components/bluetooth/ble_services/ots/include/esp_ots.h,它是理解整个服务的关键。
6.1 服务与特征 UUID 一览
OTS 服务 UUID 为0x1825(BLE_OTS_UUID16),其下包含 12 个特征(esp_ots.h):
| 特征名称 | 16 位 UUID | 宏定义 |
|---|---|---|
| OTS Feature | 0x2ABD | BLE_OTS_CHR_UUID16_OTS_FEATURE |
| Object Name | 0x2ABE | BLE_OTS_CHR_UUID16_OBJECT_NAME |
| Object Type | 0x2ABF | BLE_OTS_CHR_UUID16_OBJECT_TYPE |
| Object Size | 0x2AC0 | BLE_OTS_CHR_UUID16_OBJECT_SIZE |
| Object First Created | 0x2AC1 | BLE_OTS_CHR_UUID16_OBJECT_FIRST_CREATED |
| Object Last Modified | 0x2AC2 | BLE_OTS_CHR_UUID16_OBJECT_LAST_MODIFIED |
| Object ID | 0x2AC3 | BLE_OTS_CHR_UUID16_OBJECT_ID |
| Object Properties | 0x2AC4 | BLE_OTS_CHR_UUID16_OBJECT_PROP |
| Object Action Control Point (OACP) | 0x2AC5 | BLE_OTS_CHR_UUID16_OBJECT_ACTION_CONTROL_POINT |
| Object List Control Point (OLCP) | 0x2AC6 | BLE_OTS_CHR_UUID16_OBJECT_LIST_CONTROL_POINT |
| Object List Filter | 0x2AC7 | BLE_OTS_CHR_UUID16_OBJECT_LIST_FILTER |
| Object Changed | 0x2AC8 | BLE_OTS_CHR_UUID16_OBJECT_CHANGED |
其中BLE_OTS_ATT_VAL_LEN(值为 20,esp_ots.h)定义了特征值属性长度,与经典 BLE ATT 单包最大载荷一致。
6.2 OACP 与 OLCP 操作码定义
虽然示例未实现完整的对象操作,但头文件已完整定义协议层面的操作码,为二次开发预留了接口(esp_ots.h)。
OACP 操作码(写入 0x2AC5):
| 操作码 | 含义 | 宏 | | ------ | ---- | -- | | 0x01 | 创建对象(Create) |BLE_OTS_OACP_CREATE| | 0x02 | 删除对象(Delete) |BLE_OTS_OACP_DELETE| | 0x03 | 计算校验和 |BLE_OTS_OACP_CALCULATE_CHECKSUM| | 0x04 | 执行(Execute) |BLE_OTS_OACP_EXECUTE| | 0x05 | 读(Read) |BLE_OTS_OACP_READ| | 0x06 | 写(Write) |BLE_OTS_OACP_WRITE| | 0x07 | 中止(Abort) |BLE_OTS_OACP_ABORT| | 0x60 | 响应(Response) |BLE_OTS_OACP_RESPONSE|
配套的 OACP 响应码覆盖SUCCESS、NOT_SUPPORT、INVALID_PARAMETER、INSUFFICIENT_RESOURCES、INVALID_OBJECT、CHANNEL_UNAVAILABLE、UNSUPPORT_TYPE、NOT_PERMIT、OBJECT_LOCK、OPERATION_FAIL(0x01~0x0A)。
OLCP 操作码(写入 0x2AC6):FIRST(0x01)、LAST(0x02)、PREVIOUS(0x03)、NEXT(0x04)、GO_TO(0x05)、ORDER(0x06)、REQ_NUM_OF_OBJ(0x07)、CLEAR_MARK(0x08)、RESPONSE(0x70)。排序参数支持按名称/类型/大小/创建时间/修改时间的升序与降序共 10 种(0x01~0x15)。
Object Change 特征标志位(esp_ots.h)使用 5 个 bit 标识变更来源:
| 位 | 含义 | | -- | ---- | | bit0 | Source of Change(变更来源) | | bit1 | Change occurred to the object contents(对象内容变更) | | bit2 | Change occurred to the object metadata(对象元数据变更) | | bit3 | Object Creation(对象创建) | | bit4 | Object Deletion(对象删除) |
6.3 核心数据结构
OTS 组件定义了一批紧凑(packed)结构体,用于与特征值一一对应:
esp_ble_ots_feature_t(esp_ots.h):OTS Feature 特征值,内含oacp(10 个操作支持位)与olcp(4 个操作支持位)两个位段子结构,共 32 bit;esp_ble_ots_size_t(L148-L151):Object Size 特征值,含current_size与allocated_size;esp_ble_ots_utc_t(L156-L163):UTC 时间(年 1582~9999、月 1~12、日 1~31、时 0~23、分/秒 0~59),用于 First Created / Last Modified 特征;esp_ble_ots_id_t(L168-L170):6 字节 Object ID,合法范围 0x000000000100 ~ 0xffffffffffff;esp_ble_ots_prop_t(L175-L184):Object Properties 特征值,8 个属性位(delete/execute/read/write/append/truncate/patch/mark);esp_ble_ots_oacp_t/esp_ble_ots_olcp_t(L189-L200):OACP 与 OLCP 的控制点结构,含操作码与参数区;esp_ble_ots_change_t(L222-L225):Object Change 特征值,含标志位与 6 字节对象 ID。
6.4 公共 API 一览
esp_ots.h为每个特征提供了成对的get/set接口,应用层可在运行时读写这些特征值:
| API | 说明 |
|---|---|
esp_ble_ots_init()/esp_ble_ots_deinit() | 初始化 / 反初始化 OTS 服务 |
esp_ble_ots_get_feature()/esp_ble_ots_set_feature() | 读写 OTS Feature |
esp_ble_ots_get_name()/esp_ble_ots_set_name() | 读写 Object Name |
esp_ble_ots_get_type()/esp_ble_ots_set_type() | 读写 Object Type |
esp_ble_ots_get_size()/esp_ble_ots_set_size() | 读写 Object Size(示例在连接后调用 set) |
esp_ble_ots_get_first_create_time()/esp_ble_ots_set_first_create_time() | 读写 Object First Created |
esp_ble_ots_get_last_modify_time()/esp_ble_ots_set_last_modify_time() | 读写 Object Last Modified |
esp_ble_ots_get_id()/esp_ble_ots_set_id() | 读写 Object ID |
esp_ble_ots_get_prop()/esp_ble_ots_set_prop() | 读写 Object Properties |
esp_ble_ots_get_oacp()/esp_ble_ots_set_oacp(val, need_send) | 读写 OACP,need_send=true时主动推送至客户端 |
esp_ble_ots_get_olcp()/esp_ble_ots_set_olcp(val, need_send) | 读写 OLCP,need_send=true时主动推送 |
esp_ble_ots_get_filter()/esp_ble_ots_set_filter() | 读写 Object List Filter |
esp_ble_ots_get_change()/esp_ble_ots_set_change(val, need_send) | 读写 Object Change,need_send=true时主动推送 |
大多数接口返回ESP_OK表示成功,参数错误返回ESP_ERR_INVALID_ARG,初始化类接口还可能返回ESP_ERR_NO_MEM/ESP_FAIL。
7. 运行结果与验证方式
7.1 预期串口输出
烧录并复位后,示例启动广播,典型串口输出如下(节选自 README.md):
I (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 (420) blecm_nimble: BLE Host Task Started I (420) blecm_nimble: No characteristic(0x2a00) found I (420) blecm_nimble: No characteristic(0x2a01) found I (420) blecm_nimble: No characteristic(0x2a05) found I (430) NimBLE: GAP procedure initiated: stop advertising. I (440) NimBLE: GAP procedure initiated: advertise; I (440) NimBLE: disc_mode=2 I (440) NimBLE: adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=256 adv_itvl_max=256 I (450) NimBLE: I (460) main_task: Returned from app_main()输出要点解读:
BLE_INIT日志确认蓝牙控制器已初始化,Bluetooth MAC打印本机地址;blecm_nimble: No characteristic(0x2a00) found等提示表示连接管理器未在服务中发现 GAP/ATT 基础特征(本示例未注册这些特征,属正常现象);GAP procedure initiated: advertise表示广播已启动,adv_itvl_min=256 / adv_itvl_max=256(单位 0.625 ms,即 160 ms 广播间隔);- 最后
app_main()返回,主任务结束,应用转入事件驱动模式。
7.2 使用通用 BLE 扫描工具验证
由于示例只做基础 OTS 通信演示,使用任何通用 BLE 扫描/调试 App(如 nRF Connect)即可完成验证:
- 扫描到广播名为
BLE_OTS(默认值)的设备并连接; - 在 GATT 服务列表中查找
0x1825服务及其 12 个特征; - 读取 Object Size(0x2AC0),应看到 allocated=256、current=0(连接建立时由
esp_ble_ots_set_size()写入); - 向 Object Name(0x2ABE)写入数据,观察串口输出
Object Name write event; - 向 Object Properties(0x2AC4)写入属性位,观察串口输出
Object prop = 0x...。
8. 从示例到完整 OTS 应用的延伸方向
- 补全 OACP/OLCP 流程:示例仅在头文件中定义了操作码与响应码,未实现对象创建/删除/读写。可在
esp_ble_ots_set_oacp()/esp_ble_ots_set_olcp()的调用链上扩展解析逻辑,并配合 Object Change 特征(esp_ble_ots_set_change(..., true))向客户端推送变更通知; - 结合连接管理器做多端管理:
esp_ble_conn_mgr组件还提供多种连接策略,可在 components/bluetooth/ble_conn_mgr 中查阅; - 参考同目录其他标准服务示例:
examples/bluetooth/ble_services下还有 ANS、BAS、CTS、HRS 等服务示例,可对照学习标准服务组件的接入模式。
如果遇到技术问题,可以在项目仓库的 Issues 中反馈并附上复现日志与芯片型号。本示例以"最小可验证"为原则,是理解 esp-iot-solution 中 BLE 标准服务组件工作原理的绝佳切入点。
- 物联网
- 嵌入式
- 驱动开发
- 硬件开发
【免费下载链接】esp-iot-solution
Espressif IoT Library. IoT Device Drivers, Documentations and Solutions.
相关推荐
esp-iot-solution BLE Object Transfer Service (OTS) 详解:基于 L2CAP CoC 的批量数据传输
esp iot solution BLE Object Transfer Service OTS 详解:基于 L2CAP CoC 的批量数据传输 BLE Obj
物联网嵌入式驱动开发硬件开发ESP IoT Solution BLE 对象传输服务(OTS)实战指南:基于 L2CAP 的批量数据管理与传输
ESP IoT Solution BLE 对象传输服务(OTS)实战指南:基于 L2CAP 的批量数据管理与传输 对象传输服务(Object Transfer
物联网嵌入式驱动开发硬件开发ESP-IoT-Solution BLE Alert Notification Service(ANS)开发指南:基于 esp_ble_conn_mgr 的 GATT 告警服务实现与实战
ESP IoT Solution BLE Alert Notification Service(ANS)开发指南:基于 esp_ble_conn_mgr 的 G
物联网嵌入式驱动开发硬件开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考