Baji_Rtc_Toy_Key/main/dzbj/sleep_mgr.c
Rdzleo 3a05c3c7d5 双模设备电子吧唧按键功能完整实现 + BLE设备间图片传输 + 模式切换防护
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>
2026-03-26 17:44:46 +08:00

214 lines
6.8 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.

#include "../sleep_mgr/include/sleep_mgr.h"
#include "dzbj_button.h"
#include "pages.h"
#include "pages_pwm.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_lvgl_port.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "lvgl.h"
// #include "../ui/screens/ui_ScreenSet.h" // 按键版禁用
#include "lcd.h"
#include <stdio.h>
static const char *TAG = "SLEEP";
static bool sleep_enabled = false;
static bool screen_off = false;
static int64_t last_activity_us = 0;
static uint8_t saved_brightness = 50;
static const uint8_t DEFAULT_BRIGHTNESS = 50; // 默认亮度
static const uint8_t SLEEP_MODE_BRIGHTNESS = 10; // 休眠模式亮度
// 通知有用户活动
void sleep_mgr_notify_activity(void)
{
last_activity_us = esp_timer_get_time();
// 如果屏幕已关闭,立即唤醒
if (screen_off) {
screen_off = false;
// 恢复 LVGL 和触摸输入
if (lvgl_port_lock(100)) {
// 1. 启用所有输入设备(恢复触摸事件处理)
lv_indev_t *indev = lv_indev_get_next(NULL);
while (indev) {
lv_indev_enable(indev, true);
ESP_LOGI(TAG, "输入设备已启用");
indev = lv_indev_get_next(indev);
}
// 2. 恢复刷新定时器(恢复屏幕重绘)
lv_timer_t *refr_timer = _lv_disp_get_refr_timer(NULL);
if (refr_timer) {
lv_timer_resume(refr_timer);
ESP_LOGI(TAG, "LVGL 刷新定时器已恢复");
}
// 3. 强制刷新当前屏幕因为GRAM被清空为黑色需要重绘
lv_obj_invalidate(lv_scr_act());
ESP_LOGI(TAG, "已标记屏幕需要重绘");
lvgl_port_unlock();
}
// 延迟50ms等待LVGL完成至少一次重绘避免看到黑屏
vTaskDelay(pdMS_TO_TICKS(50));
// 恢复背光
pwm_set_brightness(saved_brightness);
ESP_LOGI(TAG, "屏幕唤醒,恢复亮度%d%%", saved_brightness);
}
}
// 按键活动回调BOOT和KEY2共用
static void btn_activity_cb(int gpio_num, void *usr_data)
{
sleep_mgr_notify_activity();
}
// 关闭屏幕(熄屏进入低功耗)
static void screen_turn_off(void)
{
if (screen_off) return;
// 保存当前亮度
saved_brightness = pwm_get_brightness();
if (saved_brightness == 0) {
saved_brightness = 50; // 防止保存到0值
}
// 暂停 LVGL 并禁用触摸输入
if (lvgl_port_lock(100)) {
// 1. 暂停刷新定时器(停止屏幕重绘)
lv_timer_t *refr_timer = _lv_disp_get_refr_timer(NULL);
if (refr_timer) {
lv_timer_pause(refr_timer);
ESP_LOGI(TAG, "LVGL 刷新定时器已暂停");
}
// 2. 禁用所有输入设备(停止触摸事件处理)
lv_indev_t *indev = lv_indev_get_next(NULL);
while (indev) {
lv_indev_enable(indev, false);
ESP_LOGI(TAG, "输入设备已禁用");
indev = lv_indev_get_next(indev);
}
lvgl_port_unlock();
}
// 清空LCD GRAM为黑色避免关闭背光后看到残影
lcd_clear_screen_black();
// 关闭背光
screen_off = true;
pwm_set_brightness(0);
ESP_LOGI(TAG, "屏幕已关闭(亮度=%d%%系统进入真正低功耗模式Light Sleep + LVGL暂停 + LCD GRAM清空", saved_brightness);
}
// 休眠管理任务
static void sleep_mgr_task(void *pvParameters)
{
while (1) {
uint32_t delay_ms = 500; // 默认轮询间隔 500ms
if (sleep_enabled) {
// 检查LVGL触摸活动屏幕开启时
if (!screen_off) {
if (lvgl_port_lock(50)) {
uint32_t inactive_ms = lv_disp_get_inactive_time(NULL);
lvgl_port_unlock();
// 屏幕开启状态:检测到新触摸(< 500ms立即更新活动时间
if (inactive_ms < 500) {
sleep_mgr_notify_activity();
}
}
// 检查超时熄屏
int64_t now = esp_timer_get_time();
int64_t elapsed_ms = (now - last_activity_us) / 1000;
if (elapsed_ms >= SLEEP_TIMEOUT_MS) {
screen_turn_off();
}
}
// 屏幕关闭状态:禁用触摸唤醒,只允许按键唤醒
// 如需启用触摸唤醒,取消注释以下代码:
/*
else {
if (lvgl_port_lock(50)) {
uint32_t inactive_ms = lv_disp_get_inactive_time(NULL);
lvgl_port_unlock();
// 检测到触摸(< 2000ms立即唤醒
if (inactive_ms < 2000) {
sleep_mgr_notify_activity();
ESP_LOGI(TAG, "触摸唤醒屏幕inactive=%lums", inactive_ms);
}
}
}
*/
}
vTaskDelay(pdMS_TO_TICKS(delay_ms));
}
}
void sleep_mgr_init(void)
{
last_activity_us = esp_timer_get_time();
// 按键版BOOT/KEY2 的按键回调由 key_nav 统一处理
// 各按键回调中应调用 sleep_mgr_notify_activity() 更新活动时间戳
xTaskCreate(sleep_mgr_task, "sleep_mgr", 3072, NULL, 3, NULL);
ESP_LOGI(TAG, "休眠管理器初始化完成(超时=%ds", SLEEP_TIMEOUT_MS / 1000);
}
// 更新亮度UI控件按键版无亮度滑块空实现
static void update_brightness_ui(uint8_t brightness)
{
// 按键版禁用了ScreenSet无亮度UI控件需要更新
(void)brightness;
}
void sleep_mgr_set_enabled(bool enabled)
{
sleep_enabled = enabled;
if (enabled) {
last_activity_us = esp_timer_get_time();
// 进入休眠模式时将亮度调节到10%
pwm_set_brightness(SLEEP_MODE_BRIGHTNESS);
update_brightness_ui(SLEEP_MODE_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已启用,亮度已调节至%d%%%ds无操作将熄屏",
SLEEP_MODE_BRIGHTNESS, SLEEP_TIMEOUT_MS / 1000);
} else {
// 禁用休眠模式时恢复到默认亮度50%
if (screen_off) {
screen_off = false;
pwm_set_brightness(DEFAULT_BRIGHTNESS);
update_brightness_ui(DEFAULT_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已禁用,屏幕已恢复,亮度恢复到%d%%", DEFAULT_BRIGHTNESS);
} else {
pwm_set_brightness(DEFAULT_BRIGHTNESS);
update_brightness_ui(DEFAULT_BRIGHTNESS);
ESP_LOGI(TAG, "休眠模式已禁用,亮度恢复到%d%%", DEFAULT_BRIGHTNESS);
}
}
}
bool sleep_mgr_is_enabled(void)
{
return sleep_enabled;
}
bool sleep_mgr_is_screen_off(void)
{
return screen_off;
}