跳转至

BLE扫描器API

本文档引用的文件 - ble_scanner.c - ble_scanner.h - hci_transport.h - config.h - main.c - hci_test_server.c

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构概览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排除指南
  9. 结论
  10. 附录

简介

BLE扫描器组件是一个基于ESP32-S3的蓝牙低功耗网关系统的核心模块,负责通过外部NRF52833控制器进行BLE设备扫描、管理和连接。该组件实现了完整的BLE扫描功能,包括设备发现、扫描控制、设备过滤和状态查询等核心接口。

本组件采用分层架构设计,通过HCI传输层与外部BLE控制器通信,内部维护设备列表和连接状态,并提供丰富的回调机制来通知上层应用设备状态变化。

项目结构

BLE扫描器组件位于项目的old_version/components/ble_scanner目录下,主要包含以下文件:

graph TB
subgraph "BLE扫描器组件"
A[ble_scanner.c<br/>主实现文件]
B[ble_scanner.h<br/>接口定义文件]
end
subgraph "相关头文件"
C[hci_transport.h<br/>HCI传输层接口]
D[config.h<br/>配置常量定义]
E[main.h<br/>主程序入口]
end
subgraph "测试工具"
F[hci_test_server.c<br/>HCI测试服务器]
end
A --> B
A --> C
A --> D
E --> A
F --> C

图表来源 - ble_scanner.c - ble_scanner.h

章节来源 - ble_scanner.c - ble_scanner.h

核心组件

BLE扫描器组件由多个核心组件构成,每个组件都有明确的职责分工:

数据结构组件

组件使用多种数据结构来管理BLE设备信息和扫描参数:

  • 设备信息结构体: 存储单个BLE设备的完整信息
  • 扫描参数结构体: 配置BLE扫描行为
  • 设备过滤器结构体: 定义设备筛选条件
  • 连接信息结构体: 跟踪当前BLE连接状态

回调机制组件

组件提供了两种类型的回调机制:

  • 设备发现回调: 当新设备被发现时触发
  • 连接状态回调: 当BLE连接状态发生变化时触发

扫描控制组件

组件实现了完整的BLE扫描控制功能:

  • 初始化/去初始化: 设置硬件和配置参数
  • 启动/停止扫描: 控制扫描生命周期
  • 参数配置: 动态调整扫描行为
  • 设备管理: 维护设备列表和状态

章节来源 - ble_scanner.h - ble_scanner.c

架构概览

BLE扫描器采用分层架构设计,确保了良好的模块化和可维护性:

graph TB
subgraph "应用层"
A[主应用程序<br/>main.c]
B[WebUI服务器<br/>webui_server.c]
C[MQTT客户端<br/>mqtt_client_wrapper.c]
end
subgraph "BLE扫描器层"
D[BLE扫描器<br/>ble_scanner.c]
E[设备管理<br/>设备列表/过滤]
F[连接管理<br/>连接状态跟踪]
end
subgraph "传输层"
G[HCI传输层<br/>hci_transport.c]
H[UART通信<br/>NRF52833控制器]
end
subgraph "硬件层"
I[ESP32-S3主控制器]
J[NRF52833外部BLE控制器]
end
A --> D
B --> D
C --> D
D --> E
D --> F
D --> G
G --> H
H --> I
H --> J

图表来源 - main.c - ble_scanner.c - hci_transport.h

详细组件分析

设备发现与管理

BLE扫描器的核心功能是发现和管理BLE设备。系统通过以下机制实现:

广告数据解析

组件能够解析BLE设备的广告数据,提取关键信息:

flowchart TD
A[接收广告数据] --> B{数据长度有效?}
B --> |否| C[忽略数据]
B --> |是| D[解析数据字段]
D --> E{找到名称字段?}
E --> |是| F[提取设备名称]
E --> |否| G[继续解析其他字段]
F --> H[更新设备信息]
G --> H
H --> I[检查过滤条件]
I --> J{通过过滤?}
J --> |是| K[触发设备回调]
J --> |否| L[忽略设备]
K --> M[更新设备列表]
L --> M
M --> N[更新最后出现时间]

