1、按键驱动重构:dzbj_button改为iot_button组件,支持BOOT/KEY2单击/双击/长按,回调通过xTaskCreate派发避免阻塞esp_timer; 2、新增按键导航管理器(key_nav):9种上下文状态机,统一分发按键事件到对应界面; 3、BLE改造:广播默认关闭由按键触发启停,新增设备间GATT Client图片传输(扫描→连接→MTU协商→分包发送),WRITE_EVT区分APP/设备传图跳转不同界面; 4、新增模式切换按键抑制:NVS标志+2秒时间窗,防止AI↔吧唧切换时幽灵按键触发配网或白屏; 5、AI模式BOOT单击回调添加抑制检查,吧唧模式key_nav_boot_click同步添加; 6、新增6个UI界面:配对(Peiwang)、更新(Update)、发送等待/接收等待/发送中/接收中; 7、新增电池指示器组件(battery_ui):多界面真实电量显示+3秒渐隐; 8、Home/Img界面重构:移除触摸手势事件,改为airhub背景+按键导航; 9、禁用触摸(DZBJ_ENABLE_TOUCH=0),保留代码可恢复; 10、sleep_mgr简化:按键唤醒由key_nav统一处理; Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
159 lines
5.0 KiB
C
159 lines
5.0 KiB
C
// 按键驱动模块
|
||
// BOOT(GPIO0):由board类的iot_button处理(单击/双击/长按3秒模式切换)
|
||
// key_nav的1200ms长按通过iot_button_register_event_cb自定义阈值注册
|
||
// KEY2(GPIO4):由本模块的iot_button处理(单击/双击/长按1200ms)
|
||
|
||
#include "dzbj_button.h"
|
||
#include "key_nav.h"
|
||
#include "device_mode.h"
|
||
#include "iot_button.h"
|
||
#include "driver/gpio.h"
|
||
#include "esp_log.h"
|
||
#include "freertos/FreeRTOS.h"
|
||
#include "freertos/task.h"
|
||
|
||
static const char *TAG = "DZBJ_BTN";
|
||
|
||
// KEY2 按键句柄
|
||
static button_handle_t key2_handle = NULL;
|
||
|
||
// === KEY2 回调(esp_timer中执行,派发到独立任务) ===
|
||
|
||
static void key2_click_task(void *arg) {
|
||
key_nav_key2_click();
|
||
vTaskDelete(NULL);
|
||
}
|
||
|
||
static void key2_double_click_task(void *arg) {
|
||
key_nav_key2_double_click();
|
||
vTaskDelete(NULL);
|
||
}
|
||
|
||
static void key2_long_press_task(void *arg) {
|
||
key_nav_key2_long_press();
|
||
vTaskDelete(NULL);
|
||
}
|
||
|
||
static void key2_click_cb(void *handle, void *data) {
|
||
xTaskCreate(key2_click_task, "nav_kc", 3072, NULL, 5, NULL);
|
||
}
|
||
|
||
static void key2_double_click_cb(void *handle, void *data) {
|
||
xTaskCreate(key2_double_click_task, "nav_kd", 3072, NULL, 5, NULL);
|
||
}
|
||
|
||
static void key2_long_press_cb(void *handle, void *data) {
|
||
xTaskCreate(key2_long_press_task, "nav_kl", 3072, NULL, 5, NULL);
|
||
}
|
||
|
||
esp_err_t dzbj_button_init(void)
|
||
{
|
||
// KEY2 按键配置(iot_button_create 旧版API)
|
||
button_config_t key2_cfg = {
|
||
.type = BUTTON_TYPE_GPIO,
|
||
.long_press_time = 1200, // 长按阈值1.2秒
|
||
.short_press_time = 300, // 双击检测窗口300ms
|
||
.gpio_button_config = {
|
||
.gpio_num = PIN_BTN_KEY2,
|
||
.active_level = 0, // 低电平有效
|
||
},
|
||
};
|
||
key2_handle = iot_button_create(&key2_cfg);
|
||
if (!key2_handle) {
|
||
ESP_LOGE(TAG, "KEY2按键创建失败");
|
||
return ESP_FAIL;
|
||
}
|
||
|
||
// 注册KEY2事件回调(4参数版本)
|
||
iot_button_register_cb(key2_handle, BUTTON_SINGLE_CLICK, key2_click_cb, NULL);
|
||
iot_button_register_cb(key2_handle, BUTTON_DOUBLE_CLICK, key2_double_click_cb, NULL);
|
||
iot_button_register_cb(key2_handle, BUTTON_LONG_PRESS_START, key2_long_press_cb, NULL);
|
||
|
||
ESP_LOGI(TAG, "按键初始化完成 (KEY2=GPIO%d, 长按1200ms, 双击300ms)", PIN_BTN_KEY2);
|
||
return ESP_OK;
|
||
}
|
||
|
||
// === BOOT 1200ms 长按注册(由board类调用,传入boot_button的iot_button句柄) ===
|
||
|
||
static void boot_long_press_1200_task(void *arg) {
|
||
key_nav_boot_long_press();
|
||
vTaskDelete(NULL);
|
||
}
|
||
|
||
static void boot_long_press_1200_cb(void *handle, void *data) {
|
||
xTaskCreate(boot_long_press_1200_task, "nav_bl", 3072, NULL, 5, NULL);
|
||
}
|
||
|
||
void dzbj_button_register_boot_long_press(void *boot_handle)
|
||
{
|
||
if (!boot_handle) return;
|
||
|
||
// 注册1200ms自定义长按事件(不影响board类的3000ms模式切换)
|
||
button_event_config_t evt_cfg = {
|
||
.event = BUTTON_LONG_PRESS_START,
|
||
.event_data = {
|
||
.long_press = {
|
||
.press_time = 1200,
|
||
},
|
||
},
|
||
};
|
||
esp_err_t ret = iot_button_register_event_cb((button_handle_t)boot_handle, evt_cfg, boot_long_press_1200_cb, NULL);
|
||
if (ret == ESP_OK) {
|
||
ESP_LOGI(TAG, "BOOT 1200ms长按事件注册成功");
|
||
} else {
|
||
ESP_LOGE(TAG, "BOOT 1200ms长按事件注册失败: %s", esp_err_to_name(ret));
|
||
}
|
||
}
|
||
|
||
// === BOOT+KEY2 组合键模式切换(BOOT 2000ms长按时检测KEY2) ===
|
||
|
||
// === BOOT+KEY2 组合键模式切换(BOOT 2000ms长按时检测KEY2) ===
|
||
|
||
static void mode_switch_task(void *arg) {
|
||
ESP_LOGI(TAG, "执行模式切换...");
|
||
if (device_mode_is_badge()) {
|
||
ESP_LOGI(TAG, "吧唧模式 → AI模式");
|
||
device_mode_set(DEVICE_MODE_AI);
|
||
} else {
|
||
ESP_LOGI(TAG, "AI模式 → 吧唧模式");
|
||
device_mode_set(DEVICE_MODE_BADGE);
|
||
}
|
||
// device_mode_set 内部会 esp_restart,不会执行到这里
|
||
vTaskDelete(NULL);
|
||
}
|
||
|
||
static void mode_switch_combo_cb(void *handle, void *data) {
|
||
// esp_timer中执行,检测KEY2是否同时按下
|
||
if (gpio_get_level(PIN_BTN_KEY2) == 0) {
|
||
ESP_LOGI(TAG, "BOOT+KEY2组合键2秒:触发模式切换");
|
||
xTaskCreate(mode_switch_task, "mode_sw", 2048, NULL, 5, NULL);
|
||
}
|
||
}
|
||
|
||
void dzbj_button_register_mode_switch_combo(void *boot_handle)
|
||
{
|
||
if (!boot_handle) return;
|
||
|
||
// 注册2000ms自定义长按事件用于组合键检测
|
||
button_event_config_t evt_cfg = {
|
||
.event = BUTTON_LONG_PRESS_START,
|
||
.event_data = {
|
||
.long_press = {
|
||
.press_time = 2000,
|
||
},
|
||
},
|
||
};
|
||
esp_err_t ret = iot_button_register_event_cb((button_handle_t)boot_handle, evt_cfg, mode_switch_combo_cb, NULL);
|
||
if (ret == ESP_OK) {
|
||
ESP_LOGI(TAG, "BOOT+KEY2组合键模式切换注册成功(2000ms)");
|
||
} else {
|
||
ESP_LOGE(TAG, "组合键注册失败: %s", esp_err_to_name(ret));
|
||
}
|
||
}
|
||
|
||
// 吧唧模式 BOOT 单击处理(转发到key_nav统一处理)
|
||
void dzbj_boot_click_handler(void)
|
||
{
|
||
key_nav_boot_click();
|
||
}
|