217 lines
6.0 KiB
C
217 lines
6.0 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <librws.h>
|
|
#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;
|
|
}
|
|
|
|
|
|
|