图表来源 - ble_scanner.c - ble_scanner.c

设备列表管理

系统维护一个固定大小的设备列表,支持动态添加、更新和清理:

  • 最大设备数量: 100个设备
  • 自动清理: 超过60秒未出现的设备会被移除
  • 线程安全: 使用互斥锁保护设备列表访问
  • 重复过滤: 可选择过滤重复的广告包

章节来源 - ble_scanner.c - config.h

扫描控制接口

BLE扫描器提供了完整的扫描控制API:

初始化和去初始化

sequenceDiagram
participant App as 应用程序
participant Scanner as BLE扫描器
participant Transport as HCI传输层
participant Controller as NRF52833控制器
App->>Scanner : ble_scanner_init()
Scanner->>Transport : 注册事件回调
Scanner->>Transport : 发送设置事件掩码命令
Transport->>Controller : HCI_Set_Event_Mask
Controller-->>Transport : 命令完成事件
Scanner->>Transport : 发送LE事件掩码命令
Transport->>Controller : HCI_LE_Set_Event_Mask
Controller-->>Transport : 命令完成事件
Scanner->>Transport : 发送随机地址命令
Transport->>Controller : HCI_LE_Set_Random_Address
Controller-->>Transport : 命令完成事件
Scanner-->>App : 初始化完成

图表来源 - ble_scanner.c - hci_transport.h

扫描参数配置

扫描参数通过ble_scan_params_t结构体配置:

参数 类型 描述 默认值
scan_interval uint16_t 扫描间隔(0.625ms单位) 0x0050 (50ms)
scan_window uint16_t 扫描窗口(0.625ms单位) 0x0030 (30ms)
scan_type uint8_t 扫描类型(0=被动,1=主动) 0x01 (主动)
filter_policy uint8_t 过滤策略 0x00 (接受所有)
filter_duplicates bool 是否过滤重复 true

章节来源 - ble_scanner.h - config.h

设备过滤机制

BLE扫描器支持多维度的设备过滤:

flowchart TD
A[设备到达] --> B[RSSI过滤]
B --> C{RSSI >= 阈值?}
C --> |否| D[拒绝设备]
C --> |是| E[名称过滤]
E --> F{名称匹配?}
F --> |否| D
F --> |是| G[MAC地址过滤]
G --> H{MAC匹配?}
H --> |否| D
H --> |是| I[接受设备]
D --> J[设备被拒绝]
I --> K[触发回调]
K --> L[更新设备列表]

图表来源 - ble_scanner.c

过滤器配置通过ble_device_filter_t结构体实现:

字段 类型 描述
name_filter char[] 名称包含过滤字符串
rssi_filter int8_t 最小RSSI阈值
mac_filter uint8_t[6] MAC地址过滤
mac_filter_enabled bool 是否启用MAC过滤

章节来源 - ble_scanner.h

连接管理功能

BLE扫描器不仅支持扫描,还提供了基本的BLE连接管理:

连接状态管理

连接状态通过ble_conn_state_t枚举管理:

stateDiagram-v2
[*] --> 断开连接
断开连接 --> 连接中 : ble_scanner_connect()
连接中 --> 已连接 : 连接成功事件
连接中 --> 断开连接 : 连接失败事件
已连接 --> 断开连接 : disconnect() 或断开事件

图表来源 - ble_scanner.h

连接参数配置

连接参数通过ble_connection_t结构体跟踪:

字段 类型 描述
conn_handle uint16_t 连接句柄
peer_addr uint8_t[6] 对端设备地址
peer_addr_type uint8_t 对端地址类型
state ble_conn_state_t 当前连接状态
conn_interval uint16_t 连接间隔
conn_latency uint16_t 连接延迟
supervision_timeout uint16_t 监督超时

章节来源 - ble_scanner.h

回调机制与事件处理

BLE扫描器提供了灵活的回调机制来通知上层应用状态变化:

设备发现回调

当新设备被发现且通过过滤条件时,会触发设备发现回调:

