Files
banban/ql-application/threadx/interface/custom_app/sleep_wake.c
T

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;
}