773 lines
24 KiB
C
773 lines
24 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <uv.h>
|
|
#include <dbus/dbus.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include <uthash/uthash.h>
|
|
|
|
#include "log.h"
|
|
#include "libuv_dbus.h"
|
|
|
|
#define TIMER_TIMEOUT (200)
|
|
|
|
#define IS_LEAP_YEAR(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
|
|
|
|
static unsigned char g_DayOfMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
|
|
typedef struct
|
|
{
|
|
void* pUserData;
|
|
OnAlarmTimer pOnAlarmCb;
|
|
unsigned int alarmId;
|
|
|
|
struct tm setDateTime;
|
|
int setWeekDay;
|
|
unsigned int repeatMode;
|
|
|
|
struct tm onDateTime;
|
|
time_t onTimestamp;
|
|
unsigned int timerPriority;
|
|
|
|
UT_hash_handle hh; ///< UT Hash handle
|
|
} ALARM_ITEM_DATA, *PALARM_ITEM_DATA;
|
|
|
|
static uv_timer_t g_uvTimer;
|
|
static unsigned int g_iAlarmId = 1;
|
|
static struct tm g_LocalTime;
|
|
static time_t g_TimeStamp;
|
|
static uv_loop_t* g_pMainLoop = NULL;
|
|
static uv_rwlock_t g_uvHashRwLock;
|
|
static PALARM_ITEM_DATA g_TimerTbl = NULL;
|
|
|
|
const char* DumpTimerRepeatModeString(int mode)
|
|
{
|
|
switch(mode & 0xFF)
|
|
{
|
|
case REPEAT_MODE_NONE: return "NONE";
|
|
case REPEAT_MODE_EVERY_DAY: return "EVERY_DAY";
|
|
case REPEAT_MODE_WORKDAY: return "WORKDAY";
|
|
case REPEAT_MODE_HOLIDAY: return ("REPEAT_MODE_HOLIDAY");
|
|
case REPEAT_MODE_WEEKEND: return "WEEKEND";
|
|
case REPEAT_MODE_WEEKDAY: return "WEEKDAY";
|
|
case REPEAT_MODE_EVERY_MONTH_DAY: return "EVERY_MONTH_DAY";
|
|
case REPEAT_MODE_EVERY_YEAR_DAY: return "EVERY_YEAR_DAY";
|
|
case REPEAT_MODE_EVERY_TIME: return ("EVERY_TIME");
|
|
case REPEAT_MODE_MONTH_LAST_DAY: return "REPEAT_MODE_MONTH_LAST_DAY";
|
|
default: return ("Unknown Mode");
|
|
}
|
|
}
|
|
|
|
static int __timestampSort(PALARM_ITEM_DATA p1, PALARM_ITEM_DATA p2)
|
|
{
|
|
if(p1->onTimestamp == p2->onTimestamp)
|
|
{
|
|
return (p2->timerPriority - p1->timerPriority);
|
|
}
|
|
else
|
|
{
|
|
return (p1->onTimestamp - p2->onTimestamp);
|
|
}
|
|
}
|
|
|
|
static int __getNextOnTimestamp(PALARM_ITEM_DATA pInfo)
|
|
{
|
|
int ret;
|
|
struct tm setTime;
|
|
time_t timestamp;
|
|
|
|
if(pInfo == NULL)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pInfo->repeatMode == REPEAT_MODE_NONE)
|
|
{
|
|
pInfo->onTimestamp = 0;
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
timestamp = pInfo->onTimestamp + 24 * 3600;
|
|
pInfo->onTimestamp = timestamp;
|
|
localtime_r(×tamp, &setTime);
|
|
|
|
switch(pInfo->repeatMode)
|
|
{
|
|
case REPEAT_MODE_EVERY_DAY:
|
|
localtime_r(×tamp, &pInfo->onDateTime);
|
|
break;
|
|
|
|
case REPEAT_MODE_WORKDAY:
|
|
do
|
|
{
|
|
ret = CurrentIsWorkDay(setTime.tm_year, setTime.tm_yday);
|
|
|
|
if(ret == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
} while(ret == 0);
|
|
|
|
if(ret < 0)
|
|
{
|
|
pInfo->onTimestamp = 0;
|
|
pInfo->onDateTime.tm_year = -1;
|
|
pInfo->onDateTime.tm_mon = -1;
|
|
pInfo->onDateTime.tm_mday = -1;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
}
|
|
break;
|
|
|
|
case REPEAT_MODE_HOLIDAY:
|
|
do
|
|
{
|
|
ret = CurrentIsWorkDay(setTime.tm_year, setTime.tm_yday);
|
|
|
|
if(ret == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
} while(ret == 1);
|
|
|
|
if(ret < 0)
|
|
{
|
|
pInfo->onTimestamp = 0;
|
|
pInfo->onDateTime.tm_year = -1;
|
|
pInfo->onDateTime.tm_mon = -1;
|
|
pInfo->onDateTime.tm_mday = -1;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
}
|
|
break;
|
|
|
|
case REPEAT_MODE_WEEKEND:
|
|
while(setTime.tm_wday != 0 && setTime.tm_wday != 6)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
break;
|
|
|
|
case REPEAT_MODE_WEEKDAY:
|
|
if(pInfo->setDateTime.tm_wday == 0)
|
|
{
|
|
pInfo->setDateTime.tm_wday = 1 << 0;
|
|
}
|
|
else if(pInfo->setDateTime.tm_wday & (1 << 7))
|
|
{
|
|
pInfo->setDateTime.tm_wday = 1 << 0;
|
|
}
|
|
|
|
while(((1 << setTime.tm_wday) & pInfo->setDateTime.tm_wday) == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
|
|
break;
|
|
|
|
case REPEAT_MODE_EVERY_TIME:
|
|
timestamp = mktime(&g_LocalTime);
|
|
|
|
if(pInfo->setDateTime.tm_hour > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_hour * 3600;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_min > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_min * 60;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_sec > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_sec;
|
|
}
|
|
|
|
localtime_r(×tamp, &pInfo->onDateTime);
|
|
pInfo->onTimestamp = timestamp;
|
|
break;
|
|
|
|
case REPEAT_MODE_MONTH_LAST_DAY:
|
|
if(pInfo->onDateTime.tm_mon < 11)
|
|
{
|
|
pInfo->onDateTime.tm_mon++;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_mon = 0;
|
|
pInfo->onDateTime.tm_year++;
|
|
}
|
|
|
|
pInfo->onDateTime.tm_mday = g_DayOfMonth[pInfo->onDateTime.tm_mon];
|
|
if(IS_LEAP_YEAR(pInfo->onDateTime.tm_year) && (pInfo->onDateTime.tm_mon == 1))
|
|
{
|
|
pInfo->onDateTime.tm_mday += 1;
|
|
}
|
|
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
break;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int __getOnTimestamp(PALARM_ITEM_DATA pInfo)
|
|
{
|
|
int ret = 0;
|
|
struct tm setTime;
|
|
time_t timestamp;
|
|
|
|
if(pInfo == NULL)
|
|
{
|
|
return (-ERR_INPUT_PARAMS);
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_hour == -1)
|
|
{
|
|
pInfo->onDateTime.tm_hour = g_LocalTime.tm_hour;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_hour = pInfo->setDateTime.tm_hour;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_min == -1)
|
|
{
|
|
pInfo->onDateTime.tm_min = g_LocalTime.tm_min;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_min = pInfo->setDateTime.tm_min;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_sec == -1)
|
|
{
|
|
pInfo->onDateTime.tm_sec = g_LocalTime.tm_sec;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_sec = pInfo->setDateTime.tm_sec;
|
|
}
|
|
|
|
switch(pInfo->repeatMode)
|
|
{
|
|
case REPEAT_MODE_EVERY_MONTH_DAY:
|
|
pInfo->setDateTime.tm_mon = -1;
|
|
pInfo->setDateTime.tm_year = -1;
|
|
case REPEAT_MODE_EVERY_YEAR_DAY:
|
|
pInfo->setDateTime.tm_year = -1;
|
|
case REPEAT_MODE_NONE:
|
|
if(pInfo->setDateTime.tm_year == -1)
|
|
{
|
|
pInfo->onDateTime.tm_year = g_LocalTime.tm_year;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_year = pInfo->setDateTime.tm_year;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_mon == -1)
|
|
{
|
|
pInfo->onDateTime.tm_mon = g_LocalTime.tm_mon;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_mon = pInfo->setDateTime.tm_mon;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_mday == -1)
|
|
{
|
|
pInfo->onDateTime.tm_mday = g_LocalTime.tm_mday;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_mday = pInfo->setDateTime.tm_mday;
|
|
}
|
|
break;
|
|
|
|
case REPEAT_MODE_EVERY_DAY:
|
|
case REPEAT_MODE_WORKDAY:
|
|
case REPEAT_MODE_WEEKEND:
|
|
case REPEAT_MODE_WEEKDAY:
|
|
case REPEAT_MODE_EVERY_TIME:
|
|
case REPEAT_MODE_HOLIDAY:
|
|
pInfo->onDateTime.tm_year = g_LocalTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = g_LocalTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = g_LocalTime.tm_mday;
|
|
break;
|
|
case REPEAT_MODE_MONTH_LAST_DAY:
|
|
pInfo->onDateTime.tm_year = g_LocalTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = g_LocalTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = g_DayOfMonth[g_LocalTime.tm_mon];
|
|
if(IS_LEAP_YEAR(g_LocalTime.tm_year) && (g_LocalTime.tm_mon == 1))
|
|
{
|
|
pInfo->onDateTime.tm_mday += 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pInfo->onDateTime.tm_wday = g_LocalTime.tm_wday;
|
|
pInfo->onDateTime.tm_yday = g_LocalTime.tm_yday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
|
|
if(pInfo->repeatMode == REPEAT_MODE_NONE)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
memcpy(&setTime, &g_LocalTime, sizeof(struct tm));
|
|
|
|
if(mktime(&setTime) > (pInfo->onTimestamp + 1))
|
|
{
|
|
if(pInfo->repeatMode == REPEAT_MODE_EVERY_MONTH_DAY)
|
|
{
|
|
if(pInfo->onDateTime.tm_mon < 11)
|
|
{
|
|
pInfo->onDateTime.tm_mon++;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_mon = 0;
|
|
pInfo->onDateTime.tm_year++;
|
|
}
|
|
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
return (0);
|
|
}
|
|
else if(pInfo->repeatMode == REPEAT_MODE_EVERY_YEAR_DAY)
|
|
{
|
|
pInfo->onDateTime.tm_year++;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
return (0);
|
|
}
|
|
else if(pInfo->repeatMode == REPEAT_MODE_MONTH_LAST_DAY)
|
|
{
|
|
if(pInfo->onDateTime.tm_mon < 11)
|
|
{
|
|
pInfo->onDateTime.tm_mon++;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_mon = 0;
|
|
pInfo->onDateTime.tm_year++;
|
|
}
|
|
|
|
pInfo->onDateTime.tm_mday = g_DayOfMonth[pInfo->onDateTime.tm_mon];
|
|
if(IS_LEAP_YEAR(pInfo->onDateTime.tm_year) && (pInfo->onDateTime.tm_mon == 1))
|
|
{
|
|
pInfo->onDateTime.tm_mday += 1;
|
|
}
|
|
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
return (0);
|
|
}
|
|
else
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
}
|
|
|
|
switch(pInfo->repeatMode)
|
|
{
|
|
case REPEAT_MODE_EVERY_DAY:
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
break;
|
|
|
|
case REPEAT_MODE_WORKDAY:
|
|
do
|
|
{
|
|
ret = CurrentIsWorkDay(setTime.tm_year, setTime.tm_yday);
|
|
|
|
if(ret == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
} while(ret == 0);
|
|
|
|
if(ret < 0)
|
|
{
|
|
pInfo->onTimestamp = 0;
|
|
pInfo->onDateTime.tm_year = -1;
|
|
pInfo->onDateTime.tm_mon = -1;
|
|
pInfo->onDateTime.tm_mday = -1;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
}
|
|
break;
|
|
|
|
case REPEAT_MODE_HOLIDAY:
|
|
do
|
|
{
|
|
ret = CurrentIsWorkDay(setTime.tm_year, setTime.tm_yday);
|
|
|
|
if(ret == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
} while(ret == 1);
|
|
|
|
if(ret < 0)
|
|
{
|
|
pInfo->onTimestamp = 0;
|
|
pInfo->onDateTime.tm_year = -1;
|
|
pInfo->onDateTime.tm_mon = -1;
|
|
pInfo->onDateTime.tm_mday = -1;
|
|
}
|
|
else
|
|
{
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
}
|
|
break;
|
|
|
|
case REPEAT_MODE_WEEKEND:
|
|
while(setTime.tm_wday != 0 && setTime.tm_wday != 6)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
break;
|
|
|
|
case REPEAT_MODE_WEEKDAY:
|
|
if(pInfo->setDateTime.tm_wday == 0)
|
|
{
|
|
pInfo->setDateTime.tm_wday = 1 << 0;
|
|
}
|
|
else if(pInfo->setDateTime.tm_wday & (1 << 7))
|
|
{
|
|
pInfo->setDateTime.tm_wday = 1 << 0;
|
|
}
|
|
|
|
while(((1 << setTime.tm_wday) & pInfo->setDateTime.tm_wday) == 0)
|
|
{
|
|
timestamp = mktime(&setTime) + 24 * 3600;
|
|
localtime_r(×tamp, &setTime);
|
|
}
|
|
|
|
pInfo->onDateTime.tm_year = setTime.tm_year;
|
|
pInfo->onDateTime.tm_mon = setTime.tm_mon;
|
|
pInfo->onDateTime.tm_mday = setTime.tm_mday;
|
|
pInfo->onTimestamp = mktime(&pInfo->onDateTime);
|
|
|
|
break;
|
|
|
|
case REPEAT_MODE_EVERY_TIME:
|
|
timestamp = mktime(&g_LocalTime);
|
|
|
|
if(pInfo->setDateTime.tm_hour > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_hour * 3600;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_min > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_min * 60;
|
|
}
|
|
|
|
if(pInfo->setDateTime.tm_sec > 0)
|
|
{
|
|
timestamp += pInfo->setDateTime.tm_sec;
|
|
}
|
|
|
|
localtime_r(×tamp, &pInfo->onDateTime);
|
|
pInfo->onTimestamp = timestamp;
|
|
break;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
static void __timerout200msCb(uv_timer_t *pTimer)
|
|
{
|
|
PALARM_ITEM_DATA pItem = NULL, pTemp = NULL;
|
|
|
|
// upgrade current time and timestamp
|
|
g_TimeStamp = time((time_t*)NULL);
|
|
localtime_r(&g_TimeStamp, &g_LocalTime);
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_ITER(hh, g_TimerTbl, pItem, pTemp)
|
|
{
|
|
// cleanup out of time more than 10s timer
|
|
if(g_TimeStamp - pItem->onTimestamp > 10)
|
|
{
|
|
LOG_EX(LOG_Warn, "Remove out of time timer: %u, %ld, %ld\n", pItem->alarmId, g_TimeStamp, pItem->onTimestamp);
|
|
HASH_DEL(g_TimerTbl, pItem);
|
|
free(pItem);
|
|
|
|
continue;
|
|
}
|
|
|
|
// timer not on time
|
|
if(pItem->onTimestamp != g_TimeStamp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// timer on time, call callback
|
|
if(pItem->pOnAlarmCb)
|
|
{
|
|
pItem->pOnAlarmCb(pItem->alarmId, g_TimeStamp, pItem->pUserData);
|
|
}
|
|
|
|
//LOG_EX(LOG_Debug, "Timer %d Alarming..................\n", pItem->alarmId);
|
|
|
|
// cleanup not repeat timer
|
|
if(pItem->repeatMode == REPEAT_MODE_NONE)
|
|
{
|
|
HASH_DEL(g_TimerTbl, pItem);
|
|
free(pItem);
|
|
}
|
|
else
|
|
{
|
|
// calc next on time
|
|
int ret = __getNextOnTimestamp(pItem);
|
|
|
|
if(ret != 0 || pItem->onTimestamp == 0)
|
|
{
|
|
// some error, remove it
|
|
LOG_EX(LOG_Error, "Timer %d repeat error: ret = %d, timestamp = %u\n", pItem->alarmId, ret, pItem->onTimestamp);
|
|
HASH_DEL(g_TimerTbl, pItem);
|
|
free(pItem);
|
|
}
|
|
else
|
|
{
|
|
// resort table by upgrade timestamp
|
|
HASH_SORT(g_TimerTbl, __timestampSort);
|
|
|
|
// show log
|
|
LOG_EX(LOG_Debug, "Readd Timer: %u at [%04u-%02u-%02u %02u:%02u:%02u], repMode = %s, Timestamp = %u\n",
|
|
pItem->alarmId,
|
|
pItem->onDateTime.tm_year + 1900,
|
|
pItem->onDateTime.tm_mon + 1,
|
|
pItem->onDateTime.tm_mday,
|
|
pItem->onDateTime.tm_hour,
|
|
pItem->onDateTime.tm_min,
|
|
pItem->onDateTime.tm_sec,
|
|
DumpTimerRepeatModeString(pItem->repeatMode),
|
|
pItem->onTimestamp);
|
|
}
|
|
}
|
|
}
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
}
|
|
|
|
int AlarmTimerInit(uv_loop_t* pLoop)
|
|
{
|
|
g_pMainLoop = pLoop;
|
|
uv_rwlock_init(&g_uvHashRwLock);
|
|
uv_timer_init(g_pMainLoop, &g_uvTimer);
|
|
|
|
g_TimeStamp = time((time_t*)NULL);
|
|
localtime_r(&g_TimeStamp, &g_LocalTime);
|
|
|
|
g_iAlarmId = 1;
|
|
|
|
uv_timer_start(&g_uvTimer, __timerout200msCb, 0, TIMER_TIMEOUT);
|
|
}
|
|
|
|
int AlarmTimerCleanup(void)
|
|
{
|
|
uv_timer_stop(&g_uvTimer);
|
|
uv_rwlock_destroy(&g_uvHashRwLock);
|
|
|
|
if(g_pMainLoop != NULL)
|
|
{
|
|
AlarmTimerInit(g_pMainLoop);
|
|
}
|
|
}
|
|
|
|
int AlarmTimerRemove(unsigned int tmId)
|
|
{
|
|
PALARM_ITEM_DATA pItem = NULL;
|
|
|
|
uv_rwlock_rdlock(&g_uvHashRwLock);
|
|
HASH_FIND_INT(g_TimerTbl, &tmId, pItem);
|
|
uv_rwlock_rdunlock(&g_uvHashRwLock);
|
|
|
|
if(pItem == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Can't find item: %u\n", tmId);
|
|
return (-ERR_NO_ITEMS);
|
|
}
|
|
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_DEL(g_TimerTbl, pItem);
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
free(pItem);
|
|
|
|
return (tmId);
|
|
}
|
|
|
|
unsigned int AlarmTimerAdd(int year,
|
|
int month,
|
|
int day,
|
|
int hour,
|
|
int minute,
|
|
int second,
|
|
int weekDay,
|
|
int repMode,
|
|
OnAlarmTimer pOnTimerCb,
|
|
int priority,
|
|
void *pUserData,
|
|
int *pError)
|
|
{
|
|
int et;
|
|
PALARM_ITEM_DATA pAlarmData = NULL;
|
|
|
|
if(pOnTimerCb == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Input Params Error: pOnTimerCb = %p\n", pOnTimerCb);
|
|
if(pError)
|
|
{
|
|
*pError = -ERR_INPUT_PARAMS;
|
|
}
|
|
|
|
return (0xFFFFFFFF);
|
|
}
|
|
|
|
g_TimeStamp = time((time_t*)NULL);
|
|
localtime_r(&g_TimeStamp, &g_LocalTime);
|
|
|
|
pAlarmData = (PALARM_ITEM_DATA)malloc(sizeof(ALARM_ITEM_DATA));
|
|
|
|
if(pAlarmData == NULL)
|
|
{
|
|
LOG_EX(LOG_Error, "Malloc Memory Error\n");
|
|
|
|
if(pError)
|
|
{
|
|
*pError = -ERR_MALLOC_MEMORY;
|
|
}
|
|
|
|
return (0xFFFFFFFF);
|
|
}
|
|
|
|
memset(pAlarmData, 0, sizeof(ALARM_ITEM_DATA));
|
|
|
|
// save input params
|
|
pAlarmData->setDateTime.tm_year = year;
|
|
pAlarmData->setDateTime.tm_mon = month;
|
|
pAlarmData->setDateTime.tm_mday = day;
|
|
pAlarmData->setDateTime.tm_hour = hour;
|
|
pAlarmData->setDateTime.tm_min = minute;
|
|
pAlarmData->setDateTime.tm_sec = second;
|
|
pAlarmData->setDateTime.tm_wday = weekDay;
|
|
|
|
pAlarmData->repeatMode = repMode;
|
|
pAlarmData->pOnAlarmCb = pOnTimerCb;
|
|
pAlarmData->pUserData = pUserData;
|
|
pAlarmData->timerPriority = priority;
|
|
|
|
// get timer on time
|
|
__getOnTimestamp(pAlarmData);
|
|
|
|
// check on time
|
|
et = pAlarmData->onTimestamp - mktime(&g_LocalTime);
|
|
|
|
if(et < -1 || pAlarmData->onTimestamp == 0)
|
|
{
|
|
LOG_EX(LOG_Debug, "Add Timer Error: [%04u-%02u-%02u %02u:%02u:%02u], repMode = %s(%u), %d, %u/%u\n",
|
|
pAlarmData->setDateTime.tm_year + 1900,
|
|
pAlarmData->setDateTime.tm_mon + 1,
|
|
pAlarmData->setDateTime.tm_mday,
|
|
pAlarmData->setDateTime.tm_hour,
|
|
pAlarmData->setDateTime.tm_min,
|
|
pAlarmData->setDateTime.tm_sec,
|
|
DumpTimerRepeatModeString(repMode), repMode,
|
|
et, pAlarmData->onTimestamp, mktime(&g_LocalTime));
|
|
|
|
if(pError)
|
|
{
|
|
*pError = -ERR_INPUT_PARAMS;
|
|
}
|
|
|
|
return (0xFFFFFFFF);
|
|
}
|
|
|
|
if(pError)
|
|
{
|
|
*pError = 0;
|
|
}
|
|
|
|
// upgrade time global id
|
|
pAlarmData->alarmId = __sync_fetch_and_add(&g_iAlarmId, 1);
|
|
|
|
// save new timer to hash table, and sort it by timestamp
|
|
uv_rwlock_wrlock(&g_uvHashRwLock);
|
|
HASH_ADD_INT(g_TimerTbl, alarmId, pAlarmData);
|
|
HASH_SORT(g_TimerTbl, __timestampSort);
|
|
uv_rwlock_wrunlock(&g_uvHashRwLock);
|
|
|
|
LOG_EX(LOG_Debug, "Add: %u [%04u-%02u-%02u %02u:%02u:%02u] at [%04u-%02u-%02u %02u:%02u:%02u], repMode = %s, priority = %d, Timestamp = %u\n",
|
|
pAlarmData->alarmId,
|
|
(pAlarmData->setDateTime.tm_year == -1) ? 1900 : pAlarmData->setDateTime.tm_year + 1900,
|
|
(pAlarmData->setDateTime.tm_mon == -1) ? 0 : pAlarmData->setDateTime.tm_mon + 1,
|
|
(pAlarmData->setDateTime.tm_mday == -1) ? 0 : pAlarmData->setDateTime.tm_mday,
|
|
(pAlarmData->setDateTime.tm_hour == -1) ? 0 : pAlarmData->setDateTime.tm_hour,
|
|
(pAlarmData->setDateTime.tm_min == -1) ? 0 : pAlarmData->setDateTime.tm_min,
|
|
(pAlarmData->setDateTime.tm_sec == -1) ? 0 : pAlarmData->setDateTime.tm_sec,
|
|
pAlarmData->onDateTime.tm_year + 1900,
|
|
pAlarmData->onDateTime.tm_mon + 1,
|
|
pAlarmData->onDateTime.tm_mday,
|
|
pAlarmData->onDateTime.tm_hour,
|
|
pAlarmData->onDateTime.tm_min,
|
|
pAlarmData->onDateTime.tm_sec,
|
|
DumpTimerRepeatModeString(repMode),
|
|
pAlarmData->timerPriority,
|
|
pAlarmData->onTimestamp);
|
|
|
|
return (pAlarmData->alarmId);
|
|
}
|
|
|
|
|