#include #include #include #include "cJSON.h" #include "app_inc.h" #include "ql_rtos.h" #include "ql_application.h" #include "ql_audio.h" #include "ql_gpio.h" #include "sockets.h" #include "ql_uart.h" #include "ql_func.h" #include "netdb.h" #include "ql_sim.h" #include "ql_dev.h" #include "ql_wtd.h" #include "ql_fs.h" #include "ql_fota.h" #include "ql_sim.h" #include "ql_ping.h" #include "ql_nw.h" #include "ql_atcmd.h" #include "layer3.h" #include "ql_uart.h" #include "hal_api.h" #include "app_inc.h" sleep_config_t g_sleep_cfg = {0}; // 休眠配置 static uint8_t g_in_sleep_mode = 0; // 0=正常 1=休眠中 // 唤醒检查间隔(休眠中每30秒检查一次时间) #define SLEEP_CHECK_INTERVAL_MS 30000 // 正常模式检查间隔(每60秒检查一次) #define NORMAL_CHECK_INTERVAL_MS 60000 uint8_t get_sleep_mode(void) { return g_in_sleep_mode; } /** * @brief 判断当前时间是否在休眠时间段内 * @param now_hour 当前小时 * @param now_min 当前分钟 * @return 1=在休眠时间段内 0=不在 * * 支持跨天场景:23:00 ~ 07:00 */ int is_in_sleep_time(uint8_t now_hour, uint8_t now_min) { uint16_t now = now_hour * 60 + now_min; // 当前时间转分钟 uint16_t start = g_sleep_cfg.start_hour * 60 + g_sleep_cfg.start_min; uint16_t end = g_sleep_cfg.end_hour * 60 + g_sleep_cfg.end_min; if (start < end) { // 不跨天:如 01:00 ~ 06:00 return (now >= start && now < end); } else { // 跨天:如 23:00 ~ 07:00 return (now >= start || now < end); } } /** * @brief 计算距离唤醒还有多久(毫秒) */ static uint32_t calc_ms_to_wake(uint8_t now_hour, uint8_t now_min, uint8_t now_sec) { uint32_t now_sec_total = now_hour * 3600 + now_min * 60 + now_sec; uint32_t end_sec_total = g_sleep_cfg.end_hour * 3600 + g_sleep_cfg.end_min * 60; if (end_sec_total <= now_sec_total) { // 唤醒时间在明天 end_sec_total += 24 * 3600; } return (end_sec_total - now_sec_total) * 1000; } /** * @brief 计算距离休眠还有多久(毫秒),用于提前准备 */ static uint32_t calc_ms_to_sleep(uint8_t now_hour, uint8_t now_min, uint8_t now_sec) { uint32_t now_sec_total = now_hour * 3600 + now_min * 60 + now_sec; uint32_t start_sec_total = g_sleep_cfg.start_hour * 3600 + g_sleep_cfg.start_min * 60; if (start_sec_total <= now_sec_total) { // 休眠时间在明天 start_sec_total += 24 * 3600; } return (start_sec_total - now_sec_total) * 1000; } /** * @brief 进入休眠模式 */ void enter_sleep_mode(void) { if (g_in_sleep_mode) return; printf("enter_sleep_mode\r\n"); g_in_sleep_mode = 1; app_play_tips_file(12); } /** * @brief 退出休眠模式(唤醒) */ void exit_sleep_mode(void) { if (!g_in_sleep_mode) return; printf("exit_sleep_mode\r\n"); g_in_sleep_mode = 0; app_play_tips_file(13); } /** * @brief 保存休眠配置到文件系统 */ int save_sleep_config(void) { hal_kv_set("sleep_config", &g_sleep_cfg, sizeof(g_sleep_cfg)); printf("save start_hour:%d\r\n", g_sleep_cfg.start_hour); printf("save end_hour:%d\r\n", g_sleep_cfg.end_hour); printf("save start_min:%d\r\n", g_sleep_cfg.start_min); printf("save end_min:%d\r\n", g_sleep_cfg.end_min); printf("save enable:%d\r\n", g_sleep_cfg.enable); return 0; } /** * @brief 从文件系统读取休眠配置 */ int load_sleep_config(void) { hal_kv_get("sleep_config", &g_sleep_cfg, sizeof(g_sleep_cfg)); printf("load start_hour:%d\r\n", g_sleep_cfg.start_hour); printf("load end_hour:%d\r\n", g_sleep_cfg.end_hour); printf("load start_min:%d\r\n", g_sleep_cfg.start_min); printf("load end_min:%d\r\n", g_sleep_cfg.end_min); printf("load enable:%d\r\n", g_sleep_cfg.enable); return 0; } /** * @brief 休眠监控任务 - 周期性检查时间 */ static void app_sleep_monitor_thread(void *arg) { char time_buf[6] = {0}; // 开机加载配置 load_sleep_config(); while (1) { hal_os_get_localtime(time_buf); uint8_t year = time_buf[0]; uint8_t month = time_buf[1]; uint8_t day = time_buf[2]; uint8_t hour = time_buf[3]; uint8_t min = time_buf[4]; uint8_t sec = time_buf[5]; printf("%02d-%02d-%02d %02d:%02d:%02d | sleep=%d\r\n", year+2000, month, day, hour, min, sec, g_in_sleep_mode); if (g_sleep_cfg.enable) { int in_sleep = is_in_sleep_time(hour, min); if (in_sleep && !g_in_sleep_mode) { // 该睡了但还没睡 -> 进入休眠 enter_sleep_mode(); } else if (!in_sleep && g_in_sleep_mode) { // 该醒了但还在睡 -> 唤醒 exit_sleep_mode(); } else if (g_in_sleep_mode) { // 正在休眠中,计算还有多久唤醒,设置长睡眠 uint32_t ms_to_wake = calc_ms_to_wake(hour, min, sec); printf("SleeptoWake %lu s\r\n", ms_to_wake / 1000); // 最多睡30秒检查一次(防止时间跳变) uint32_t sleep_ms = (ms_to_wake > SLEEP_CHECK_INTERVAL_MS) ? SLEEP_CHECK_INTERVAL_MS : ms_to_wake; ql_rtos_task_sleep_ms(sleep_ms); continue; } } // 正常模式:每分钟检查一次 ql_rtos_task_sleep_ms(NORMAL_CHECK_INTERVAL_MS); } } int app_sleep_init(void) { ql_task_t appSleepTaskRef = NULL; ql_rtos_task_create(&appSleepTaskRef, 1024*4, 100, "app_sleep_mgt", app_sleep_monitor_thread, NULL); return 0; }