ESP32 BLE Object Transfer Service(OTS)服务端示例详解:基于 esp-iot-solution 实现对象传输服务的 GATT 服务器
2026/9/19 17:42:55 网站建设 项目流程
  • 物联网
  • 嵌入式
  • 驱动开发
  • 硬件开发

【免费下载链接】esp-iot-solution

Espressif IoT Library. IoT Device Drivers, Documentations and Solutions.

项目地址:https://gitcode.com/GitHub_Trending/es/esp-iot-solution
点击查看免费下载

本指南以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):

支持的芯片ESP32ESP32-C3ESP32-C2ESP32-S3ESP32-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 可以看到,应用层直接依赖btnvs_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 menuconfig

Example 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_ENABLEy是否启用 Object First Created 特征(0x2AC1)
BLE_OTS_LAST_MODIFIED_CHARACTERISTIC_ENABLEy是否启用 Object Last Modified 特征(0x2AC2)
BLE_OTS_OBJECT_CHANGE_CHARACTERISTIC_ENABLEy是否启用 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)按以下顺序完成启动:

  1. 初始化 NVS:调用nvs_flash_init();若返回ESP_ERR_NVS_NO_FREE_PAGESESP_ERR_NVS_NEW_VERSION_FOUND,则先擦除再重新初始化,保证首次烧录或版本升级时 NVS 分区可用;
  2. 创建默认事件循环esp_event_loop_create_default()
  3. 注册连接管理事件回调esp_event_handler_register(BLE_CONN_MGR_EVENTS, ESP_EVENT_ANY_ID, app_ble_conn_event_handler, NULL)
  4. 初始化连接管理器:构造esp_ble_conn_config_t配置(设备名取CONFIG_EXAMPLE_BLE_ADV_NAME,广播数据取CONFIG_EXAMPLE_BLE_SUB_ADV),调用esp_ble_conn_init(&config)
  5. 初始化 OTS 服务:调用app_ble_ots_init()
  6. 启动广播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 为0x1825BLE_OTS_UUID16),其下包含 12 个特征(esp_ots.h):

特征名称16 位 UUID宏定义
OTS Feature0x2ABDBLE_OTS_CHR_UUID16_OTS_FEATURE
Object Name0x2ABEBLE_OTS_CHR_UUID16_OBJECT_NAME
Object Type0x2ABFBLE_OTS_CHR_UUID16_OBJECT_TYPE
Object Size0x2AC0BLE_OTS_CHR_UUID16_OBJECT_SIZE
Object First Created0x2AC1BLE_OTS_CHR_UUID16_OBJECT_FIRST_CREATED
Object Last Modified0x2AC2BLE_OTS_CHR_UUID16_OBJECT_LAST_MODIFIED
Object ID0x2AC3BLE_OTS_CHR_UUID16_OBJECT_ID
Object Properties0x2AC4BLE_OTS_CHR_UUID16_OBJECT_PROP
Object Action Control Point (OACP)0x2AC5BLE_OTS_CHR_UUID16_OBJECT_ACTION_CONTROL_POINT
Object List Control Point (OLCP)0x2AC6BLE_OTS_CHR_UUID16_OBJECT_LIST_CONTROL_POINT
Object List Filter0x2AC7BLE_OTS_CHR_UUID16_OBJECT_LIST_FILTER
Object Changed0x2AC8BLE_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 响应码覆盖SUCCESSNOT_SUPPORTINVALID_PARAMETERINSUFFICIENT_RESOURCESINVALID_OBJECTCHANNEL_UNAVAILABLEUNSUPPORT_TYPENOT_PERMITOBJECT_LOCKOPERATION_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_sizeallocated_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)即可完成验证:

  1. 扫描到广播名为BLE_OTS(默认值)的设备并连接;
  2. 在 GATT 服务列表中查找0x1825服务及其 12 个特征;
  3. 读取 Object Size(0x2AC0),应看到 allocated=256、current=0(连接建立时由esp_ble_ots_set_size()写入);
  4. 向 Object Name(0x2ABE)写入数据,观察串口输出Object Name write event
  5. 向 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.

项目地址:https://gitcode.com/GitHub_Trending/es/esp-iot-solution
点击查看免费下载

相关推荐

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询