aqhome-react: added unit for timer programs.
This commit is contained in:
@@ -68,6 +68,13 @@ void AQHREACT_PrgRule_free(AQHREACT_PRGRULE *prgRule)
|
||||
|
||||
|
||||
|
||||
double AQHREACT_PrgRule_GetValue(const AQHREACT_PRGRULE *prgRule)
|
||||
{
|
||||
return prgRule?prgRule->value:0.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQHREACT_PrgRule_Matches(const AQHREACT_PRGRULE *prgRule, int min, int hour, int dayOfMonth, int month, int dayOfWeek)
|
||||
{
|
||||
if ((prgRule->bitfieldMonth & (1L<<month)) &&
|
||||
|
||||
@@ -22,6 +22,8 @@ GWEN_LIST_FUNCTION_DEFS(AQHREACT_PRGRULE, AQHREACT_PrgRule)
|
||||
AQHREACT_PRGRULE *AQHREACT_PrgRule_new(void);
|
||||
void AQHREACT_PrgRule_free(AQHREACT_PRGRULE *prgRule);
|
||||
|
||||
double AQHREACT_PrgRule_GetValue(const AQHREACT_PRGRULE *prgRule);
|
||||
|
||||
int AQHREACT_PrgRule_Matches(const AQHREACT_PRGRULE *prgRule, int min, int hour, int dayOfMonth, int month, int dayOfWeek);
|
||||
|
||||
AQHREACT_PRGRULE *AQHREACT_PrgRule_List_FindMatchingRule(AQHREACT_PRGRULE_LIST *prgRuleList,
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
u_module_p.h
|
||||
u_suntime.h
|
||||
u_suntime_p.h
|
||||
u_timeprogram.h
|
||||
u_timeprogram_p.h
|
||||
</headers>
|
||||
|
||||
<sources>
|
||||
@@ -67,6 +69,7 @@
|
||||
u_zeroposnegstring.c
|
||||
u_module.c
|
||||
u_suntime.c
|
||||
u_timeprogram.c
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
|
||||
325
apps/aqhome-react/units/u_timeprogram.c
Normal file
325
apps/aqhome-react/units/u_timeprogram.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "./u_timeprogram_p.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/xml.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/gwendate.h>
|
||||
#include <gwenhywfar/gwentime.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defines
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT 0
|
||||
|
||||
|
||||
GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, 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);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
GWEN_LIST_FUNCTIONS(MODULE_TIMER_ACTION, ModuleTimerAction);
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
* ModuleTimerAction
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
*/
|
||||
|
||||
MODULE_TIMER_ACTION *ModuleTimerAction_new(int hourTime, double value)
|
||||
{
|
||||
MODULE_TIMER_ACTION *act;
|
||||
|
||||
GWEN_NEW_OBJECT(MODULE_TIMER_ACTION, act);
|
||||
GWEN_LIST_INIT(MODULE_TIMER_ACTION, act);
|
||||
|
||||
act->hourMinutes=hourTime;
|
||||
act->value=value;
|
||||
|
||||
return act;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ModuleTimerAction_free(MODULE_TIMER_ACTION *act)
|
||||
{
|
||||
if (act) {
|
||||
GWEN_LIST_FINI(MODULE_TIMER_ACTION, act);
|
||||
GWEN_FREE_OBJECT(act);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
* AqHomeReact_UnitTimeProgram
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
*/
|
||||
|
||||
AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQHOME_REACT *aqh)
|
||||
{
|
||||
AQHREACT_UNIT *unit;
|
||||
AQHREACT_UNIT_TIMEPROGRAM *xunit;
|
||||
AQHREACT_PORT *port;
|
||||
AQHREACT_PARAM *param;
|
||||
|
||||
unit=AQHREACT_Unit_new(aqh);
|
||||
GWEN_NEW_OBJECT(AQHREACT_UNIT_TIMEPROGRAM, xunit);
|
||||
GWEN_INHERIT_SETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit, xunit, _freeData);
|
||||
|
||||
xunit->actionList=ModuleTimerAction_List_new();
|
||||
AQHREACT_Unit_SetProcessFn(unit, _cbProcess);
|
||||
|
||||
port=AQHREACT_Port_new();
|
||||
AQHREACT_Port_SetName(port, "output");
|
||||
AQHREACT_Port_SetIdForUnit(port, AQHOMEREACT_UNIT_TIMEPROGRAM_OUTSLOT_OUTPUT);
|
||||
AQHREACT_Port_SetDataType(port, AQHREACT_DATAOBJECTTYPE_DOUBLE);
|
||||
AQHREACT_Unit_AddOutputPort(unit, port);
|
||||
|
||||
param=AQHREACT_Param_new();
|
||||
AQHREACT_Param_SetName(param, AQHOMEREACT_UNIT_TIMEPROGRAM_PARAM_RULES);
|
||||
AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_STRING);
|
||||
AQHREACT_Unit_AddParam(unit, param);
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p)
|
||||
{
|
||||
AQHREACT_UNIT_TIMEPROGRAM *xunit;
|
||||
|
||||
xunit=(AQHREACT_UNIT_TIMEPROGRAM*) p;
|
||||
|
||||
ModuleTimerAction_List_free(xunit->actionList);
|
||||
AQHREACT_PrgRule_List_free(xunit->ruleList);
|
||||
GWEN_FREE_OBJECT(xunit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _cbProcess(AQHREACT_UNIT *unit)
|
||||
{
|
||||
int didSomething=0;
|
||||
|
||||
if (unit) {
|
||||
AQHREACT_UNIT_TIMEPROGRAM *xunit;
|
||||
|
||||
xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit);
|
||||
if (xunit) {
|
||||
int rv;
|
||||
|
||||
if (xunit->ruleList==NULL) {
|
||||
rv=_readRules(unit);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
didSomething=1;
|
||||
}
|
||||
|
||||
rv=_checkAndAddActions(unit);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
if (rv>0)
|
||||
didSomething=1;
|
||||
}
|
||||
}
|
||||
return didSomething?1:0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkAndAddActions(AQHREACT_UNIT *unit)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
rv=GWEN_Time_GetBrokenDownTime(ti, &hours, &mins, &secs);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
GWEN_Time_free(ti);
|
||||
return rv;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleActionsForGivenTime(AQHREACT_UNIT *unit, int hourMins)
|
||||
{
|
||||
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;
|
||||
|
||||
nextAction=ModuleTimerAction_List_Next(action);
|
||||
if ((hourMins>action->hourMinutes) || (hourMins+(23*60))<action->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;
|
||||
}
|
||||
|
||||
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 actionsAdded=0;
|
||||
GWEN_DATE *dt;
|
||||
int dayOfMonth;
|
||||
int month;
|
||||
int dayOfWeek;
|
||||
int mins;
|
||||
|
||||
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++) {
|
||||
const AQHREACT_PRGRULE *rule;
|
||||
|
||||
rule=AQHREACT_PrgRule_List_First(ruleList);
|
||||
while(rule) {
|
||||
if (AQHREACT_PrgRule_Matches(rule, mins, hour, dayOfMonth, month, dayOfWeek)>0) {
|
||||
MODULE_TIMER_ACTION *act;
|
||||
|
||||
act=ModuleTimerAction_new((hour*60)+mins, AQHREACT_PrgRule_GetValue(rule));
|
||||
ModuleTimerAction_List_Add(act, actionList);
|
||||
actionsAdded=1;
|
||||
}
|
||||
rule=AQHREACT_PrgRule_List_Next(rule);
|
||||
}
|
||||
}
|
||||
return actionsAdded?1:0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readRules(AQHREACT_UNIT *unit)
|
||||
{
|
||||
AQHREACT_UNIT_TIMEPROGRAM *xunit;
|
||||
const char *s;
|
||||
|
||||
xunit=GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_TIMEPROGRAM, unit);
|
||||
AQHREACT_PrgRule_List_free(xunit->ruleList);
|
||||
xunit->ruleList=NULL;
|
||||
|
||||
s=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_TIMEPROGRAM_PARAM_RULES, NULL);
|
||||
if (s) {
|
||||
xunit->ruleList=AQHREACT_PrgRule_ReadRules(s);
|
||||
if (xunit->ruleList==NULL) {
|
||||
DBG_INFO(NULL, "Error reading rules from [%s]", s);
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No rules");
|
||||
return GWEN_ERROR_NO_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
26
apps/aqhome-react/units/u_timeprogram.h
Normal file
26
apps/aqhome-react/units/u_timeprogram.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOMEREACT_U_TIMEPROGRAM_H
|
||||
#define AQHOMEREACT_U_TIMEPROGRAM_H
|
||||
|
||||
|
||||
#include "aqhome-react/aqhome_react.h"
|
||||
#include "aqhome-react/types/unit.h"
|
||||
|
||||
|
||||
#define AQHOMEREACT_UNIT_TIMEPROGRAM_PARAM_RULES "rules"
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT *AqHomeReact_UnitTimeProgram_new(AQHOME_REACT *aqh);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
49
apps/aqhome-react/units/u_timeprogram_p.h
Normal file
49
apps/aqhome-react/units/u_timeprogram_p.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2024 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOMEREACT_U_TIMEPROGRAM_P_H
|
||||
#define AQHOMEREACT_U_TIMEPROGRAM_P_H
|
||||
|
||||
|
||||
#include "./u_timeprogram.h"
|
||||
|
||||
#include "aqhome-react/aqhome_react.h"
|
||||
#include "aqhome-react/types/unit.h"
|
||||
#include "aqhome-react/types/prgrule.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
|
||||
|
||||
|
||||
typedef struct MODULE_TIMER_ACTION MODULE_TIMER_ACTION;
|
||||
typedef struct AQHREACT_UNIT_TIMEPROGRAM AQHREACT_UNIT_TIMEPROGRAM;
|
||||
|
||||
GWEN_LIST_FUNCTION_DEFS(MODULE_TIMER_ACTION, ModuleTimerAction)
|
||||
|
||||
|
||||
|
||||
struct MODULE_TIMER_ACTION {
|
||||
GWEN_LIST_ELEMENT(MODULE_TIMER_ACTION)
|
||||
|
||||
int hourMinutes;
|
||||
double value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct AQHREACT_UNIT_TIMEPROGRAM {
|
||||
AQHREACT_PRGRULE_LIST *ruleList;
|
||||
MODULE_TIMER_ACTION_LIST *actionList;
|
||||
|
||||
int lastActionHour;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user