PV1_Comm/Framework/Timer/timer.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(&timestamp, &setTime);
switch(pInfo->repeatMode)
{
case REPEAT_MODE_EVERY_DAY:
localtime_r(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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(&timestamp, &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);
}