TT12-MCU/applications/alarmer.c
2024-01-07 20:21:31 +08:00

318 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-06-19 murmur the first version
*/
/*
** 程序清单:这是一个 RTC 设备使用例程
** 例程导出了 alarm_sample 命令到控制终端
** 命令调用格式alarm_sample
** 程序功能设置RTC时间创建闹钟模式每秒触发启动闹钟
**/
#include <rtthread.h>
#include <rtdevice.h>
#define LOG_TAG "alarm"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
//#define BOOT_PER_HOUR
void user_alarm_callback(rt_alarm_t alarm, time_t timestamp)
{
rt_kprintf("user alarm callback function.\n");
}
void alarm_sample(int argc, char *argv[])
{
// rt_device_t dev = rt_device_find("rtc");
struct rt_alarm_setup setup;
struct rt_alarm * alarm = RT_NULL;
static time_t now;
struct tm p_tm;
if (alarm != RT_NULL)
return;
/* 获取当前时间戳,并把下一秒时间设置为闹钟时间 */
now = time(NULL) + 10;
gmtime_r(&now,&p_tm);
setup.flag = RT_ALARM_DAILY;
setup.wktime.tm_year = p_tm.tm_year;
setup.wktime.tm_mon = p_tm.tm_mon;
setup.wktime.tm_mday = p_tm.tm_mday;
setup.wktime.tm_wday = p_tm.tm_wday;
setup.wktime.tm_hour = atoi(argv[1]);//p_tm.tm_hour;
setup.wktime.tm_min = 0;//p_tm.tm_min;
setup.wktime.tm_sec = 0;//p_tm.tm_sec;
alarm = rt_alarm_create(user_alarm_callback, &setup);
if(RT_NULL != alarm)
{
rt_alarm_start(alarm);
LOG_D("alarm started.");
}
}
/* export msh cmd */
MSH_CMD_EXPORT(alarm_sample,alarm sample);
/**
* 开窗回调
* @param alarm
* @param timestamp
*/
void poTT_callback(rt_alarm_t alarm, time_t timestamp)
{
LOG_I("power UP TT by RTC.");
// timerIsReady();
setWindowMode();
initTT();
}
/**
* 关窗回调
* @param alarm
* @param timestamp
*/
void pdTT_callback(rt_alarm_t alarm, time_t timestamp)
{
LOG_I("power DOWN TT by RTC.");
clearWindowMode();
deInitTT();
//预置开窗会更新多次尝试逻辑,未激活时会始终尝试
}
/**
* 每小时开窗回调
* @param alarm
* @param timestamp
*/
void poTT2_callback(rt_alarm_t alarm, time_t timestamp)
{
// LOG_I("power UP TT by INTERVAL RTC");
// timerIsReady();
// initTT();
}
static uint8_t rstCnt=0;
/**
* 定时更新debug文件名
* @param alarm
* @param timestamp
*/
void updatelog_callback(rt_alarm_t alarm, time_t timestamp)
{
//idle且TT未开启状态下主动重启
if (++rstCnt >= 2)//每N小时一检
{
rstCnt = 0;
if (isIdle())
{
rt_hw_cpu_reset(); //reboot
}
}
else {
updateDebuglogName();
}
}
void addDefaultAlarm()
{
struct rt_alarm_setup setup;
struct rt_alarm * alarm = RT_NULL;
static time_t now;
struct tm p_tm;
/* 获取当前时间戳,并把下一秒时间设置为闹钟时间 */
now = time(NULL);
gmtime_r(&now, &p_tm);
setup.flag = RT_ALARM_HOUR;//小时重复
setup.wktime.tm_year = p_tm.tm_year;
setup.wktime.tm_mon = p_tm.tm_mon;
setup.wktime.tm_mday = p_tm.tm_mday;
setup.wktime.tm_wday = p_tm.tm_wday;
setup.wktime.tm_hour = 0; //整点
setup.wktime.tm_min = 0; //p_tm.tm_min;
setup.wktime.tm_sec = 1; //p_tm.tm_sec;
if (RT_NULL != alarm)
{
rt_alarm_delete(alarm); //
}
alarm = rt_alarm_create(updatelog_callback, &setup);
if (alarm != RT_NULL) {
rt_alarm_start(alarm);
// LOG_D("alarm %d(%02d:%02d) started.",var+1,alarm[var]->wktime.tm_hour+8,alarm[var]->wktime.tm_min);
}
else {
LOG_E("Failed to start alarm.");
}
}
#define BOOT_PER_HOUR
#ifdef BOOT_PER_HOUR
INIT_APP_EXPORT(addDefaultAlarm);
#endif
extern struct rt_alarm_container _container;
static rt_alarm_t a[50];
static size_t cnt = 0;
#ifdef BOOT_PER_HOUR
static size_t indexBegin=1;
#else
static size_t indexBegin=0;
#endif
/**
*获取所有RTC闹钟不含预置闹钟
*/
void getAllAlarm()
{
rt_list_t *next;
rt_alarm_t alarm;
cnt = 0;
for (next = _container.head.next; next != &_container.head; next = next->next)
{
alarm = rt_list_entry(next, struct rt_alarm, list);
a[cnt++] = alarm;
}
}
/**
* 清空所有RTC闹钟
*/
void clearAlarm(void)
{
getAllAlarm();
for (size_t i = 0; i < cnt-indexBegin; ++i)
{
rt_alarm_delete(a[i]);
}
}
/**
* 关闭rtc闹钟
*/
void stopAlarm()
{
getAllAlarm();
for (size_t i = 0; i < cnt-indexBegin; ++i)
{
rt_alarm_stop(a[i]);
}
}
/**
* 恢复rtc闹钟
*/
void startAlarm()
{
getAllAlarm();
for (size_t i = 0; i < cnt-indexBegin; ++i)
{
rt_alarm_start(a[i]);
}
}
void addAlarm(uint8_t *din, rt_alarm_callback_t callback)
{
struct rt_alarm_setup setup;
struct rt_alarm * alarm = RT_NULL;
static time_t now;
struct tm p_tm;
if (alarm != RT_NULL)
return;
/* 获取当前时间戳,并把下一秒时间设置为闹钟时间 */
now = time(NULL) + 10;
gmtime_r(&now, &p_tm);
setup.flag = RT_ALARM_DAILY;
setup.wktime.tm_year = p_tm.tm_year;
setup.wktime.tm_mon = p_tm.tm_mon;
setup.wktime.tm_mday = p_tm.tm_mday;
setup.wktime.tm_wday = p_tm.tm_wday;
setup.wktime.tm_hour = din[0]; //p_tm.tm_hour;
setup.wktime.tm_min = din[1]; //p_tm.tm_min;
setup.wktime.tm_sec = 0; //p_tm.tm_sec;
alarm = rt_alarm_create(callback, &setup);
if (RT_NULL != alarm)
{
// rt_alarm_start(alarm);//默认不启动
// LOG_D("alarm started.");
}
else {
LOG_E("Failed to start alarm.");
}
}
/**
* 更新rtc闹钟
* @param t 每个rtc时刻组成的数组依次对应开窗时段的开始和结束
*/
void updateAlarm(uint8_t *t, size_t len)
{
clearAlarm();
for (int var = 0; var < len; var+=4) {
addAlarm(t+var, poTT_callback);
addAlarm(t+var+2, pdTT_callback);
}
}
static int isInAlarm(rt_alarm_t stop, rt_alarm_t start)
{
struct tm alBegin = start->wktime;
alBegin.tm_hour += 8;
time_t tBegin = mktime(&alBegin);
struct tm alEnd = stop->wktime;
alEnd.tm_hour += 8;
time_t tEnd = mktime(&alEnd);
time_t now = time(RT_NULL);
int rst = (now >= tBegin) && (now <= tEnd);
return rst;
}
/**
* check if in the WINs zone
* @return 1-in,0-not in
*/
int isInWindowZone()
{
getAllAlarm();
int rst = 0;
for (size_t i = 0; i < cnt-indexBegin; i+=2)
{
if(isInAlarm(a[i], a[i+1]))
{
LOG_I("is in window zone.");
rst = 1;
break;
}
}
return rst;
}
MSH_CMD_EXPORT(clearAlarm,clear all alarms);
MSH_CMD_EXPORT(stopAlarm,stop);
MSH_CMD_EXPORT(startAlarm,start);
MSH_CMD_EXPORT(isInWindowZone,isInWindow);
//MSH_CMD_EXPORT(getCurrentTime,getCurrentTime);