386 lines
8.8 KiB
C
386 lines
8.8 KiB
C
/****************************************************************************
|
|
* 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 "./aqhome_react_p.h"
|
|
#include "./net_read.h"
|
|
#include "aqhome-react/units/u_logical.h"
|
|
#include "aqhome-react/units/u_valuefilter.h"
|
|
#include "aqhome-react/units/u_valueset.h"
|
|
#include "aqhome-react/units/u_varset.h"
|
|
#include "aqhome-react/units/u_stabilize.h"
|
|
#include "aqhome-react/units/u_lowpass.h"
|
|
#include "aqhome-react/units/u_highpass.h"
|
|
#include "aqhome-react/units/u_zeroposnegstring.h"
|
|
#include "aqhome-react/units/u_suntime.h"
|
|
#include "aqhome-react/units/u_varchanges.h"
|
|
#include "aqhome-react/units/u_timeprogram.h"
|
|
#include "aqhome-react/units/u_statfns.h"
|
|
|
|
#include "aqhome/data/vars_dbwrite.h"
|
|
|
|
#include <gwenhywfar/misc.h>
|
|
#include <gwenhywfar/debug.h>
|
|
|
|
|
|
|
|
AQHOME_REACT *AqHomeReact_new()
|
|
{
|
|
AQHOME_REACT *aqh;
|
|
|
|
GWEN_NEW_OBJECT(AQHOME_REACT, aqh);
|
|
aqh->unitList=AQHREACT_Unit_List_new();
|
|
|
|
return aqh;
|
|
}
|
|
|
|
|
|
|
|
void AqHomeReact_free(AQHOME_REACT *aqh)
|
|
{
|
|
if (aqh) {
|
|
AQHREACT_Unit_List_free(aqh->unitList);
|
|
GWEN_MsgEndpoint_free(aqh->brokerEndpoint);
|
|
GWEN_DB_Group_free(aqh->dbArgs);
|
|
free(aqh->varsFile);
|
|
free(aqh->pidFile);
|
|
|
|
GWEN_FREE_OBJECT(aqh);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GWEN_MSG_ENDPOINT *AqHomeReact_GetBrokerEndpoint(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?(aqh->brokerEndpoint):NULL;
|
|
}
|
|
|
|
|
|
|
|
GWEN_DB_NODE *AqHomeReact_GetDbArgs(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?(aqh->dbArgs):NULL;
|
|
}
|
|
|
|
|
|
|
|
const char *AqHomeReact_GetPidFile(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->pidFile:NULL;
|
|
}
|
|
|
|
|
|
|
|
void AqHomeReact_SetPidFile(AQHOME_REACT *aqh, const char *s)
|
|
{
|
|
if (aqh) {
|
|
free(aqh->pidFile);
|
|
aqh->pidFile=s?strdup(s):NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const char *AqHomeReact_GetVarsFile(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->varsFile:NULL;
|
|
}
|
|
|
|
|
|
|
|
void AqHomeReact_SetVarsFile(AQHOME_REACT *aqh, const char *s)
|
|
{
|
|
if (aqh) {
|
|
free(aqh->varsFile);
|
|
aqh->varsFile=s?strdup(s):NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_GetTimeout(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->timeout:0;
|
|
}
|
|
|
|
|
|
|
|
time_t AqHomeReact_GetLatestNetworkFileTime(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->latestNetworkFileTime:0;
|
|
}
|
|
|
|
|
|
|
|
void AqHomeReact_SetLatestNetworkFileTime(AQHOME_REACT *aqh, time_t t)
|
|
{
|
|
if (aqh)
|
|
aqh->latestNetworkFileTime=t;
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *AqHomeReact_GetTimerUnit(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->timerUnit:NULL;
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *AqHomeReact_GetServerVarChangeUnit(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->serverVarChangeUnit:NULL;
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *AqHomeReact_FindUnitByUnitId(const AQHOME_REACT *aqh, const char *unitId)
|
|
{
|
|
if (aqh && unitId && *unitId) {
|
|
AQHREACT_UNIT *unit;
|
|
|
|
unit=AQHREACT_Unit_List_GetById(aqh->unitList, unitId);
|
|
if (unit==NULL) {
|
|
DBG_ERROR(NULL, "Unit \"%s\" not found", unitId);
|
|
return NULL;
|
|
}
|
|
return unit;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
void AqHomeReact_AddUnit(AQHOME_REACT *aqh, AQHREACT_UNIT *unit)
|
|
{
|
|
if (aqh && unit)
|
|
AQHREACT_Unit_List_Add(unit, aqh->unitList);
|
|
}
|
|
|
|
|
|
|
|
AQH_VARS *AqHomeReact_GetLocalVars(const AQHOME_REACT *aqh)
|
|
{
|
|
return aqh?aqh->localVars:NULL;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_SetCharValue(AQHOME_REACT *aqh, const char *path, const char *value)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
int rv;
|
|
uint64_t timestamp;
|
|
|
|
timestamp=(uint64_t) time(NULL);
|
|
rv=AQH_Vars_SetCharValue(aqh->localVars, AQH_VARS_PATHFLAGS_OVERWRITE_VARS, path, value);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
AqHomeReact_UnitVarChanges_StringVarUpdated(aqh->localVarChangeUnit, path, timestamp, value);
|
|
return 0;
|
|
}
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
|
|
|
|
const char *AqHomeReact_GetCharValue(AQHOME_REACT *aqh, const char *path, int idx, const char *defaultValue)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
return AQH_Vars_GetCharValue(aqh->localVars, path, idx, defaultValue);
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_SetDoubleValue(AQHOME_REACT *aqh, const char *path, double value)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
int rv;
|
|
uint64_t timestamp;
|
|
|
|
timestamp=(uint64_t) time(NULL);
|
|
rv=AQH_Vars_SetDoubleValue(aqh->localVars, AQH_VARS_PATHFLAGS_OVERWRITE_VARS, path, value);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
AqHomeReact_UnitVarChanges_DoubleVarUpdated(aqh->localVarChangeUnit, path, timestamp, value);
|
|
return 0;
|
|
}
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
|
|
|
|
double AqHomeReact_GetDoubleValue(AQHOME_REACT *aqh, const char *path, int idx, double defaultValue)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
return AQH_Vars_GetDoubleValue(aqh->localVars, path, idx, defaultValue);
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_SetIntValue(AQHOME_REACT *aqh, const char *path, int value)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
int rv;
|
|
uint64_t timestamp;
|
|
|
|
timestamp=(uint64_t) time(NULL);
|
|
rv=AQH_Vars_SetIntValue(aqh->localVars, AQH_VARS_PATHFLAGS_OVERWRITE_VARS, path, value);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
AqHomeReact_UnitVarChanges_IntVarUpdated(aqh->localVarChangeUnit, path, timestamp, value);
|
|
return 0;
|
|
}
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_GetIntValue(AQHOME_REACT *aqh, const char *path, int idx, int defaultValue)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
return AQH_Vars_GetIntValue(aqh->localVars, path, idx, defaultValue);
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_IncIntValue(AQHOME_REACT *aqh, const char *path, int startValue, int defaultValue)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
int v;
|
|
|
|
v=AQH_Vars_GetIntValue(aqh->localVars, path, 0, startValue);
|
|
v++;
|
|
AqHomeReact_SetIntValue(aqh, path, v);
|
|
return v;
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_DecIntValue(AQHOME_REACT *aqh, const char *path, int startValue, int defaultValue)
|
|
{
|
|
if (aqh && aqh->localVars && path && *path) {
|
|
int v;
|
|
|
|
v=AQH_Vars_GetIntValue(aqh->localVars, path, 0, startValue);
|
|
v--;
|
|
AqHomeReact_SetIntValue(aqh, path, v);
|
|
return v;
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
int AqHomeReact_WriteVarsFile(AQHOME_REACT *aqh)
|
|
{
|
|
if (aqh && aqh->localVars && aqh->varsFile) {
|
|
int rv;
|
|
|
|
rv=AQH_Vars_WriteDbFile(aqh->localVars, aqh->varsFile);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *AqHomeReact_CreateUnitByName(AQHOME_REACT *aqh, const char *unitType)
|
|
{
|
|
/* this does not include u_timer and u_varchanges, because those are only created once globally in init.c */
|
|
if (aqh && unitType && *unitType) {
|
|
if (strcasecmp(unitType, "or")==0)
|
|
return AqHomeReact_UnitOr_new(aqh);
|
|
else if (strcasecmp(unitType, "and")==0)
|
|
return AqHomeReact_UnitAnd_new(aqh);
|
|
else if (strcasecmp(unitType, "xor")==0)
|
|
return AqHomeReact_UnitXor_new(aqh);
|
|
else if (strcasecmp(unitType, "valueFilter")==0)
|
|
return AqHomeReact_UnitValueFilter_new(aqh);
|
|
else if (strcasecmp(unitType, "valueSet")==0)
|
|
return AqHomeReact_UnitValueSet_new(aqh);
|
|
else if (strcasecmp(unitType, "varSet")==0)
|
|
return AqHomeReact_UnitVarSet_new(aqh);
|
|
else if (strcasecmp(unitType, "stabilize")==0)
|
|
return AqHomeReact_UnitStabilize_new(aqh);
|
|
else if (strcasecmp(unitType, "lowPass")==0)
|
|
return AqHomeReact_UnitLowPass_new(aqh);
|
|
else if (strcasecmp(unitType, "highPass")==0)
|
|
return AqHomeReact_UnitHighPass_new(aqh);
|
|
else if (strcasecmp(unitType, "zeroPosNegString")==0)
|
|
return AqHomeReact_UnitZeroPosNegString_new(aqh);
|
|
else if (strcasecmp(unitType, "suntime")==0)
|
|
return AqHomeReact_UnitSuntime_new(aqh);
|
|
else if (strcasecmp(unitType, "timeraction")==0)
|
|
return AqHomeReact_UnitTimeProgram_new(aqh);
|
|
else if (strcasecmp(unitType, "average")==0)
|
|
return AqHomeReact_UnitAverage_new(aqh);
|
|
else if (strcasecmp(unitType, "minvalue")==0)
|
|
return AqHomeReact_UnitMinValue_new(aqh);
|
|
else if (strcasecmp(unitType, "maxvalue")==0)
|
|
return AqHomeReact_UnitMaxValue_new(aqh);
|
|
else {
|
|
AQHREACT_UNIT *unit;
|
|
|
|
DBG_INFO(NULL, "Trying to load network \"%s\"", unitType);
|
|
unit=AQHomeReact_FindAndReadDataDirNetwork(aqh, unitType);
|
|
if (unit==NULL) {
|
|
DBG_ERROR(NULL, "Unknown unit type \"%s\"", unitType);
|
|
return NULL;
|
|
}
|
|
else {
|
|
const char *s;
|
|
|
|
s=AQHREACT_Unit_GetTypeName(unit);
|
|
if (!(s && *s && strcasecmp(s, unitType)==0)) {
|
|
DBG_ERROR(NULL, "ERROR: Network file for type \"%s\" contains type \"%s\" instead", unitType, s?s:"<no name>");
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
}
|
|
return unit;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|