wangzhibo
2026-10-08 220e4fab27b7f419b3e89e2f2d28ae789aac09d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "sleep_timer.h"
#include "application.h"
#include "board.h"
#include "display.h"
#include "settings.h"
 
#include <esp_log.h>
#include <esp_sleep.h>
#include <esp_lvgl_port.h>
 
#define TAG "SleepTimer"
 
 
SleepTimer::SleepTimer(int seconds_to_light_sleep, int seconds_to_deep_sleep)
    : seconds_to_light_sleep_(seconds_to_light_sleep), seconds_to_deep_sleep_(seconds_to_deep_sleep) {
    esp_timer_create_args_t timer_args = {
        .callback = [](void* arg) {
            auto self = static_cast<SleepTimer*>(arg);
            self->CheckTimer();
        },
        .arg = this,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "sleep_timer",
        .skip_unhandled_events = true,
    };
    ESP_ERROR_CHECK(esp_timer_create(&timer_args, &sleep_timer_));
}
 
SleepTimer::~SleepTimer() {
    esp_timer_stop(sleep_timer_);
    esp_timer_delete(sleep_timer_);
}
 
void SleepTimer::SetEnabled(bool enabled) {
    if (enabled && !enabled_) {
        Settings settings("wifi", false);
        if (!settings.GetBool("sleep_mode", true)) {
            ESP_LOGI(TAG, "Power save timer is disabled by settings");
            return;
        }
 
        ticks_ = 0;
        enabled_ = enabled;
        ESP_ERROR_CHECK(esp_timer_start_periodic(sleep_timer_, 1000000));
        ESP_LOGI(TAG, "Sleep timer enabled");
    } else if (!enabled && enabled_) {
        ESP_ERROR_CHECK(esp_timer_stop(sleep_timer_));
        enabled_ = enabled;
        WakeUp();
        ESP_LOGI(TAG, "Sleep timer disabled");
    }
}
 
void SleepTimer::OnEnterLightSleepMode(std::function<void()> callback) {
    on_enter_light_sleep_mode_ = callback;
}
 
void SleepTimer::OnExitLightSleepMode(std::function<void()> callback) {
    on_exit_light_sleep_mode_ = callback;
}
 
void SleepTimer::OnEnterDeepSleepMode(std::function<void()> callback) {
    on_enter_deep_sleep_mode_ = callback;
}
 
void SleepTimer::CheckTimer() {
    auto& app = Application::GetInstance();
    if (!app.CanEnterSleepMode()) {
        ticks_ = 0;
        return;
    }
 
    ticks_++;
    if (seconds_to_light_sleep_ != -1 && ticks_ >= seconds_to_light_sleep_) {
        if (!in_light_sleep_mode_) {
            in_light_sleep_mode_ = true;
            if (on_enter_light_sleep_mode_) {
                on_enter_light_sleep_mode_();
            }
 
            auto& audio_service = app.GetAudioService();
            bool is_wake_word_running = audio_service.IsWakeWordRunning();
            if (is_wake_word_running) {
                audio_service.EnableWakeWordDetection(false);
                vTaskDelay(pdMS_TO_TICKS(100));
            }
        
            app.Schedule([this, &app]() {
                while (in_light_sleep_mode_) {
                    auto& board = Board::GetInstance();
                    board.GetDisplay()->UpdateStatusBar(true);
                    lv_refr_now(nullptr);
                    lvgl_port_stop();
    
                    // 配置timer唤醒源(30秒后自动唤醒)
                    esp_sleep_enable_timer_wakeup(30 * 1000000);
                    
                    // 进入light sleep模式
                    esp_light_sleep_start();
                    lvgl_port_resume();
 
                    auto wakeup_reason = esp_sleep_get_wakeup_cause();
                    ESP_LOGI(TAG, "Wake up from light sleep, wakeup_reason: %d", wakeup_reason);
                    if (wakeup_reason != ESP_SLEEP_WAKEUP_TIMER) {
                        break;
                    }
                }
                WakeUp();
            });
 
            if (is_wake_word_running) {
                audio_service.EnableWakeWordDetection(true);
            }
        }
    }
    if (seconds_to_deep_sleep_ != -1 && ticks_ >= seconds_to_deep_sleep_) {
        if (on_enter_deep_sleep_mode_) {
            on_enter_deep_sleep_mode_();
        }
 
        esp_deep_sleep_start();
    }
}
 
void SleepTimer::WakeUp() {
    ticks_ = 0;
    if (in_light_sleep_mode_) {
        in_light_sleep_mode_ = false;
        if (on_exit_light_sleep_mode_) {
            on_exit_light_sleep_mode_();
        }
    }
}