sequenceDiagram
participant Controller as BLE控制器
participant Scanner as BLE扫描器
participant Callback as 用户回调
participant App as 应用程序
Controller->>Scanner : LE_Advertising_Report事件
Scanner->>Scanner : 解析广告数据
Scanner->>Scanner : 检查过滤条件
alt 设备通过过滤
Scanner->>Callback : 调用设备回调
Callback->>App : 处理设备信息
else 设备被拒绝
Scanner->>Scanner : 忽略设备
end

图表来源 - ble_scanner.c

连接状态回调

连接状态变化时触发连接状态回调:

sequenceDiagram
participant Controller as BLE控制器
participant Scanner as BLE扫描器
participant ConnCallback as 连接回调
participant App as 应用程序
Controller->>Scanner : LE_Connection_Complete事件
Scanner->>Scanner : 更新连接状态
Scanner->>ConnCallback : 调用连接回调
ConnCallback->>App : 处理连接状态

图表来源 - ble_scanner.c

章节来源 - ble_scanner.h - ble_scanner.h

依赖关系分析

BLE扫描器组件的依赖关系清晰明确,遵循了良好的软件工程原则:

graph TB
subgraph "外部依赖"
A[ESP-IDF框架]
B[FREERTOS]
C[ESP_LOG宏]
end
subgraph "组件内部依赖"
D[ble_scanner.c]
E[ble_scanner.h]
F[hci_transport.h]
G[config.h]
end
subgraph "硬件依赖"
H[ESP32-S3主控制器]
I[NRF52833外部BLE控制器]
J[UART接口]
end
D --> E
D --> F
D --> G
E --> F
E --> G
D --> A
D --> B
D --> C
F --> H
F --> J
F --> I

图表来源 - ble_scanner.c - hci_transport.h

关键依赖说明

  1. ESP-IDF框架: 提供底层硬件抽象和系统服务
  2. FreeRTOS: 提供任务调度和同步原语
  3. HCI传输层: 抽象了与BLE控制器的通信协议
  4. 配置常量: 定义了硬件特性和运行参数

章节来源 - ble_scanner.c - config.h

性能考虑

BLE扫描器在设计时充分考虑了性能优化:

内存管理

  • 静态分配: 设备列表使用静态数组,避免动态内存分配带来的碎片化
  • 固定大小: 最大设备数量限制为100个,确保内存使用可预测
  • 自动清理: 超时设备自动移除,防止内存泄漏

扫描效率

  • 重复过滤: 启用重复过滤减少不必要的回调触发
  • 批量处理: 设备列表操作使用互斥锁保护,避免竞态条件
  • 异步处理: 通过回调机制实现非阻塞的事件处理

资源优化

  • 线程安全: 使用互斥锁保护共享资源
  • 最小化阻塞: 扫描操作非阻塞,不影响其他任务执行
  • 硬件优化: 利用外部BLE控制器减轻主控制器负担

故障排除指南

常见问题及解决方案

扫描无法启动

症状: 调用ble_scanner_start()返回错误

可能原因: 1. HCI传输层未正确初始化 2. 设备处于已连接状态 3. 扫描参数配置无效

解决方法:

// 检查初始化状态
if (ble_scanner_init() != ESP_OK) {
    ESP_LOGE(TAG, "BLE扫描器初始化失败");
    return;
}

// 确保设备处于断开连接状态
ble_connection_t conn;
if (ble_scanner_get_connection(&conn) == ESP_OK) {
    if (conn.state == BLE_CONN_STATE_CONNECTED) {
        ble_scanner_disconnect(0);
    }
}

// 启动扫描
if (ble_scanner_start() != ESP_OK) {
    ESP_LOGE(TAG, "BLE扫描启动失败");
}

设备过滤不生效

症状: 设置过滤器后仍能收到不符合条件的设备

可能原因: 1. 过滤器配置未正确设置 2. 设备名称解析失败 3. 回调函数未正确注册

解决方法:

// 正确设置过滤器
ble_device_filter_t filter = {0};
strcpy(filter.name_filter, "MyDevice");
filter.rssi_filter = -80;  // 设置RSSI阈值
filter.mac_filter_enabled = false;

