feat: 添加 BLE 管理功能与配置
- 新增 ble_manager.c 和 ble_manager.h 文件,提供 BLE 初始化和管理功能 - 更新 CMakeLists.txt,包含 ble_manager.c 以支持 BLE 功能 - 在 sdkconfig.defaults 中启用 BLE 和相关配置 - 更新 app_main.c,初始化 BLE 管理器 - 在 Kconfig.projbuild 中添加 BLE 设备名称配置选项 - 更新 board_config.h,定义 BLE 启用标志
This commit is contained in:
Vendored
+1
@@ -6,6 +6,7 @@
|
|||||||
],
|
],
|
||||||
"idf.port": "/dev/ttyACM0",
|
"idf.port": "/dev/ttyACM0",
|
||||||
"idf.currentSetup": "C:\\esp\\v6.0.1\\esp-idf",
|
"idf.currentSetup": "C:\\esp\\v6.0.1\\esp-idf",
|
||||||
|
"idf.pythonInstallPath": "C:\\Espressif\\tools\\python\\v6.0.1\\venv\\Scripts\\python.exe",
|
||||||
"idf.customExtraVars": {
|
"idf.customExtraVars": {
|
||||||
"IDF_TARGET": "esp32s3"
|
"IDF_TARGET": "esp32s3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ idf_component_register(SRCS
|
|||||||
"bsp/lvgl_port.c"
|
"bsp/lvgl_port.c"
|
||||||
"bsp/boot_button.c"
|
"bsp/boot_button.c"
|
||||||
"services/wifi_manager.c"
|
"services/wifi_manager.c"
|
||||||
|
"services/ble_manager.c"
|
||||||
"ui/ui.c"
|
"ui/ui.c"
|
||||||
"ui/ui_helpers.c"
|
"ui/ui_helpers.c"
|
||||||
"ui/screens/ui_Screen1.c"
|
"ui/screens/ui_Screen1.c"
|
||||||
"ui/screens/ui_Screen2.c"
|
"ui/screens/ui_Screen2.c"
|
||||||
"ui/widgets/ui_comp_hook.c"
|
"ui/widgets/ui_comp_hook.c"
|
||||||
PRIV_REQUIRES
|
PRIV_REQUIRES
|
||||||
|
bt
|
||||||
esp_wifi
|
esp_wifi
|
||||||
esp_netif
|
esp_netif
|
||||||
nvs_flash
|
nvs_flash
|
||||||
|
|||||||
@@ -66,4 +66,10 @@ menu "Example Configuration"
|
|||||||
bool "WAPI PSK"
|
bool "WAPI PSK"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config ESP_BLE_DEVICE_NAME
|
||||||
|
string "BLE device name"
|
||||||
|
default "HeavenlyHeroStar"
|
||||||
|
help
|
||||||
|
GAP device name advertised over BLE.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "ui_handlers.h"
|
#include "ui_handlers.h"
|
||||||
#include "wifi_manager.h"
|
#include "wifi_manager.h"
|
||||||
|
#include "ble_manager.h"
|
||||||
|
|
||||||
static const char *TAG = "app";
|
static const char *TAG = "app";
|
||||||
|
|
||||||
@@ -40,4 +41,7 @@ void app_main(void)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Starting WiFi");
|
ESP_LOGI(TAG, "Starting WiFi");
|
||||||
wifi_manager_init();
|
wifi_manager_init();
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Starting BLE");
|
||||||
|
ble_manager_init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
#define BOARD_PIN_KEY 4
|
#define BOARD_PIN_KEY 4
|
||||||
#define BOARD_PIN_LED 16
|
#define BOARD_PIN_LED 16
|
||||||
|
|
||||||
|
/* BLE (ESP32-S3 built-in radio) */
|
||||||
|
#define BOARD_BLE_ENABLED 1
|
||||||
|
|
||||||
/* LVGL port */
|
/* LVGL port */
|
||||||
#define BOARD_LVGL_DRAW_BUF_LINES 20
|
#define BOARD_LVGL_DRAW_BUF_LINES 20
|
||||||
#define BOARD_LVGL_TICK_PERIOD_MS 2
|
#define BOARD_LVGL_TICK_PERIOD_MS 2
|
||||||
|
|||||||
@@ -0,0 +1,271 @@
|
|||||||
|
#include "ble_manager.h"
|
||||||
|
|
||||||
|
#include "board_config.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if BOARD_BLE_ENABLED
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "host/ble_uuid.h"
|
||||||
|
#include "host/util/util.h"
|
||||||
|
#include "nimble/nimble_port.h"
|
||||||
|
#include "nimble/nimble_port_freertos.h"
|
||||||
|
#include "services/gap/ble_svc_gap.h"
|
||||||
|
#include "services/gatt/ble_svc_gatt.h"
|
||||||
|
#include "store/config/ble_store_config.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define BLE_DEVICE_NAME CONFIG_ESP_BLE_DEVICE_NAME
|
||||||
|
|
||||||
|
#define HHS_SVC_UUID16 0xFFF0
|
||||||
|
#define HHS_CHR_UUID16 0xFFF1
|
||||||
|
|
||||||
|
static const char *TAG = "ble_manager";
|
||||||
|
|
||||||
|
static ble_status_cb_t s_status_cb;
|
||||||
|
static bool s_connected;
|
||||||
|
static uint8_t s_own_addr_type;
|
||||||
|
static uint16_t s_conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
|
||||||
|
static uint8_t s_chr_val[20] = "HeavenlyHeroStar";
|
||||||
|
static uint16_t s_chr_val_handle;
|
||||||
|
static const ble_uuid16_t s_hhs_svc_uuid = BLE_UUID16_INIT(HHS_SVC_UUID16);
|
||||||
|
static const ble_uuid16_t s_hhs_chr_uuid = BLE_UUID16_INIT(HHS_CHR_UUID16);
|
||||||
|
|
||||||
|
static void start_advertising(void);
|
||||||
|
static int gap_event_handler(struct ble_gap_event *event, void *arg);
|
||||||
|
|
||||||
|
static int chr_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
|
struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
if (attr_handle != s_chr_val_handle) {
|
||||||
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ctxt->op) {
|
||||||
|
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||||
|
return os_mbuf_append(ctxt->om, s_chr_val, sizeof(s_chr_val)) == 0
|
||||||
|
? 0
|
||||||
|
: BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||||
|
|
||||||
|
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
|
||||||
|
uint16_t len = OS_MBUF_PKTLEN(ctxt->om);
|
||||||
|
if (len > sizeof(s_chr_val)) {
|
||||||
|
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
}
|
||||||
|
memset(s_chr_val, 0, sizeof(s_chr_val));
|
||||||
|
int rc = ble_hs_mbuf_to_flat(ctxt->om, s_chr_val, sizeof(s_chr_val), NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "characteristic write from conn=%d, len=%u", conn_handle, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BLE_ATT_ERR_UNLIKELY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ble_gatt_svc_def s_gatt_svcs[] = {
|
||||||
|
{
|
||||||
|
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||||
|
.uuid = &s_hhs_svc_uuid.u,
|
||||||
|
.characteristics =
|
||||||
|
(struct ble_gatt_chr_def[]){
|
||||||
|
{
|
||||||
|
.uuid = &s_hhs_chr_uuid.u,
|
||||||
|
.access_cb = chr_access,
|
||||||
|
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
|
||||||
|
.val_handle = &s_chr_val_handle,
|
||||||
|
},
|
||||||
|
{0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void notify_status(bool connected)
|
||||||
|
{
|
||||||
|
s_connected = connected;
|
||||||
|
gpio_set_level(BOARD_PIN_LED, connected ? 1 : 0);
|
||||||
|
if (s_status_cb != NULL) {
|
||||||
|
s_status_cb(connected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_advertising(void)
|
||||||
|
{
|
||||||
|
struct ble_hs_adv_fields fields = {0};
|
||||||
|
struct ble_gap_adv_params adv_params = {0};
|
||||||
|
const char *name = ble_svc_gap_device_name();
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||||
|
fields.name = (uint8_t *)name;
|
||||||
|
fields.name_len = strlen(name);
|
||||||
|
fields.name_is_complete = 1;
|
||||||
|
|
||||||
|
rc = ble_gap_adv_set_fields(&fields);
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "failed to set advertising data: %d", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||||
|
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||||
|
|
||||||
|
rc = ble_gap_adv_start(s_own_addr_type, NULL, BLE_HS_FOREVER, &adv_params,
|
||||||
|
gap_event_handler, NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "failed to start advertising: %d", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "advertising as \"%s\"", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gap_event_handler(struct ble_gap_event *event, void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
switch (event->type) {
|
||||||
|
case BLE_GAP_EVENT_CONNECT:
|
||||||
|
if (event->connect.status == 0) {
|
||||||
|
s_conn_handle = event->connect.conn_handle;
|
||||||
|
ESP_LOGI(TAG, "connected, handle=%d", s_conn_handle);
|
||||||
|
notify_status(true);
|
||||||
|
} else {
|
||||||
|
ESP_LOGW(TAG, "connection failed, status=%d", event->connect.status);
|
||||||
|
start_advertising();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_DISCONNECT:
|
||||||
|
ESP_LOGI(TAG, "disconnected, reason=%d", event->disconnect.reason);
|
||||||
|
s_conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
notify_status(false);
|
||||||
|
start_advertising();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||||
|
start_advertising();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_stack_sync(void)
|
||||||
|
{
|
||||||
|
int rc = ble_hs_util_ensure_addr(0);
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "no available BT address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ble_hs_id_infer_auto(0, &s_own_addr_type);
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "failed to infer address type: %d", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_advertising();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_stack_reset(int reason)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "nimble stack reset, reason=%d", reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
|
||||||
|
{
|
||||||
|
(void)ctxt;
|
||||||
|
(void)arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gatt_svc_init(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
ble_svc_gatt_init();
|
||||||
|
rc = ble_gatts_count_cfg(s_gatt_svcs);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ble_gatts_add_svcs(s_gatt_svcs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_store_config_init(void);
|
||||||
|
|
||||||
|
static void nimble_host_task(void *param)
|
||||||
|
{
|
||||||
|
(void)param;
|
||||||
|
nimble_port_run();
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BOARD_BLE_ENABLED */
|
||||||
|
|
||||||
|
void ble_manager_set_status_cb(ble_status_cb_t cb)
|
||||||
|
{
|
||||||
|
#if BOARD_BLE_ENABLED
|
||||||
|
s_status_cb = cb;
|
||||||
|
#else
|
||||||
|
(void)cb;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_manager_is_connected(void)
|
||||||
|
{
|
||||||
|
#if BOARD_BLE_ENABLED
|
||||||
|
return s_connected;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_manager_init(void)
|
||||||
|
{
|
||||||
|
#if BOARD_BLE_ENABLED
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
gpio_reset_pin(BOARD_PIN_LED);
|
||||||
|
gpio_set_direction(BOARD_PIN_LED, GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(BOARD_PIN_LED, 0);
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(nimble_port_init());
|
||||||
|
|
||||||
|
ble_svc_gap_init();
|
||||||
|
rc = ble_svc_gap_device_name_set(BLE_DEVICE_NAME);
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "failed to set device name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = gatt_svc_init();
|
||||||
|
if (rc != 0) {
|
||||||
|
ESP_LOGE(TAG, "failed to init GATT service: %d", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_hs_cfg.reset_cb = on_stack_reset;
|
||||||
|
ble_hs_cfg.sync_cb = on_stack_sync;
|
||||||
|
ble_hs_cfg.gatts_register_cb = gatt_register_cb;
|
||||||
|
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||||
|
ble_store_config_init();
|
||||||
|
|
||||||
|
nimble_port_freertos_init(nimble_host_task);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "BLE peripheral started");
|
||||||
|
#else
|
||||||
|
ESP_LOGI("ble_manager", "BLE disabled by board config");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef void (*ble_status_cb_t)(bool connected);
|
||||||
|
|
||||||
|
void ble_manager_init(void);
|
||||||
|
void ble_manager_set_status_cb(ble_status_cb_t cb);
|
||||||
|
bool ble_manager_is_connected(void);
|
||||||
@@ -1,2 +1,11 @@
|
|||||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||||
CONFIG_ESP_LCD_TOUCH_CST816S_DISABLE_READ_ID=y
|
CONFIG_ESP_LCD_TOUCH_CST816S_DISABLE_READ_ID=y
|
||||||
|
|
||||||
|
# App partition: BLE + WiFi + LVGL exceed default 1MB
|
||||||
|
CONFIG_PARTITION_TABLE_SINGLE_APP=n
|
||||||
|
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
|
||||||
|
|
||||||
|
# BLE (NimBLE peripheral, coexists with WiFi)
|
||||||
|
CONFIG_BT_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_ENABLED=y
|
||||||
|
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=n
|
||||||
|
|||||||
Reference in New Issue
Block a user