/*****************************************************include files **************************************************************************/ #include "screen_sleep.h" #include "ui/generated/events_init.h" #include "ui/ui.h" #define AUTO_SLEEP_DEFAULT_MS 0//默认休眠时间 /******************************************************* variable declaration ************************************************************************/ static uint32_t g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS; // 初始化为当前开机时间 int64_t last_activity_timestamp = 0; //最后一次用户活动的时间戳 static bool g_sleep_timeout_dirty = false; //休眠时间是否被改过但是没有写入NVS static uint32_t g_sleep_commit_pending_ms = 0; //待提交到NVS的休眠时间缓存值 /* ===== 休眠设置 NVS 提交:离开休眠界面时写一次 ===== */ static TimerHandle_t g_sleep_commit_timer = NULL; //创建了freeRTOS的软件定时器句柄 extern volatile bool is_system_sleeping; //系统睡眠标记 extern bool block_auto_sleep ; //是否阻止自动休眠 extern int current_page_idx ; //当前页面索引 /******************************************************* functions declaration ************************************************************************/ static void save_timeout_to_nvs(uint32_t ms); static void sleep_commit_timer_cb(TimerHandle_t xTimer); /******************************************************* functions definition ************************************************************************/ // 【新增】从 NVS 加载休眠时间 void load_timeout_from_nvs(void)//从nvs加载休眠时间 { nvs_handle_t my_handle; esp_err_t err = nvs_open("system_cfg", NVS_READONLY, &my_handle); if (err != ESP_OK) { ESP_LOGW("NVS", "打开 system_cfg 失败: %s,休眠时间使用默认 %lu ms", esp_err_to_name(err), (unsigned long)AUTO_SLEEP_DEFAULT_MS); g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS; system_keep_alive(); return; } uint32_t saved_val = 0; if (nvs_get_u32(my_handle, "sleep_ms", &saved_val) == ESP_OK) { g_auto_sleep_timeout_ms = saved_val; ESP_LOGI("NVS", "从 NVS 加载休眠时间: %lu ms", (unsigned long)g_auto_sleep_timeout_ms); } else { g_auto_sleep_timeout_ms = AUTO_SLEEP_DEFAULT_MS; ESP_LOGW("NVS", "未找到 sleep_ms,使用默认 %lu ms", (unsigned long)AUTO_SLEEP_DEFAULT_MS); } nvs_close(my_handle); /* 以完成 NVS 加载时刻为空闲计时起点,避免 last_activity 长期为 0 误判超时 */ system_keep_alive(); } // 【新增】保存设置到 NVS static void save_timeout_to_nvs(uint32_t ms)//保存休眠时间到nvs { nvs_handle_t my_handle; esp_err_t err = nvs_open("system_cfg", NVS_READWRITE, &my_handle); if (err == ESP_OK) { nvs_set_u32(my_handle, "sleep_ms", ms); nvs_commit(my_handle); // 提交保存 nvs_close(my_handle); ESP_LOGI("NVS", "休眠时间已保存: %lu ms", (unsigned long)ms); } else { ESP_LOGE("NVS", "无法打开 NVS 保存设置"); } } void persist_auto_sleep_timeout_ms_now(uint32_t ms) { if (g_sleep_commit_timer != NULL) { xTimerStop(g_sleep_commit_timer, pdMS_TO_TICKS(100)); } g_auto_sleep_timeout_ms = ms; g_sleep_timeout_dirty = false; g_sleep_commit_pending_ms = ms; system_keep_alive(); save_timeout_to_nvs(ms); } // 2. 【新增】设置超时时间的函数 (提供给按钮调用) // 输入 0 代表永不休眠 设置自动休眠时间 void set_auto_sleep_timeout(uint32_t ms) { if (g_auto_sleep_timeout_ms == ms) { return; } g_auto_sleep_timeout_ms = ms; system_keep_alive(); ESP_LOGI("PM", "休眠设置更新: %lu ms (mark dirty)", (unsigned long)ms); g_sleep_timeout_dirty = true; } // 【核心函数 1】系统保活:任何操作都应该调用这个函数 void system_keep_alive(void)//更新当前的活动时间戳 { last_activity_timestamp = esp_timer_get_time() / 1000; // 更新为当前时间(ms) } //获取自动休眠时间 uint32_t get_auto_sleep_timeout(void) { return g_auto_sleep_timeout_ms; } //如果脏标记被设置过之后 发送自动休眠时间 void commit_auto_sleep_timeout_if_dirty(void) { if (!g_sleep_timeout_dirty) return; g_sleep_commit_pending_ms = g_auto_sleep_timeout_ms; g_sleep_timeout_dirty = false; /* 真正的 NVS 写放到 timer 回调里,避免在 LVGL 事件栈上下文里写 NVS */ if (g_sleep_commit_timer == NULL) { g_sleep_commit_timer = xTimerCreate("sleep_commit_tmr", pdMS_TO_TICKS(50), pdFALSE, NULL, sleep_commit_timer_cb); } if (g_sleep_commit_timer) { if (xTimerStart(g_sleep_commit_timer, 0) != pdPASS) { save_timeout_to_nvs(g_sleep_commit_pending_ms); } } else { save_timeout_to_nvs(g_sleep_commit_pending_ms); } } static void sleep_commit_timer_cb(TimerHandle_t xTimer) { (void)xTimer; save_timeout_to_nvs(g_sleep_commit_pending_ms); } void auto_sleep_checker_cb(lv_timer_t *timer) { // 如果已经在睡觉,或者被阻止,或者设置为 0 (永不),直接返回 if (is_system_sleeping || block_auto_sleep || g_auto_sleep_timeout_ms == 0) { return; } int64_t now = esp_timer_get_time() / 1000; // 使用变量 g_auto_sleep_timeout_ms 替代原来的 30000 if ((now - last_activity_timestamp) > g_auto_sleep_timeout_ms) { ESP_LOGW("PM", "系统空闲超时,自动进入休眠..."); if (current_page_idx != 0) { ui_change_page(0, LV_SCR_LOAD_ANIM_FADE_ON); } toggle_sleep_mode(true); } }