if (ble_scanner_set_filter(&filter) != ESP_OK) {
    ESP_LOGE(TAG, "设置过滤器失败");
}

内存不足错误

症状: ESP_ERR_NO_MEM错误

可能原因: 1. 设备列表已满 2. 互斥锁创建失败 3. 内存碎片化

解决方法:

// 清理设备列表
ble_scanner_clear_devices();

// 检查可用内存
ESP_LOGI(TAG, "可用堆内存: %lu bytes", esp_get_free_heap_size());

// 重新初始化
ble_scanner_deinit();
ble_scanner_init();

章节来源 - ble_scanner.c - ble_scanner.c

结论

BLE扫描器组件是一个功能完整、设计合理的嵌入式BLE管理模块。它通过清晰的分层架构、完善的API设计和高效的实现方式,为ESP32-S3 BLE网关系统提供了强大的BLE设备管理能力。

组件的主要优势包括: - 模块化设计: 良好的职责分离和接口抽象 - 性能优化: 静态内存分配和高效的算法实现 - 易用性: 直观的API和丰富的回调机制 - 可靠性: 完善的错误处理和状态管理

对于开发者而言,该组件提供了清晰的扩展点和良好的集成接口,可以轻松地集成到各种BLE应用场景中。

附录

API参考表

设备发现相关API

函数名 参数 返回值 描述
ble_scanner_init() esp_err_t 初始化BLE扫描器
ble_scanner_deinit() esp_err_t 去初始化BLE扫描器
ble_scanner_start() esp_err_t 开始BLE扫描
ble_scanner_stop() esp_err_t 停止BLE扫描
ble_scanner_register_callback() ble_device_callback_t esp_err_t 注册设备回调

设备管理相关API

函数名 参数 返回值 描述
ble_scanner_get_devices() ble_device_t[], uint8_t, uint8_t* esp_err_t 获取设备列表
ble_scanner_clear_devices() esp_err_t 清空设备列表
ble_scanner_get_device_count() uint8_t 获取设备数量
ble_scanner_is_running() bool 检查扫描状态

连接管理相关API

函数名 参数 返回值 描述
ble_scanner_connect() uint8_t*, uint8_t esp_err_t 连接到BLE设备
ble_scanner_disconnect() uint16_t esp_err_t 断开BLE连接
ble_scanner_get_connection() ble_connection_t* esp_err_t 获取连接信息
ble_scanner_register_conn_callback() ble_conn_callback_t void 注册连接回调

错误码定义

BLE扫描器使用标准的ESP-IDF错误码:

  • ESP_OK: 操作成功
  • ESP_ERR_INVALID_ARG: 参数无效
  • ESP_ERR_INVALID_STATE: 状态无效
  • ESP_ERR_NO_MEM: 内存不足
  • ESP_ERR_NOT_FOUND: 未找到目标
  • ESP_ERR_TIMEOUT: 操作超时

使用示例

以下是一个完整的BLE扫描器使用示例:

// 初始化BLE扫描器
if (ble_scanner_init() != ESP_OK) {
    ESP_LOGE(TAG, "BLE扫描器初始化失败");
    return;
}

// 设置设备过滤器
ble_device_filter_t filter = {0};
strcpy(filter.name_filter, "MyDevice");
filter.rssi_filter = -80;
ble_scanner_set_filter(&filter);

// 注册回调函数
ble_scanner_register_callback(on_device_found);

// 开始扫描
ble_scanner_start();

// 主循环
while (1) {
    // 获取设备列表
    ble_device_t devices[MAX_DEVICES];
    uint8_t count;
    if (ble_scanner_get_devices(devices, MAX_DEVICES, &count) == ESP_OK) {
        for (int i = 0; i < count; i++) {
            printf("设备: %s (RSSI: %d)\n", devices[i].name, devices[i].rssi);
        }
    }
    vTaskDelay(pdMS_TO_TICKS(1000));
}

章节来源 - main.c - main.c