Baji_Rtc_Toy/main/bluetooth_provisioning.h

173 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
/**
* @file bluetooth_provisioning.h
* @brief 蓝牙配网模块头文件(基于自定义 GATT Server
*
* 使用自定义 BLE GATT Server 实现配网通讯,
* 采用原始广播数据raw advertising确保手机系统蓝牙可发现。
* 保留完整的 WiFi 配网业务逻辑、状态机和事件回调。
*/
#include <functional>
#include <string>
// 使用条件编译避免IDE环境中的头文件错误
#ifdef ESP_PLATFORM
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_common_api.h"
#include "esp_wifi.h"
#include "esp_event.h"
#else
// 在非ESP环境中定义必要的类型和常量
typedef int esp_event_base_t;
typedef void* wifi_ap_record_t;
#endif
// ============================================================
// 配网协议命令定义 (手机 → 设备, WRITE 特征)
// ============================================================
#define PROV_CMD_SET_SSID 0x01 // 设置 WiFi SSID
#define PROV_CMD_SET_PASSWORD 0x02 // 设置 WiFi 密码
#define PROV_CMD_SET_BSSID 0x03 // 设置 BSSID (6字节)
#define PROV_CMD_CONNECT_AP 0x04 // 请求连接 WiFi
#define PROV_CMD_DISCONNECT_AP 0x05 // 请求断开 WiFi
#define PROV_CMD_GET_WIFI_LIST 0x06 // 请求 WiFi 列表
#define PROV_CMD_DISCONNECT_BLE 0x07 // 请求断开 BLE
#define PROV_CMD_SET_WIFI_MODE 0x08 // 设置 WiFi 模式
#define PROV_CMD_GET_WIFI_STATUS 0x09 // 获取 WiFi 状态
#define PROV_CMD_CUSTOM_DATA 0x10 // 自定义数据
// ============================================================
// 配网协议响应定义 (设备 → 手机, NOTIFY 特征)
// ============================================================
#define PROV_RESP_WIFI_STATUS 0x81 // WiFi 状态: [success(1)][reason(1)]
#define PROV_RESP_WIFI_LIST 0x82 // WiFi 列表: [rssi(1)][ssid_len(1)][ssid...]
#define PROV_RESP_WIFI_LIST_END 0x83 // WiFi 列表结束标记
#define PROV_RESP_CUSTOM_DATA 0x84 // 自定义数据
// ============================================================
// GATT 服务配置
// ============================================================
#define PROV_SERVICE_UUID 0xABF0 // 配网服务 UUID
#define PROV_CHAR_WRITE_UUID 0xABF1 // 写入特征 UUID (手机→设备)
#define PROV_CHAR_NOTIFY_UUID 0xABF2 // 通知特征 UUID (设备→手机)
#define PROV_APP_ID 2 // GATTS App ID
#define PROV_HANDLE_NUM 8 // Service handle 数量
#define PROV_LOCAL_MTU 512 // 本地 MTU
/**
* @brief 蓝牙配网状态枚举
*/
enum class BluetoothProvisioningState {
IDLE, //< 空闲状态,未启动配网
INITIALIZING, //< 初始化中,正在初始化蓝牙和服务
ADVERTISING, //< 广播中,等待手机客户端连接
CONNECTED, //< 已连接,手机客户端已连接到设备
PROVISIONING, //< 配网中正在接收和处理WiFi凭据
SUCCESS, //< 配网成功WiFi连接建立成功
FAILED, //< 配网失败WiFi连接失败或其他错误
STOPPED //< 已停止,配网服务已停止
};
/**
* @brief 蓝牙配网事件类型
*/
enum class BluetoothProvisioningEvent {
STATE_CHANGED, //< 状态改变事件
WIFI_CREDENTIALS, //< 收到WiFi凭据事件
WIFI_CONNECTED, //< WiFi连接成功事件
WIFI_FAILED, //< WiFi连接失败事件
CLIENT_CONNECTED, //< 客户端连接事件
CLIENT_DISCONNECTED //< 客户端断开事件
};
/**
* @brief WiFi凭据结构体
*/
struct WiFiCredentials {
std::string ssid; //< WiFi网络名称SSID
std::string password; //< WiFi网络密码
uint8_t bssid[6]; //< WiFi接入点的MAC地址BSSID
bool bssid_set; //< 是否设置了BSSID
};
/**
* @brief 蓝牙配网事件回调函数类型
*/
using BluetoothProvisioningCallback = std::function<void(BluetoothProvisioningEvent event, void* data)>;
/**
* @brief 蓝牙配网封装类(基于自定义 GATT Server
*
* 使用自定义 BLE GATT Server + 原始广播数据,
* 手机系统蓝牙可直接搜索到设备。保留完整的 WiFi 配网业务逻辑。
*/
class BluetoothProvisioning {
public:
BluetoothProvisioning();
~BluetoothProvisioning();
bool Initialize();
bool Deinitialize();
bool StartProvisioning();
bool StopProvisioning();
BluetoothProvisioningState GetState() const { return state_; }
void SetCallback(BluetoothProvisioningCallback callback) { callback_ = callback; }
const WiFiCredentials& GetWiFiCredentials() const { return wifi_credentials_; }
bool IsClientConnected() const { return client_connected_; }
std::string GetStateString() const;
void ReportWiFiStatus(bool success, uint8_t reason = 0);
void SendWiFiList(const wifi_ap_record_t* ap_list, uint16_t ap_count);
bool SendMacAddressReliably();
void ResetMacSendingState();
private:
BluetoothProvisioningState state_;
BluetoothProvisioningCallback callback_;
WiFiCredentials wifi_credentials_;
bool client_connected_;
bool initialized_;
bool delayed_disconnect_;
bool wifi_connecting_;
bool mac_address_sent_;
static BluetoothProvisioning* instance_;
void SetState(BluetoothProvisioningState new_state);
void TriggerCallback(BluetoothProvisioningEvent event, void* data = nullptr);
#ifdef ESP_PLATFORM
// GATT 相关成员
esp_gatt_if_t gatts_if_ = ESP_GATT_IF_NONE;
uint16_t service_handle_ = 0;
uint16_t write_char_handle_ = 0;
uint16_t notify_char_handle_ = 0;
uint16_t notify_cccd_handle_ = 0;
uint16_t conn_id_ = 0;
bool notify_enabled_ = false;
uint16_t mtu_ = 23;
// BLE 回调
static void GattsEventHandler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param);
static void GapEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param);
void HandleGattsEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t* param);
// GATT 辅助方法
void CreateService(esp_gatt_if_t gatts_if);
void StartAdvertising();
bool SendNotify(const uint8_t* data, uint16_t len);
void ProcessWriteData(const uint8_t* data, uint16_t len);
// WiFi 事件处理
static void WiFiEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
static void IPEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
#endif
BluetoothProvisioning(const BluetoothProvisioning&) = delete;
BluetoothProvisioning& operator=(const BluetoothProvisioning&) = delete;
};