# BLE 配网组件
这是一个用于 ESP32-S3 的 BLE (Bluetooth Low Energy) 配网组件,基于 ESP-IDF 开发。它允许用户通过蓝牙连接配置设备的 WiFi 网络,并支持简单的指令交互和状态查询。
## 功能特性
* **双模式配网**:优先尝试连接已保存的 WiFi,失败后自动进入 BLE 配网模式。
* **WiFi 连接管理**:
* 自动重连机制(每轮 5 次,共 3 轮)。
* 支持 WiFi 凭据的 NVS 存储、查询和删除。
* **BLE 交互**:
* 提供标准的 GATT Server 服务。
* 基于 JSON 的指令协议(连接、扫描、配网、重启等)。
* 支持状态通知(Notify)。
* 可配置 WiFi 连接后是否保持 BLE 开启。
* **扩展性**:
* 提供 Python 上位机测试工具。
* 预留重启前的 Hook 函数,方便二次开发。
## 目录结构
```
ble_provisioning/
├── include/
│ └── ble_provisioning.h # 对外公共接口
├── src/
│ ├── ble_provisioning.c # 核心配网逻辑
│ ├── ble_gatts_module.c # BLE GATT Server 实现
│ ├── ble_gatts_module.h # BLE 模块内部头文件
│ ├── ble_proto_parser.c # 协议解析与指令处理
│ ├── ble_proto_parser.h # 协议解析器头文件
│ ├── wifi_driver.c # WiFi 驱动封装
│ └── wifi_driver.h # WiFi 驱动头文件
├── python_tool/ # Python 上位机测试工具
│ ├── ble_test.py # 测试脚本
│ ├── requirements.txt # 依赖库
│ └── README.md # 上位机使用说明
├── CMakeLists.txt # 构建脚本
├── PROTOCOL.md # 通信协议文档
└── README.md # 组件说明文档
```
## 作为依赖引入
### 方式 A:从 Git 仓库(推荐用于开发)
在项目 `main/idf_component.yml`(或任意需要依赖它的组件清单)中添加:
```yaml
dependencies:
ble_provisioning:
git: "https://github.com/dxbsw/ble_provisioning.git"
version: "v1.0.1"
```
### 方式 B:从组件中心(发布后使用)
```yaml
dependencies:
dxbsw/ble_provisioning:
version: "^1.0.1"
```
## 依赖 (Dependencies)
本组件依赖以下 ESP-IDF 组件(构建系统会自动处理):
* `nvs_flash`: 用于存储 WiFi 凭据。
* `bt`: 蓝牙协议栈 (Bluedroid)。
* `esp_wifi`: WiFi 驱动。
* `json`: cJSON 库,用于协议解析。
## 配置与使用
### 1. 必需的 SDK 配置 (`sdkconfig`)
在使用本组件前,必须在 `sdkconfig` 中开启蓝牙支持。请运行 `idf.py menuconfig` 并确保以下选项已启用:
* **Component config -> Bluetooth**:
* [x] `Bluetooth`
* [x] `Bluedroid Options` -> `Include BLE 4.2 features` (或者确保 `CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y`)
* *注意:本组件使用了传统的 BLE 广播 API,因此必须开启 BLE 4.2 特性支持。*
* **Partition Table**:
* 建议使用自定义分区表,确保 App 分区足够大(蓝牙协议栈占用较大空间)。
* 建议 `factory` 分区至少 2MB,或使用 `partitions.csv` 配置更大的 `ota_0` 分区。
### 2. 代码集成
在您的 `main` 函数中初始化组件:
```c
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ble_provisioning.h"
#include "wifi_driver.h"
void app_main(void)
{
// 定义配置
ble_prov_config_t config = {
.device_name = "ESP32-S3-TEXT", // 自定义蓝牙广播名称
};
// 初始化 BLE 配网组件
// 这会自动初始化 NVS、WiFi,并根据情况启动连接或配网
esp_err_t err = ble_provisioning_init(&config);
if (err != ESP_OK) {
// 错误处理
}
// 等待 wifi 连接完成(可选)
while (!wifi_driver_is_connected()) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
```
### 3. 自定义配置
#### 3.1 WiFi 连接后保持 BLE
在 `include/ble_provisioning.h` 中,可以通过修改宏定义来决定 WiFi 连接成功后是否保持蓝牙开启:
```c
// 1: 保持开启(默认),允许后续通过蓝牙控制
// 0: 关闭蓝牙以省电
#define BLE_KEEP_ALIVE_AFTER_WIFI_CONNECTED 1
```
#### 3.2 重启钩子 (Hook)
组件在执行重启指令前预留了 Hook 函数。您可以在自己的代码(如 `main.c`)中重新实现该函数,以执行自定义的清理工作(如保存数据、关闭外设):
```c
// 在您的代码中覆盖此函数
void pre_restart_hook(void) {
ESP_LOGI("APP", "设备即将重启,正在保存数据...");
// save_user_data();
// disable_peripherals();
}
```
## 注意事项
1. **UUID 匹配**:
* 上位机(Python 脚本或手机 App)使用的 UUID 必须与固件中 `ble_gatts_module.c` 定义的 UUID 一致。
* 默认 UUID:
* Service: `00000001-0000-1000-8000-00805F9B34FB`
* Write: `00000002-0000-1000-8000-00805F9B34FB`
* Notify: `00000003-0000-1000-8000-00805F9B34FB`
2. **句柄数量 (`GATTS_NUM_HANDLE_TEST_A`)**:
* 在 `ble_gatts_module.c` 中,宏 `GATTS_NUM_HANDLE_TEST_A` 定义了服务的最大句柄数。
* 当前定义为 **8**,足以支持当前的 Service + 2 Characteristics + 1 Descriptor。
* 如果您添加了新的特征值,务必增加此数值,否则新特征值将无法添加。
3. **分区表大小**:
* 启用蓝牙和 WiFi 栈后,固件体积会显著增加(通常 >1MB)。
* 请确保分区表中的 APP 分区足够大(建议至少 1.5MB 或 2MB),否则会出现 `app partition is too small` 编译错误。
4. **MTU 限制**:
* 默认 BLE MTU 较小(23 字节)。虽然组件设置了本地 MTU 为 500,但实际传输大小取决于手机/上位机的协商结果。
* 发送长 JSON 响应时,建议上位机先请求增大 MTU,或在应用层进行分包处理(当前组件通过 Notify 直接发送,如果超过 MTU 可能会被截断)。
## 测试工具
组件附带了一个 Python 上位机脚本,位于 `python_tool/` 目录下。它可以模拟手机 App 进行全功能的配网和控制测试。详细使用说明请参考该目录下的 `README.md`。
idf.py add-dependency "dxbsw/ble_provisioning^1.0.3"