diff --git a/apps/aqhome-react/units/u_timeprogram.c b/apps/aqhome-react/units/u_timeprogram.c index 194af19..e9b4056 100644 --- a/apps/aqhome-react/units/u_timeprogram.c +++ b/apps/aqhome-react/units/u_timeprogram.c @@ -29,6 +29,10 @@ #define AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT 0 +#define AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEINTERVAL_MIN 60 /* 1h */ +#define AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEINTERVAL_SEC (61*60) /* 61m */ + +#define AQHOMEREACT_UNIT_TIMEPROGRAM_CHECKINTERVAL_SEC 60 /* 1m */ GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM); @@ -39,19 +43,17 @@ GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM); * ------------------------------------------------------------------------------------------------ */ -static MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, double value); +static MODULE_TIMER_ACTION *ModuleTimerAction_new(int64_t triggerTime, double value); static void ModuleTimerAction_free(MODULE_TIMER_ACTION *act); static void GWENHYWFAR_CB _freeData(void *bp, void *p); static int _cbProcess(AQHREACT_UNIT *unit); static int _readRules(AQHREACT_UNIT *unit); -static int _handleActionsForGivenTime(AQHREACT_UNIT *unit, int hourMins); -static int _checkAndAddActions(AQHREACT_UNIT *unit); -static int _addActionsForGivenTime(const GWEN_TIME *ti, - int hour, - const AQHREACT_PRGRULE_LIST *ruleList, - MODULE_TIMER_ACTION_LIST *actionList); +static int _checkAndAddActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit); +static int _addActionsForNextMinutes(GWEN_TIMESTAMP *ts, int minutes, + const AQHREACT_PRGRULE_LIST *ruleList, MODULE_TIMER_ACTION_LIST *actionList); +static int _handlePendingActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit); @@ -68,14 +70,14 @@ GWEN_LIST_FUNCTIONS(MODULE_TIMER_ACTION, ModuleTimerAction); * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, double value) +MODULE_TIMER_ACTION *ModuleTimerAction_new(int64_t triggerTime, double value) { MODULE_TIMER_ACTION *act; GWEN_NEW_OBJECT(MODULE_TIMER_ACTION, act); GWEN_LIST_INIT(MODULE_TIMER_ACTION, act); - act->hourMinutes=hourTime; + act->triggerTime=triggerTime; act->value=value; return act; @@ -112,6 +114,7 @@ AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQH_OBJECT *aqh) GWEN_INHERIT_SETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit, xunit, _freeData); xunit->actionList=ModuleTimerAction_List_new(); + xunit->lastActionHour=-1; AQHREACT_Unit_SetProcessFn(unit, _cbProcess); port=AQHREACT_Port_new(); @@ -125,6 +128,8 @@ AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQH_OBJECT *aqh) AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_STRING); AQHREACT_Unit_AddParam(unit, param); + xunit->nextAddTime=GWEN_Timestamp_NowInLocalTime(); + return unit; } @@ -138,6 +143,7 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p) ModuleTimerAction_List_free(xunit->actionList); AQHREACT_PrgRule_List_free(xunit->ruleList); + GWEN_Timestamp_free(xunit->nextAddTime); GWEN_FREE_OBJECT(xunit); } @@ -155,6 +161,7 @@ int _cbProcess(AQHREACT_UNIT *unit) int rv; if (xunit->ruleList==NULL) { + DBG_INFO(NULL, "Reading rules"); rv=_readRules(unit); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); @@ -163,7 +170,7 @@ int _cbProcess(AQHREACT_UNIT *unit) didSomething=1; } - rv=_checkAndAddActions(unit); + rv=_checkAndAddActions(unit, xunit); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; @@ -177,58 +184,40 @@ int _cbProcess(AQHREACT_UNIT *unit) -int _checkAndAddActions(AQHREACT_UNIT *unit) +int _checkAndAddActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit) { - AQHREACT_UNIT_TIMEPROGRAM *xunit; - GWEN_TIME *ti; int didSomething=0; xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit); - ti=GWEN_CurrentTime(); - if (ti) { - int hours; - int mins; - int secs; - int hourMins; + if (xunit) { + time_t now; int rv; - /* translate current time */ - rv=GWEN_Time_GetBrokenDownTime(ti, &hours, &mins, &secs); - if (rv<0) { - DBG_INFO(NULL, "here (%d)", rv); - GWEN_Time_free(ti); - return rv; - } - hourMins=(hours*60)+mins; - - rv=GWEN_Time_AddSeconds(ti, 60*60); /* next hour */ - if (rv<0) { - DBG_INFO(NULL, "here (%d)", rv); - GWEN_Time_free(ti); - return rv; + now=time(NULL); + if (now-xunit->lastCreateTime>AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEINTERVAL_SEC) { + rv=_addActionsForNextMinutes(xunit->nextAddTime, + AQHOMEREACT_UNIT_TIMEPROGRAM_CREATEINTERVAL_MIN, + xunit->ruleList, + xunit->actionList); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + return rv; + } + if (rv>0) + didSomething=1; + xunit->lastCreateTime=now; } - rv=GWEN_Time_GetBrokenDownTime(ti, &hours, &mins, &secs); - if (rv<0) { - DBG_INFO(NULL, "here (%d)", rv); - GWEN_Time_free(ti); - return rv; + if (now-xunit->lastCheckTime>AQHOMEREACT_UNIT_TIMEPROGRAM_CHECKINTERVAL_SEC) { + rv=_handlePendingActions(unit, xunit); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + return rv; + } + if (rv>0) + didSomething=1; + xunit->lastCheckTime=now; } - if (hours!=xunit->lastActionHour) { - DBG_INFO(NULL, "Adding actions for next hour %02d", hours); - _addActionsForGivenTime(ti, hours, xunit->ruleList, xunit->actionList); - xunit->lastActionHour=hours; - didSomething=1; - } - GWEN_Time_free(ti); - - rv=_handleActionsForGivenTime(unit, hourMins); - if (rv<0) { - DBG_INFO(NULL, "here (%d)", rv); - return rv; - } - if (rv>0) - didSomething=1; } return didSomething?1:0; @@ -236,64 +225,78 @@ int _checkAndAddActions(AQHREACT_UNIT *unit) -int _handleActionsForGivenTime(AQHREACT_UNIT *unit, int hourMins) +int _handlePendingActions(AQHREACT_UNIT *unit, AQHREACT_UNIT_TIMEPROGRAM *xunit) { - AQHREACT_UNIT_TIMEPROGRAM *xunit; - MODULE_TIMER_ACTION *action; int valueSent=0; - xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit); - action=ModuleTimerAction_List_First(xunit->actionList); - while(action) { - MODULE_TIMER_ACTION *nextAction; + if (unit && xunit) { + AQHREACT_PORT *outputPort; - nextAction=ModuleTimerAction_List_Next(action); - if ((hourMins>action->hourMinutes) || (hourMins+(23*60))hourMinutes) { - ModuleTimerAction_List_Del(action); - DBG_INFO(NULL, "Sending output value %.2f", action->value); - AQHREACT_Unit_OutputDoubleData(unit, AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT, action->value); - ModuleTimerAction_free(action); - valueSent=1; + outputPort=AQHREACT_Unit_GetOutputPortByIdForUnit(unit, AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT); + if (outputPort) { + GWEN_TIMESTAMP *ts; + int64_t nowInt64; + MODULE_TIMER_ACTION *action; + + ts=GWEN_Timestamp_NowInLocalTime(); + nowInt64=ts?GWEN_Timestamp_toInt64(ts):0; + GWEN_Timestamp_free(ts); + + xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit); + action=ModuleTimerAction_List_First(xunit->actionList); + while(action) { + MODULE_TIMER_ACTION *nextAction; + + nextAction=ModuleTimerAction_List_Next(action); + if (action->triggerTimevalue); + AQHREACT_Unit_OutputDoubleData(unit, outputPort, action->value); + ModuleTimerAction_free(action); + valueSent=1; + } + + action=nextAction; + } } - - action=nextAction; } - return valueSent?1:0; } -int _addActionsForGivenTime(const GWEN_TIME *ti, int hour, const AQHREACT_PRGRULE_LIST *ruleList, MODULE_TIMER_ACTION_LIST *actionList) +int _addActionsForNextMinutes(GWEN_TIMESTAMP *ts, int minutes, const AQHREACT_PRGRULE_LIST *ruleList, MODULE_TIMER_ACTION_LIST *actionList) { int actionsAdded=0; - GWEN_DATE *dt; - int dayOfMonth; - int month; - int dayOfWeek; - int mins; + int i; - dt=GWEN_Date_fromTime(ti); - month=GWEN_Date_GetMonth(dt); - dayOfMonth=GWEN_Date_GetDay(dt); - dayOfWeek=GWEN_Date_WeekDay(dt); - GWEN_Date_free(dt); - - for (mins=0; mins<60; mins++) { + for (i=0; i0) { + if (AQHREACT_PrgRule_Matches(rule, + GWEN_Timestamp_GetMinute(ts), + GWEN_Timestamp_GetHour(ts), + GWEN_Timestamp_GetDay(ts), + GWEN_Timestamp_GetMonth(ts), + GWEN_Timestamp_GetWeekDay(ts))>0) { MODULE_TIMER_ACTION *act; - act=ModuleTimerAction_new((hour*60)+mins, AQHREACT_PrgRule_GetValue(rule)); + DBG_INFO(NULL, "- rule matches for %s, creating action", GWEN_Timestamp_GetString(ts)); + act=ModuleTimerAction_new(triggerTime, AQHREACT_PrgRule_GetValue(rule)); ModuleTimerAction_List_Add(act, actionList); actionsAdded=1; } rule=AQHREACT_PrgRule_List_Next(rule); - } - } + } /* while */ + + GWEN_Timestamp_AddSeconds(ts, 60); /* next min */ + } /* for */ + return actionsAdded?1:0; } diff --git a/apps/aqhome-react/units/u_timeprogram_p.h b/apps/aqhome-react/units/u_timeprogram_p.h index 43b60fa..48085e7 100644 --- a/apps/aqhome-react/units/u_timeprogram_p.h +++ b/apps/aqhome-react/units/u_timeprogram_p.h @@ -16,6 +16,10 @@ #include "aqhome-react/types/prgrule.h" #include +#include + +#include + @@ -29,7 +33,7 @@ GWEN_LIST_FUNCTION_DEFS(MODULE_TIMER_ACTION, ModuleTimerAction) struct MODULE_TIMER_ACTION { GWEN_LIST_ELEMENT(MODULE_TIMER_ACTION) - int hourMinutes; + int64_t triggerTime; double value; }; @@ -40,6 +44,10 @@ struct AQHREACT_UNIT_TIMEPROGRAM { MODULE_TIMER_ACTION_LIST *actionList; int lastActionHour; + GWEN_TIMESTAMP *nextAddTime; + time_t lastCheckTime; + time_t lastCreateTime; + };