/* * 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 #include #define LOG_TAG "alarm" #define LOG_LVL LOG_LVL_DBG #include 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); void poTT_callback(rt_alarm_t alarm, time_t timestamp) { LOG_D("power UP TT by RTC."); initTT(); setWindowMode(); } void pdTT_callback(rt_alarm_t alarm, time_t timestamp) { LOG_D("power DOWN TT by RTC."); deInitTT(); } void poTT2_callback(rt_alarm_t alarm, time_t timestamp) { LOG_D("power UP TT by RTC."); initTT(); } //每个开窗设置对应两个rtc闹钟,一个上电一个下电 //更新开窗设置前需要先清空闹钟设置。可改为调用rt_alarm_control()修改。 static struct rt_alarm *alarm[4+1];//支持2组开窗共4个闹钟,加一个定时发送闹钟 #ifndef al void InitAlarm() { struct rt_alarm_setup setup; time_t now; struct tm p_tm; /* 获取当前时间戳,并把下一秒时间设置为闹钟时间 */ now = time(NULL); 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 = 1; //整点 setup.wktime.tm_min = 0; //p_tm.tm_min; setup.wktime.tm_sec = 0; //p_tm.tm_sec; if (RT_NULL != alarm[0]) { rt_alarm_delete(alarm[0]); // } alarm[0] = rt_alarm_create(poTT_callback, &setup); setup.wktime.tm_hour = 2; //开窗1闭合点 if (RT_NULL != alarm[1]) { rt_alarm_delete(alarm[1]); // } alarm[1] = rt_alarm_create(pdTT_callback, &setup); setup.wktime.tm_hour = 7; //开窗2开启点 if (RT_NULL != alarm[2]) { rt_alarm_delete(alarm[2]); // } alarm[2] = rt_alarm_create(poTT_callback, &setup); setup.wktime.tm_hour = 8; //开窗2闭合点 if (RT_NULL != alarm[3]) { rt_alarm_delete(alarm[3]); // } alarm[3] = rt_alarm_create(pdTT_callback, &setup); setup.flag = RT_ALARM_HOUR;//小时重复 setup.wktime.tm_min = 15; //每小时的1刻钟启动发送 if (RT_NULL != alarm[4]) { rt_alarm_delete(alarm[4]); // } alarm[4] = rt_alarm_create(poTT2_callback, &setup); for (size_t var = 0; var < 5; var++) { if (alarm[var] != RT_NULL) { rt_alarm_start(alarm[var]); // 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 %d.",var+1); } } } #else void updateAlarm(uint8_t *t, size_t len); void InitAlarm() { updateAlarm(scfg.openWindowTime, 8); } #endif INIT_APP_EXPORT(InitAlarm); /** * 更新rtc闹钟 * @param t 每个rtc时刻组成的数组,依次对应开窗时段的开始和结束 */ void updateAlarm(uint8_t *t, size_t len) { // LOG_HEX("alarm",16,t,4); struct rt_alarm_setup setup; time_t now; struct tm p_tm; /* 获取当前时间戳,并把下一秒时间设置为闹钟时间 */ now = time(NULL); 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 = 1; //整点 setup.wktime.tm_min = 0; //p_tm.tm_min; setup.wktime.tm_sec = 0; //p_tm.tm_sec; setup.wktime.tm_hour = t[0]; //开窗1开启点 setup.wktime.tm_min = t[1]; //开窗1开启点 if (RT_NULL != alarm[0]) { rt_alarm_delete(alarm[0]); // } alarm[0] = rt_alarm_create(poTT_callback, &setup); setup.wktime.tm_hour = t[2]; //开窗1闭合点 setup.wktime.tm_min = t[3]; //开窗1开启点 if (RT_NULL != alarm[1]) { rt_alarm_delete(alarm[1]); // } alarm[1] = rt_alarm_create(pdTT_callback, &setup); setup.wktime.tm_hour = t[4]; //开窗2开启点 setup.wktime.tm_min = t[5]; //开窗2开启点 if (RT_NULL != alarm[2]) { rt_alarm_delete(alarm[2]); // } alarm[2] = rt_alarm_create(poTT_callback, &setup); setup.wktime.tm_hour = t[6]; //开窗2闭合点 setup.wktime.tm_min = t[7]; //开窗2开启点 if (RT_NULL != alarm[3]) { rt_alarm_delete(alarm[3]); // } alarm[3] = rt_alarm_create(pdTT_callback, &setup); for (size_t var = 0; var < 4; var++) { if (alarm[var] != RT_NULL) { rt_alarm_start(alarm[var]); // LOG_D("alarm %d started.",var+1); LOG_D("alarmer %d(%02d:%02d) started.",var+1,alarm[var]->wktime.tm_hour+8,alarm[var]->wktime.tm_min); } else { LOG_E("Failed to start alarm %d.",var+1); } } // rt_alarm_control(alarm[0],RT_ALARM_CTRL_MODIFY,&setup); } /** * 关闭rtc闹钟, */ void stopAlarm() { for (size_t var = 0; var < 4; var++) { if (alarm[var] != RT_NULL) { rt_alarm_stop(alarm[var]); LOG_D("alarm %d stopped.",var+1); } else { LOG_E("Failed to stop alarm %d.",var+1); } } } /** * 恢复rtc闹钟, */ void startAlarm() { for (size_t var = 0; var < 4; var++) { if (alarm[var] != RT_NULL) { rt_alarm_start(alarm[var]); LOG_D("alarm %d started.",var+1); } else { LOG_E("Failed to start alarm %d.",var+1); } } } /** * check if in the WINs zone * @return 1-in,0-not in */ int isInWindowZone() { struct timeval tv; gettimeofday(&tv, NULL); time_t now = (long) tv.tv_sec; // LOG_D("now = %ld", now); struct tm *alBegin = &alarm[0]->wktime; alBegin->tm_hour += 8; time_t tBegin = mktime(alBegin); struct tm *alEnd = &alarm[1]->wktime; alEnd->tm_hour += 8; time_t tEnd = mktime(alEnd); // LOG_D("%ld-%ld", (long)tBegin,(long)tEnd); uint8_t isIn1 = (now > tBegin && now < tEnd); alBegin = &alarm[2]->wktime; alBegin->tm_hour += 8; tBegin = mktime(alBegin); alEnd = &alarm[3]->wktime; alEnd->tm_hour += 8; tEnd = mktime(alEnd); // LOG_D("%ld-%ld", (long)tBegin,(long)tEnd); uint8_t isIn2 = (now > tBegin && now < tEnd); if (isIn1 || isIn2) { LOG_D("is in window zone."); return 1; } else { return 0; } } //读取系统毫秒级时间 //long getCurrentTime() // //{ // //struct timeval tv; // //gettimeofday(&tv,NULL); // //LOG_D("ms=%lld", tv.tv_sec * 1000 + tv.tv_usec / 1000); // //LOG_D("Current time: %ld.%06ld\n", tv.tv_sec, tv.tv_usec); // //} MSH_CMD_EXPORT(stopAlarm,stop); MSH_CMD_EXPORT(startAlarm,start); MSH_CMD_EXPORT(isInWindowZone,isInWindow); //MSH_CMD_EXPORT(getCurrentTime,getCurrentTime);