From a4795387432f9b59a15e355102c65f755e7d8e2a Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Fri, 12 Apr 2024 21:29:40 +0200 Subject: [PATCH] aqhome-react: enable network loading. This application has now basic functionality. --- apps/aqhome-react/aqhome_react.c | 6 + apps/aqhome-react/init.c | 8 ++ apps/aqhome-react/loop.c | 4 +- apps/aqhome-react/main.c | 3 + apps/aqhome-react/net_read.c | 134 ++++++++++++++----- apps/aqhome-react/networks/tvlight.xml | 6 +- apps/aqhome-react/types/dataobject.c | 35 +++++ apps/aqhome-react/types/dataobject.h | 5 + apps/aqhome-react/types/inputslot.c | 46 +++++++ apps/aqhome-react/types/inputslot.h | 3 + apps/aqhome-react/types/link.c | 35 +++++ apps/aqhome-react/types/link.h | 3 + apps/aqhome-react/types/outputslot.c | 51 +++++++ apps/aqhome-react/types/outputslot.h | 3 + apps/aqhome-react/types/param.c | 112 ++++++++++++++++ apps/aqhome-react/types/param.h | 6 + apps/aqhome-react/types/unit.c | 77 ++++++++++- apps/aqhome-react/types/unit.h | 3 + apps/aqhome-react/types/unitnet.c | 33 +++++ apps/aqhome-react/types/unitnet.h | 2 + apps/aqhome-react/units/u_stabilize.c | 30 ++++- apps/aqhome-react/units/u_valuefilter.c | 7 +- apps/aqhome-react/units/u_valueset.c | 80 ++++++++++- apps/aqhome-react/units/u_varchanges.c | 2 +- apps/aqhome-react/units/u_zeroposnegstring.c | 30 ++--- 25 files changed, 648 insertions(+), 76 deletions(-) diff --git a/apps/aqhome-react/aqhome_react.c b/apps/aqhome-react/aqhome_react.c index 8ad08fd..8dc6252 100644 --- a/apps/aqhome-react/aqhome_react.c +++ b/apps/aqhome-react/aqhome_react.c @@ -13,9 +13,11 @@ #include "./aqhome_react_p.h" #include "aqhome-react/units/u_or.h" #include "aqhome-react/units/u_valuefilter.h" +#include "aqhome-react/units/u_valueset.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 @@ -193,12 +195,16 @@ AQHREACT_UNIT *AqHomeReact_CreateUnitByName(AQHOME_REACT *aqh, const char *unitT return AqHomeReact_UnitOr_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, "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 { DBG_ERROR(NULL, "Unknown unit type \"%s\"", unitType); return NULL; diff --git a/apps/aqhome-react/init.c b/apps/aqhome-react/init.c index 464f93f..6224655 100644 --- a/apps/aqhome-react/init.c +++ b/apps/aqhome-react/init.c @@ -124,6 +124,14 @@ void AqHomeReact_ReloadUnitNets(AQHOME_REACT *aqh) if (unitNetList) { AQHREACT_UnitNet_List_free(aqh->unitNetList); aqh->unitNetList=unitNetList; + { + GWEN_BUFFER *dbuf; + + dbuf=GWEN_Buffer_new(0, 256, 0, 1); + AQHREACT_UnitNet_List_Dump(unitNetList, dbuf, 2, "Loaded networks:"); + fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(dbuf)); + GWEN_Buffer_free(dbuf); + } } else { DBG_INFO(NULL, "No unit nets read"); diff --git a/apps/aqhome-react/loop.c b/apps/aqhome-react/loop.c index 327a7a7..cb4c6c9 100644 --- a/apps/aqhome-react/loop.c +++ b/apps/aqhome-react/loop.c @@ -58,7 +58,7 @@ void AqHomeReact_IoLoop(AQHOME_REACT *aqh, int timeoutInMilliSecs) code=GWEN_IpcMsg_GetCode(msg); if (code==AQH_MSGTYPE_IPC_DATA_DATACHANGED) { - DBG_INFO(NULL, "Received expected IPC message"); + DBG_DEBUG(NULL, "Received expected IPC message"); _handleDataResponse(aqh->varChangeUnit, msg); } else if (code==AQH_MSGTYPE_IPC_DATA_RESULT) { @@ -118,7 +118,7 @@ int _processNet(AQHREACT_UNIT_NET *unitNet) const char *netName; netName=AQHREACT_UnitNet_GetName(unitNet); - DBG_INFO(NULL, "Processing net \"%s\"", netName?netName:""); + DBG_DEBUG(NULL, "Processing net \"%s\"", netName?netName:""); unitList=AQHREACT_UnitNet_GetUnitList(unitNet); if (unitList) { int result=0; diff --git a/apps/aqhome-react/main.c b/apps/aqhome-react/main.c index a1f01a6..b267409 100644 --- a/apps/aqhome-react/main.c +++ b/apps/aqhome-react/main.c @@ -151,6 +151,8 @@ void _serve(AQHOME_REACT *aqh) lastTimerTime=startTime; lastFileScanTime=startTime; + AqHomeReact_SetLatestNetworkFileTime(aqh, AQHomeReact_GetNewestUnitNetFiletime(aqh)); + dbArgs=AqHomeReact_GetDbArgs(aqh); timerUnit=AqHomeReact_GetTimerUnit(aqh); @@ -189,6 +191,7 @@ void _serve(AQHOME_REACT *aqh) AqHomeReact_ReloadUnitNets(aqh); AqHomeReact_SetLatestNetworkFileTime(aqh, tNew); } + lastFileScanTime=now; } if (timeout) { diff --git a/apps/aqhome-react/net_read.c b/apps/aqhome-react/net_read.c index 60a7bcf..f34672c 100644 --- a/apps/aqhome-react/net_read.c +++ b/apps/aqhome-react/net_read.c @@ -39,11 +39,12 @@ static GWEN_XMLNODE *_readNetworkFromSysconfIntoXml(AQHOME_REACT *aqh, const cha static AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode); static GWEN_XMLNODE *_readUnitNetFileToXml(AQHOME_REACT *aqh, const char *sFilename); static void _readNetParamDefsWithList(AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *unitNetNode); -static int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode); +static int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode, GWEN_DB_NODE *dbNetParams); static int _readLinks(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode); -static AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode); -static int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *parentNode); -static int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *paramNode); +static AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode, GWEN_DB_NODE *dbNetParams); +static int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *parentNode, GWEN_DB_NODE *dbNetParams); +static int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *paramNode, GWEN_DB_NODE *dbNetParams); +static int _setParamDataFromString(AQHREACT_PARAM *param, const char *value); static AQHREACT_PARAM *_readNetParamDef(GWEN_XMLNODE *paramNode); static int _readLink(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *linkNode); static int _setParamDoubleValueFromString(AQHREACT_PARAM *param, const char *s); @@ -239,6 +240,7 @@ AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetN AQHREACT_UNIT_NET *unitNet; const char *s; int rv; + GWEN_DB_NODE *dbNetParams=NULL; unitNet=AQHREACT_UnitNet_new(); s=GWEN_XMLNode_GetProperty(unitNetNode, "id", NULL); @@ -259,7 +261,7 @@ AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetN _readNetParamDefsWithList(AQHREACT_UnitNet_GetParamList(unitNet), baseNetXml); /* also read netParams from this file (after reading from template) */ - rv=_readParamValuesForList(AQHREACT_UnitNet_GetParamList(unitNet), unitNetNode); + rv=_readParamValuesForList(AQHREACT_UnitNet_GetParamList(unitNet), unitNetNode, NULL); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); AQHREACT_UnitNet_free(unitNet); @@ -267,9 +269,20 @@ AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetN return NULL; } - rv=_readUnits(aqh, unitNet, baseNetXml); + dbNetParams=GWEN_DB_Group_new("params"); + rv=AQHREACT_Param_List_WriteIntoDb(AQHREACT_UnitNet_GetParamList(unitNet), dbNetParams, GWEN_DB_FLAGS_OVERWRITE_VARS); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); + AQHREACT_UnitNet_free(unitNet); + GWEN_XMLNode_free(baseNetXml); + return NULL; + } + + rv=_readUnits(aqh, unitNet, baseNetXml, dbNetParams); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); AQHREACT_UnitNet_free(unitNet); GWEN_XMLNode_free(baseNetXml); return NULL; @@ -278,19 +291,31 @@ AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetN rv=_readLinks(aqh, unitNet, baseNetXml); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); AQHREACT_UnitNet_free(unitNet); GWEN_XMLNode_free(baseNetXml); return NULL; } + GWEN_DB_Group_free(dbNetParams); GWEN_XMLNode_free(baseNetXml); } else { /* just directly read network from given XML node (no need to load a template file) */ _readNetParamDefsWithList(AQHREACT_UnitNet_GetParamList(unitNet), unitNetNode); - rv=_readUnits(aqh, unitNet, unitNetNode); + dbNetParams=GWEN_DB_Group_new("params"); + rv=AQHREACT_Param_List_WriteIntoDb(AQHREACT_UnitNet_GetParamList(unitNet), dbNetParams, GWEN_DB_FLAGS_OVERWRITE_VARS); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); + AQHREACT_UnitNet_free(unitNet); + return NULL; + } + + rv=_readUnits(aqh, unitNet, unitNetNode, dbNetParams); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); AQHREACT_UnitNet_free(unitNet); return NULL; } @@ -298,9 +323,11 @@ AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetN rv=_readLinks(aqh, unitNet, unitNetNode); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); + GWEN_DB_Group_free(dbNetParams); AQHREACT_UnitNet_free(unitNet); return NULL; } + GWEN_DB_Group_free(dbNetParams); } return unitNet; @@ -336,7 +363,7 @@ GWEN_XMLNODE *_readUnitNetFileToXml(AQHOME_REACT *aqh, const char *sFilename) -int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode) +int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode, GWEN_DB_NODE *dbNetParams) { GWEN_XMLNODE *nGroup; @@ -348,7 +375,7 @@ int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unit while(n) { AQHREACT_UNIT *unit; - unit=_readUnit(aqh, n); + unit=_readUnit(aqh, n, dbNetParams); if (unit) AQHREACT_UnitNet_AddUnit(unitNet, unit); else { @@ -389,7 +416,7 @@ int _readLinks(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unit -AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode) +AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode, GWEN_DB_NODE *dbNetParams) { AQHREACT_UNIT *unit; const char *unitType; @@ -406,7 +433,7 @@ AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode) unitId=GWEN_XMLNode_GetProperty(unitNode, "id", NULL); AQHREACT_Unit_SetId(unit, unitId); - rv=_readParamValuesForList(AQHREACT_Unit_GetParamList(unit), unitNode); + rv=_readParamValuesForList(AQHREACT_Unit_GetParamList(unit), unitNode, dbNetParams); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); AQHREACT_Unit_free(unit); @@ -418,7 +445,7 @@ AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode) -int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *parentNode) +int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *parentNode, GWEN_DB_NODE *dbNetParams) { GWEN_XMLNODE *nGroup; @@ -430,7 +457,7 @@ int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE * while(n) { int rv; - rv=_readParamValueForList(paramList, n); + rv=_readParamValueForList(paramList, n, dbNetParams); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; @@ -443,7 +470,7 @@ int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE * -int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *paramNode) +int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *paramNode, GWEN_DB_NODE *dbNetParams) { const char *paramName; @@ -457,29 +484,35 @@ int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *p value=GWEN_XMLNode_GetCharValue(paramNode, NULL, NULL); if (value && *value) { - int dataType; - - dataType=AQHREACT_Param_GetDataType(param); - switch(dataType) { - case AQHREACT_DATAOBJECTTYPE_DOUBLE: - { - int rv; - double valueAsDouble; - - rv=GWEN_Text_StringToDouble(value, &valueAsDouble); - if (rv<0) { - DBG_ERROR(NULL, "Not a DOUBLE value for param %s in list [%s]", paramName, value); - return rv; - } - AQHREACT_Param_SetDoubleValue(param, valueAsDouble); - break; + if (dbNetParams) { + GWEN_BUFFER *buf; + int rv; + + buf=GWEN_Buffer_new(0, 64, 0, 1); + rv=GWEN_DB_ReplaceVars(dbNetParams, value, buf); + if (rv<0) { + DBG_ERROR(NULL, "Error replacing vars for param \"%s\" (%d)", paramName, rv); + GWEN_Buffer_free(buf); + return rv; } - case AQHREACT_DATAOBJECTTYPE_STRING: - default: - AQHREACT_Param_SetStringValue(param, value); - break; + rv=_setParamDataFromString(param, GWEN_Buffer_GetStart(buf)); + if (rv<0) { + DBG_ERROR(NULL, "Error setting param data for param \"%s\" (%d)", paramName, rv); + GWEN_Buffer_free(buf); + return rv; + } + GWEN_Buffer_free(buf); } - } + else { + int rv; + + rv=_setParamDataFromString(param, value); + if (rv<0) { + DBG_ERROR(NULL, "Error setting param data for param \"%s\" (%d)", paramName, rv); + return rv; + } + } + } /* if value */ } else { DBG_ERROR(NULL, "No param name \"%s\" in list", paramName); @@ -492,6 +525,37 @@ int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *p +int _setParamDataFromString(AQHREACT_PARAM *param, const char *value) +{ + if (value && *value) { + int dataType; + + dataType=AQHREACT_Param_GetDataType(param); + switch(dataType) { + case AQHREACT_DATAOBJECTTYPE_DOUBLE: + { + int rv; + double valueAsDouble; + + rv=GWEN_Text_StringToDouble(value, &valueAsDouble); + if (rv<0) { + DBG_ERROR(NULL, "Not a DOUBLE value for param \"%s\" [%s]", AQHREACT_Param_GetName(param), value); + return rv; + } + AQHREACT_Param_SetDoubleValue(param, valueAsDouble); + break; + } + case AQHREACT_DATAOBJECTTYPE_STRING: + default: + AQHREACT_Param_SetStringValue(param, value); + break; + } + } + return 0; +} + + + void _readNetParamDefsWithList(AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *unitNetNode) { GWEN_XMLNODE *nGroup; diff --git a/apps/aqhome-react/networks/tvlight.xml b/apps/aqhome-react/networks/tvlight.xml index 05522aa..695630e 100644 --- a/apps/aqhome-react/networks/tvlight.xml +++ b/apps/aqhome-react/networks/tvlight.xml @@ -25,7 +25,7 @@ - + $(outPlugValue) @@ -54,8 +54,8 @@ - - + + diff --git a/apps/aqhome-react/types/dataobject.c b/apps/aqhome-react/types/dataobject.c index 628112d..747df6a 100644 --- a/apps/aqhome-react/types/dataobject.c +++ b/apps/aqhome-react/types/dataobject.c @@ -188,6 +188,41 @@ void AQHREACT_DataObject_SetStringData(AQHREACT_DATAOBJECT *dataObject, const ch +const char *AQHREACT_DataObjectType_toString(int t) +{ + switch(t) { + case AQHREACT_DATAOBJECTTYPE_DOUBLE: return "double"; + case AQHREACT_DATAOBJECTTYPE_STRING: return "string"; + default: return "unknown"; + } +} + + + +void AQHREACT_DataObject_Dump(const AQHREACT_DATAOBJECT *dataObject, GWEN_BUFFER *buf, int indent) +{ + if (dataObject && buf) { + const char *sVarSystemId; + + sVarSystemId=AQHREACT_DataObject_GetSystemValueId(dataObject); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + + switch(dataObject->dataType) { + case AQHREACT_DATAOBJECTTYPE_DOUBLE: + GWEN_Buffer_AppendArgs(buf, "%f (DOUBLE) [%s]\n", AQHREACT_DataObject_GetDoubleData(dataObject), sVarSystemId?sVarSystemId:""); + break; + case AQHREACT_DATAOBJECTTYPE_STRING: + GWEN_Buffer_AppendArgs(buf, "%s (STRING) [%s]\n", AQHREACT_DataObject_GetStringData(dataObject), sVarSystemId?sVarSystemId:""); + break; + default: + break; + } + } +} + + diff --git a/apps/aqhome-react/types/dataobject.h b/apps/aqhome-react/types/dataobject.h index f4b8d63..9aeb409 100644 --- a/apps/aqhome-react/types/dataobject.h +++ b/apps/aqhome-react/types/dataobject.h @@ -55,6 +55,11 @@ void AQHREACT_DataObject_SetDoubleData(AQHREACT_DATAOBJECT *dataObject, double i const char *AQHREACT_DataObject_GetStringData(const AQHREACT_DATAOBJECT *dataObject); void AQHREACT_DataObject_SetStringData(AQHREACT_DATAOBJECT *dataObject, const char *s); +void AQHREACT_DataObject_Dump(const AQHREACT_DATAOBJECT *dataObject, GWEN_BUFFER *buf, int indent); + + +const char *AQHREACT_DataObjectType_toString(int t); + #endif diff --git a/apps/aqhome-react/types/inputslot.c b/apps/aqhome-react/types/inputslot.c index c8b6221..f9920c5 100644 --- a/apps/aqhome-react/types/inputslot.c +++ b/apps/aqhome-react/types/inputslot.c @@ -180,6 +180,52 @@ void AQHREACT_InputSlot_SetCurrentDataObject(AQHREACT_INPUT_SLOT *inSlot, AQHREA +void AQHREACT_InputSlot_Dump(const AQHREACT_INPUT_SLOT *inSlot, GWEN_BUFFER *buf, int indent) +{ + if (inSlot && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "id................: %d\n", inSlot->idForUnit); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "name..............: %s\n", (inSlot->name)?(inSlot->name):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "description.......: %s\n", (inSlot->description)?(inSlot->description):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "accepted data type: %s\n", AQHREACT_DataObjectType_toString(inSlot->acceptedDataType)); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "flags.............: %08x\n", inSlot->flags); + } +} + + + +void AQHREACT_InputSlot_List_Dump(const AQHREACT_INPUT_SLOT_LIST *inSlotList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (inSlotList && buf) { + const AQHREACT_INPUT_SLOT *inSlot; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Input Slot List:\n"); + + inSlot=AQHREACT_InputSlot_List_First(inSlotList); + while(inSlot) { + GWEN_Buffer_FillWithBytes(buf, ' ', indent+2); + GWEN_Buffer_AppendString(buf, "Input Slot:\n"); + AQHREACT_InputSlot_Dump(inSlot, buf, indent+4); + inSlot=AQHREACT_InputSlot_List_Next(inSlot); + } + } +} + diff --git a/apps/aqhome-react/types/inputslot.h b/apps/aqhome-react/types/inputslot.h index cd2f5f4..ba21702 100644 --- a/apps/aqhome-react/types/inputslot.h +++ b/apps/aqhome-react/types/inputslot.h @@ -45,6 +45,9 @@ void AQHREACT_InputSlot_SetAcceptedDataType(AQHREACT_INPUT_SLOT *inSlot, int i); AQHREACT_DATAOBJECT *AQHREACT_InputSlot_GetCurrentDataObject(const AQHREACT_INPUT_SLOT *inSlot); void AQHREACT_InputSlot_SetCurrentDataObject(AQHREACT_INPUT_SLOT *inSlot, AQHREACT_DATAOBJECT *dataObject); +void AQHREACT_InputSlot_Dump(const AQHREACT_INPUT_SLOT *inSlot, GWEN_BUFFER *buf, int indent); +void AQHREACT_InputSlot_List_Dump(const AQHREACT_INPUT_SLOT_LIST *inSlotList, GWEN_BUFFER *buf, int indent, const char *title); + diff --git a/apps/aqhome-react/types/link.c b/apps/aqhome-react/types/link.c index 81fe0cf..47b2c50 100644 --- a/apps/aqhome-react/types/link.c +++ b/apps/aqhome-react/types/link.c @@ -90,4 +90,39 @@ void AQHREACT_Link_SetTargetUnit(AQHREACT_LINK *lnk, AQHREACT_UNIT *unit) +void AQHREACT_Link_Dump(const AQHREACT_LINK *lnk, GWEN_BUFFER *buf, int indent) +{ + if (lnk && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "target unit id: %s (%s), target slot id: %d\n", + (lnk->targetUnitId)?(lnk->targetUnitId):"", + (lnk->targetUnit)?"set":"not set", + lnk->targetInputSlotIdForUnit); + } +} + + + +void AQHREACT_Link_List_Dump(const AQHREACT_LINK_LIST *lnkList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (lnkList && buf) { + const AQHREACT_LINK *lnk; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Link List:\n"); + + lnk=AQHREACT_Link_List_First(lnkList); + while(lnk) { + AQHREACT_Link_Dump(lnk, buf, indent+2); + lnk=AQHREACT_Link_List_Next(lnk); + } + } +} + + + + + diff --git a/apps/aqhome-react/types/link.h b/apps/aqhome-react/types/link.h index c6ee371..6c1f72a 100644 --- a/apps/aqhome-react/types/link.h +++ b/apps/aqhome-react/types/link.h @@ -33,6 +33,9 @@ void AQHREACT_Link_SetTargetInputSlotIdForUnit(AQHREACT_LINK *lnk, int i); AQHREACT_UNIT *AQHREACT_Link_GetTargetUnit(const AQHREACT_LINK *lnk); void AQHREACT_Link_SetTargetUnit(AQHREACT_LINK *lnk, AQHREACT_UNIT *unit); +void AQHREACT_Link_Dump(const AQHREACT_LINK *lnk, GWEN_BUFFER *buf, int indent); +void AQHREACT_Link_List_Dump(const AQHREACT_LINK_LIST *lnkList, GWEN_BUFFER *buf, int indent, const char *title); + #endif diff --git a/apps/aqhome-react/types/outputslot.c b/apps/aqhome-react/types/outputslot.c index 82a3b54..429729b 100644 --- a/apps/aqhome-react/types/outputslot.c +++ b/apps/aqhome-react/types/outputslot.c @@ -157,6 +157,57 @@ void AQHREACT_OutputSlot_AddLink(AQHREACT_OUTPUT_SLOT *outSlot, AQHREACT_LINK *l +void AQHREACT_OutputSlot_Dump(const AQHREACT_OUTPUT_SLOT *outSlot, GWEN_BUFFER *buf, int indent) +{ + if (outSlot && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "id...............: %d (%d)\n", outSlot->id, outSlot->idForUnit); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "name.............: %s\n", (outSlot->name)?(outSlot->name):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "description......: %s\n", (outSlot->description)?(outSlot->description):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "emitted data type: %s\n", AQHREACT_DataObjectType_toString(outSlot->emittedDataType)); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "flags............: %08x\n", outSlot->flags); + + AQHREACT_Link_List_Dump(outSlot->linkList, buf, indent, "Link List:"); + } +} + + + +void AQHREACT_OutputSlot_List_Dump(const AQHREACT_OUTPUT_SLOT_LIST *outSlotList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (outSlotList && buf) { + const AQHREACT_OUTPUT_SLOT *outSlot; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Output Slot List:\n"); + + outSlot=AQHREACT_OutputSlot_List_First(outSlotList); + while(outSlot) { + GWEN_Buffer_FillWithBytes(buf, ' ', indent+2); + GWEN_Buffer_AppendString(buf, "Output Slot:\n"); + AQHREACT_OutputSlot_Dump(outSlot, buf, indent+4); + outSlot=AQHREACT_OutputSlot_List_Next(outSlot); + } + } +} + + + + diff --git a/apps/aqhome-react/types/outputslot.h b/apps/aqhome-react/types/outputslot.h index 585da6e..264347e 100644 --- a/apps/aqhome-react/types/outputslot.h +++ b/apps/aqhome-react/types/outputslot.h @@ -45,6 +45,9 @@ void AQHREACT_OutputSlot_SetEmittedDataType(AQHREACT_OUTPUT_SLOT *outSlot, int i AQHREACT_LINK_LIST *AQHREACT_OutputSlot_GetLinkList(const AQHREACT_OUTPUT_SLOT *outSlot); void AQHREACT_OutputSlot_AddLink(AQHREACT_OUTPUT_SLOT *outSlot, AQHREACT_LINK *lnk); +void AQHREACT_OutputSlot_Dump(const AQHREACT_OUTPUT_SLOT *outSlot, GWEN_BUFFER *buf, int indent); +void AQHREACT_OutputSlot_List_Dump(const AQHREACT_OUTPUT_SLOT_LIST *outSlotList, GWEN_BUFFER *buf, int indent, const char *title); + #endif diff --git a/apps/aqhome-react/types/param.c b/apps/aqhome-react/types/param.c index 2b7f84a..083eb98 100644 --- a/apps/aqhome-react/types/param.c +++ b/apps/aqhome-react/types/param.c @@ -14,12 +14,30 @@ #include "./param_p.h" #include "./dataobject.h" +#include +#include + GWEN_LIST_FUNCTIONS(AQHREACT_PARAM, AQHREACT_Param) +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _setDbValueFromParamString(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags); +static void _setDbValueFromParamDouble(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + AQHREACT_PARAM *AQHREACT_Param_new() { AQHREACT_PARAM *param; @@ -177,6 +195,100 @@ AQHREACT_PARAM *AQHREACT_Param_List_GetParamByName(const AQHREACT_PARAM_LIST *pa +int AQHREACT_Param_List_WriteIntoDb(const AQHREACT_PARAM_LIST *paramList, GWEN_DB_NODE *db, uint32_t dbFlags) +{ + if (paramList && db) { + const AQHREACT_PARAM *param; + + param=AQHREACT_Param_List_First(paramList); + while(param) { + if (param->name) { + switch(param->dataType) { + case AQHREACT_DATAOBJECTTYPE_STRING: + _setDbValueFromParamString(param, db, dbFlags); + break; + case AQHREACT_DATAOBJECTTYPE_DOUBLE: + _setDbValueFromParamDouble(param, db, dbFlags); + break; + default: + DBG_ERROR(NULL, "Unhandled param type %d", param->dataType); + return GWEN_ERROR_GENERIC; + } + } + + param=AQHREACT_Param_List_Next(param); + } + } + return 0; +} + + + +void _setDbValueFromParamString(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags) +{ + if (param->stringValue) + GWEN_DB_SetCharValue(db, dbFlags, param->name, param->stringValue); + else + GWEN_DB_DeleteVar(db, param->name); +} + + + +void _setDbValueFromParamDouble(const AQHREACT_PARAM *param, GWEN_DB_NODE *db, uint32_t dbFlags) +{ + GWEN_BUFFER *buf; + int rv; + + buf=GWEN_Buffer_new(0, 32, 0, 1); + rv=GWEN_Text_DoubleToBuffer(param->doubleValue, buf); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + } + else + GWEN_DB_SetCharValue(db, dbFlags, param->name, GWEN_Buffer_GetStart(buf)); + GWEN_Buffer_free(buf); +} + + + +void AQHREACT_Param_Dump(const AQHREACT_PARAM *param, GWEN_BUFFER *buf, int indent) +{ + if (param && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + + switch(param->dataType) { + case AQHREACT_DATAOBJECTTYPE_DOUBLE: + GWEN_Buffer_AppendArgs(buf, "%s = %f [DOUBLE]\n", (param->name)?(param->name):"", param->doubleValue); + break; + case AQHREACT_DATAOBJECTTYPE_STRING: + GWEN_Buffer_AppendArgs(buf, "%s = %s [STRING]\n", (param->name)?(param->name):"", param->stringValue); + break; + default: + DBG_ERROR(NULL, "Unhandled data type %d", param->dataType); + } + } +} + + + +void AQHREACT_Param_List_Dump(const AQHREACT_PARAM_LIST *paramList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (paramList && buf) { + const AQHREACT_PARAM *param; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Parameter List:\n"); + + param=AQHREACT_Param_List_First(paramList); + while(param) { + AQHREACT_Param_Dump(param, buf, indent+2); + param=AQHREACT_Param_List_Next(param); + } + } +} + diff --git a/apps/aqhome-react/types/param.h b/apps/aqhome-react/types/param.h index 0a04714..06d3548 100644 --- a/apps/aqhome-react/types/param.h +++ b/apps/aqhome-react/types/param.h @@ -10,6 +10,7 @@ #define AQHOME_REACT_PARAM_H #include +#include typedef struct AQHREACT_PARAM AQHREACT_PARAM; @@ -44,6 +45,11 @@ void AQHREACT_Param_SubFlags(AQHREACT_PARAM *param, uint32_t f); AQHREACT_PARAM *AQHREACT_Param_List_GetParamByName(const AQHREACT_PARAM_LIST *paramList, const char *paramName); +int AQHREACT_Param_List_WriteIntoDb(const AQHREACT_PARAM_LIST *paramList, GWEN_DB_NODE *db, uint32_t dbFlags); + +void AQHREACT_Param_Dump(const AQHREACT_PARAM *param, GWEN_BUFFER *buf, int indent); +void AQHREACT_Param_List_Dump(const AQHREACT_PARAM_LIST *paramList, GWEN_BUFFER *buf, int indent, const char *title); + #endif diff --git a/apps/aqhome-react/types/unit.c b/apps/aqhome-react/types/unit.c index 8beef9c..1769534 100644 --- a/apps/aqhome-react/types/unit.c +++ b/apps/aqhome-react/types/unit.c @@ -55,6 +55,13 @@ void AQHREACT_Unit_free(AQHREACT_UNIT *unit) +AQHOME_REACT *AQHREACT_Unit_GetAqHomeReact(const AQHREACT_UNIT *unit) +{ + return unit?unit->aqHomeReact:NULL; +} + + + const char *AQHREACT_Unit_GetName(const AQHREACT_UNIT *unit) { return unit?unit->name:NULL; @@ -362,8 +369,12 @@ void AQHREACT_Unit_OutputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHR targetUnit=AQHREACT_Link_GetTargetUnit(lnk); targetSlotIdForUnit=AQHREACT_Link_GetTargetInputSlotIdForUnit(lnk); - if (targetUnit && targetSlotIdForUnit>=0) + if (targetUnit && targetSlotIdForUnit>=0) { + DBG_DEBUG(NULL, "%s: Sending data to %s:%d", + AQHREACT_Unit_GetId(unit), + AQHREACT_Link_GetTargetUnitId(lnk), AQHREACT_Link_GetTargetInputSlotIdForUnit(lnk)); AQHREACT_Unit_InputData(targetUnit, targetSlotIdForUnit, dataObject); + } lnk=AQHREACT_Link_List_Next(lnk); } /* while */ } /* if linkList */ @@ -409,7 +420,18 @@ void AQHREACT_Unit_InputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHRE if (unit->inputDataFn) (unit->inputDataFn)(unit, slotIdForUnit, dataObject); else { - AQHREACT_Unit_ClearChangeFlagsInUnitAndInputSlots(unit); + if (dataObject) { + AQHREACT_INPUT_SLOT *inSlot; + + inSlot=AQHREACT_Unit_GetInputSlotByIdForUnit(unit, slotIdForUnit); + if (inSlot) { + if (AQHREACT_DataObject_GetDataType(dataObject)==AQHREACT_InputSlot_GetAcceptedDataType(inSlot)) { + AQHREACT_InputSlot_SetCurrentDataObject(inSlot, AQHREACT_DataObject_dup(dataObject)); + AQHREACT_InputSlot_AddFlags(inSlot, AQHREACT_UNIT_FLAGS_CHANGED); + AQHREACT_Unit_AddFlags(unit, AQHREACT_UNIT_FLAGS_CHANGED); + } + } + } } } else { @@ -603,6 +625,57 @@ AQHREACT_UNIT *AQHREACT_Unit_List_GetById(const AQHREACT_UNIT_LIST *unitList, co +void AQHREACT_Unit_Dump(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent) +{ + if (unit && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "id.........: %s\n", (unit->id)?(unit->id):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "name.......: %s\n", (unit->name)?(unit->name):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "description: %s\n", (unit->description)?(unit->description):""); + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "flags......: %08x\n", unit->flags); + + AQHREACT_Param_List_Dump(unit->paramList, buf, indent, "Unit Parameter List:"); + AQHREACT_InputSlot_List_Dump(unit->inputSlotList, buf, indent, "Input Slot List:"); + AQHREACT_OutputSlot_List_Dump(unit->outputSlotList, buf, indent, "Output Slot List:"); + } +} + + + +void AQHREACT_Unit_List_Dump(const AQHREACT_UNIT_LIST *unitList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (unitList && buf) { + const AQHREACT_UNIT *unit; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Unit List:\n"); + + unit=AQHREACT_Unit_List_First(unitList); + while(unit) { + GWEN_Buffer_FillWithBytes(buf, ' ', indent+2); + GWEN_Buffer_AppendString(buf, "Unit:\n"); + AQHREACT_Unit_Dump(unit, buf, indent+4); + + unit=AQHREACT_Unit_List_Next(unit); + } + + } +} + + + + diff --git a/apps/aqhome-react/types/unit.h b/apps/aqhome-react/types/unit.h index 6918fdc..e949a0c 100644 --- a/apps/aqhome-react/types/unit.h +++ b/apps/aqhome-react/types/unit.h @@ -109,6 +109,9 @@ AQHREACT_UNIT_PROCESS_FN AQHREACT_Unit_SetProcessFn(AQHREACT_UNIT *unit, AQHREAC AQHREACT_UNIT *AQHREACT_Unit_List_GetById(const AQHREACT_UNIT_LIST *unitList, const char *id); +void AQHREACT_Unit_Dump(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent); +void AQHREACT_Unit_List_Dump(const AQHREACT_UNIT_LIST *unitList, GWEN_BUFFER *buf, int indent, const char *title); + #endif diff --git a/apps/aqhome-react/types/unitnet.c b/apps/aqhome-react/types/unitnet.c index 40131d9..fcbd63b 100644 --- a/apps/aqhome-react/types/unitnet.c +++ b/apps/aqhome-react/types/unitnet.c @@ -142,6 +142,39 @@ AQHREACT_UNIT_NET *AQHREACT_UnitNet_List_GetByName(const AQHREACT_UNIT_NET_LIST +void AQHREACT_UnitNet_Dump(const AQHREACT_UNIT_NET *unitNet, GWEN_BUFFER *buf, int indent) +{ + if (unitNet && buf) { + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "Network \"%s\"\n", (unitNet->name)?(unitNet->name):""); + AQHREACT_Param_List_Dump(unitNet->paramList, buf, indent, "Network Parameter List:"); + AQHREACT_Unit_List_Dump(unitNet->unitList, buf, indent, "Unit List:"); + } +} + + + +void AQHREACT_UnitNet_List_Dump(const AQHREACT_UNIT_NET_LIST *unitNetList, GWEN_BUFFER *buf, int indent, const char *title) +{ + if (unitNetList && buf) { + const AQHREACT_UNIT_NET *unitNet; + + if (indent) + GWEN_Buffer_FillWithBytes(buf, ' ', indent); + GWEN_Buffer_AppendArgs(buf, "%s\n", (title && *title)?title:"Unit List:\n"); + + unitNet=AQHREACT_UnitNet_List_First(unitNetList); + while(unitNet) { + AQHREACT_UnitNet_Dump(unitNet, buf, indent+2); + unitNet=AQHREACT_UnitNet_List_Next(unitNet); + } + } +} + + + + diff --git a/apps/aqhome-react/types/unitnet.h b/apps/aqhome-react/types/unitnet.h index 13d8105..0ebc291 100644 --- a/apps/aqhome-react/types/unitnet.h +++ b/apps/aqhome-react/types/unitnet.h @@ -38,6 +38,8 @@ AQHREACT_PARAM *AQHREACT_UnitNet_GetParamByName(const AQHREACT_UNIT_NET *unitNet AQHREACT_UNIT_NET *AQHREACT_UnitNet_List_GetByName(const AQHREACT_UNIT_NET_LIST *unitNetList, const char *name); +void AQHREACT_UnitNet_Dump(const AQHREACT_UNIT_NET *unitNet, GWEN_BUFFER *buf, int indent); +void AQHREACT_UnitNet_List_Dump(const AQHREACT_UNIT_NET_LIST *unitNetList, GWEN_BUFFER *buf, int indent, const char *title); diff --git a/apps/aqhome-react/units/u_stabilize.c b/apps/aqhome-react/units/u_stabilize.c index d7cf257..ff48ebe 100644 --- a/apps/aqhome-react/units/u_stabilize.c +++ b/apps/aqhome-react/units/u_stabilize.c @@ -68,6 +68,7 @@ AQHREACT_UNIT *AqHomeReact_UnitStabilize_new(AQHOME_REACT *aqh) AQHREACT_UNIT *unit; AQHREACT_OUTPUT_SLOT *outputSlot; AQHREACT_INPUT_SLOT *inputSlot; + AQHREACT_PARAM *param; unit=AQHREACT_Unit_new(aqh); GWEN_NEW_OBJECT(AQHREACT_UNIT_STABILIZE, xunit); @@ -95,6 +96,16 @@ AQHREACT_UNIT *AqHomeReact_UnitStabilize_new(AQHOME_REACT *aqh) AQHREACT_InputSlot_SetAcceptedDataType(inputSlot, AQHREACT_DATAOBJECTTYPE_DOUBLE); AQHREACT_Unit_AddInputSlot(unit, inputSlot); + param=AQHREACT_Param_new(); + AQHREACT_Param_SetName(param, AQHOMEREACT_UNIT_STABILIZE_PARAM_HOLDTIME_HIGH); + AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_DOUBLE); + AQHREACT_Unit_AddParam(unit, param); + + param=AQHREACT_Param_new(); + AQHREACT_Param_SetName(param, AQHOMEREACT_UNIT_STABILIZE_PARAM_HOLDTIME_LOW); + AQHREACT_Param_SetDataType(param, AQHREACT_DATAOBJECTTYPE_DOUBLE); + AQHREACT_Unit_AddParam(unit, param); + return unit; } @@ -119,7 +130,6 @@ int _cbProcessFn(AQHREACT_UNIT *unit) AQHREACT_Unit_ClearChangeFlagsInUnitAndInputSlots(unit); return rv; } - return 0; } @@ -140,14 +150,19 @@ int _checkState(AQHREACT_UNIT *unit) dataObject=AQHREACT_InputSlot_GetCurrentDataObject(dataSlot); if (dataObject) { + double doubleData; int newState; - newState=(AQHREACT_DataObject_GetDoubleData(dataObject)>0.0)?1:0; + doubleData=AQHREACT_DataObject_GetDoubleData(dataObject); + newState=(doubleData>0.0)?1:0; + DBG_DEBUG(NULL, "Got dataObject (%f), new state is %d (previously: %d)", doubleData, newState, xunit->lastProcessedState); if (newState!=xunit->lastProcessedState) { + DBG_INFO(NULL, "Stage changed (%d->%d)", xunit->lastProcessedState, newState); _startTimer(unit, xunit, newState); result=1; } else { + DBG_DEBUG(NULL, "Stage unchanged (%d)", newState); if (_handleStateNoChange(unit, xunit, newState)>0) result=1; } @@ -166,7 +181,7 @@ int _handleStateNoChange(AQHREACT_UNIT *unit, AQHREACT_UNIT_STABILIZE *xunit, in uint64_t now; now=(uint64_t) time(NULL); - if (now>xunit->tsHoldUntil) { + if (xunit->tsHoldUntil && now>xunit->tsHoldUntil) { /* timeout, switch output */ _setOutput(unit, xunit, newState); result=1; @@ -183,15 +198,18 @@ void _startTimer(AQHREACT_UNIT *unit, AQHREACT_UNIT_STABILIZE *xunit, int newSta now=(uint64_t) time(NULL); - DBG_INFO(NULL, "Starting timeout counter (%d)", newState); if (newState) holdTime=AQHREACT_Unit_GetParamValueDouble(unit, AQHOMEREACT_UNIT_STABILIZE_PARAM_HOLDTIME_HIGH, 0.0); else holdTime=AQHREACT_Unit_GetParamValueDouble(unit, AQHOMEREACT_UNIT_STABILIZE_PARAM_HOLDTIME_LOW, 30.0); - if (holdTime<=0.0) + if (holdTime<=0.0) { + DBG_INFO(NULL, "Timeout is zero, immediately setting output (%d)", newState); _setOutput(unit, xunit, newState); - else + } + else { + DBG_INFO(NULL, "Starting timeout counter (%d, t=%d)", newState, holdTime); xunit->tsHoldUntil=now+holdTime; + } } diff --git a/apps/aqhome-react/units/u_valuefilter.c b/apps/aqhome-react/units/u_valuefilter.c index 2bb3233..5f1d7cc 100644 --- a/apps/aqhome-react/units/u_valuefilter.c +++ b/apps/aqhome-react/units/u_valuefilter.c @@ -85,8 +85,13 @@ void _cbInputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHREACT_DATAOBJ const char *sFilter; sFilter=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUEFILTER_PARAM_VALUENAME, NULL); - if (sFilter && *sFilter && strcasecmp(sSystemValueId, sFilter)==0) + if (sFilter && *sFilter && strcasecmp(sSystemValueId, sFilter)==0) { + DBG_INFO(NULL, "Value \"%s\" matches", sSystemValueId); AQHREACT_Unit_OutputData(unit, AQHOMEREACT_UNIT_VALUEFILTER_OUTSLOT_RESULT, dataObject); + } + else { + DBG_DEBUG(NULL, "Value \"%s\" does not match", sSystemValueId); + } } } } diff --git a/apps/aqhome-react/units/u_valueset.c b/apps/aqhome-react/units/u_valueset.c index 0d7169f..8d64408 100644 --- a/apps/aqhome-react/units/u_valueset.c +++ b/apps/aqhome-react/units/u_valueset.c @@ -12,7 +12,11 @@ #include "./u_valueset.h" +#include "aqhome/ipc/data/msg_data_set.h" +#include "aqhome/ipc/data/ipc_data.h" + #include +#include @@ -31,6 +35,8 @@ */ static void _cbInputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHREACT_DATAOBJECT *dataObject); +static GWEN_MSG *_mkSetDataMsgString(AQHREACT_UNIT *unit, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); +static GWEN_MSG *_mkSetDataMsgDouble(AQHREACT_UNIT *unit, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); @@ -69,20 +75,80 @@ AQHREACT_UNIT *AqHomeReact_UnitValueSet_new(AQHOME_REACT *aqh) void _cbInputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHREACT_DATAOBJECT *dataObject) { if (unit && dataObject && slotIdForUnit==AQHOMEREACT_UNIT_VALUESET_INSLOT_VALUE) { - const char *sSystemValueId; + const char *sValueName; - sSystemValueId=AQHREACT_DataObject_GetSystemValueId(dataObject); - if (sSystemValueId && *sSystemValueId) { - const char *sValueName; + sValueName=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUENAME, NULL); + if (sValueName && *sValueName) { + GWEN_MSG_ENDPOINT *brokerEndpoint; - sValueName=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUENAME, NULL); - if (sValueName && *sValueName) { - // TODO: set value + brokerEndpoint=AqHomeReact_GetBrokerEndpoint(AQHREACT_Unit_GetAqHomeReact(unit)); + if (brokerEndpoint) { + GWEN_MSG *msgOut; + + switch(AQHREACT_DataObject_GetDataType(dataObject)) { + case AQHREACT_DATAOBJECTTYPE_DOUBLE: + msgOut=_mkSetDataMsgDouble(unit, sValueName, dataObject); + break; + case AQHREACT_DATAOBJECTTYPE_STRING: + msgOut=_mkSetDataMsgString(unit, sValueName, dataObject); + break; + default: + DBG_INFO(NULL, "Unhandled data type (%d)", AQHREACT_DataObject_GetDataType(dataObject)); + msgOut=NULL; + break; + } + if (msgOut) { + DBG_INFO(NULL, "Sending data for value \"%s\"", sValueName); + GWEN_MsgEndpoint_AddSendMessage(brokerEndpoint, msgOut); + } } } } } +GWEN_MSG *_mkSetDataMsgString(AQHREACT_UNIT *unit, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) +{ + GWEN_MSG *msgOut; + AQH_VALUE *v; + + v=AQH_Value_new(); + AQH_Value_SetNameForSystem(v, sValueName); + + msgOut=AQH_SetDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, v, AQHREACT_DataObject_GetStringData(dataObject)); + AQH_Value_free(v); + return msgOut; +} + + + +GWEN_MSG *_mkSetDataMsgDouble(AQHREACT_UNIT *unit, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) +{ + GWEN_MSG *msgOut; + AQH_VALUE *v; + double data; + GWEN_BUFFER *buf; + int rv; + + v=AQH_Value_new(); + AQH_Value_SetNameForSystem(v, sValueName); + + data=AQHREACT_DataObject_GetDoubleData(dataObject); + buf=GWEN_Buffer_new(0, 64, 0, 1); + rv=GWEN_Text_DoubleToBuffer(data, buf); + if (rv<0) { + GWEN_Buffer_free(buf); + AQH_Value_free(v); + return NULL; + } + + msgOut=AQH_SetDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_SETDATA, v, GWEN_Buffer_GetStart(buf)); + GWEN_Buffer_free(buf); + AQH_Value_free(v); + return msgOut; +} + + + diff --git a/apps/aqhome-react/units/u_varchanges.c b/apps/aqhome-react/units/u_varchanges.c index fced7c6..35ee073 100644 --- a/apps/aqhome-react/units/u_varchanges.c +++ b/apps/aqhome-react/units/u_varchanges.c @@ -34,7 +34,7 @@ void AqHomeReact_UnitVarChanges_ValueUpdated(AQHREACT_UNIT *unit, const AQH_VALU { AQHREACT_DATAOBJECT *dataObject; - DBG_INFO(NULL, "Value \"%s\" changed", AQH_Value_GetNameForSystem(value)); + DBG_DEBUG(NULL, "Value \"%s\" changed", AQH_Value_GetNameForSystem(value)); dataObject=AQHREACT_DataObject_new(); AQHREACT_DataObject_SetDataType(dataObject, AQHREACT_DATAOBJECTTYPE_DOUBLE); AQHREACT_DataObject_SetTimestamp(dataObject, timestamp); diff --git a/apps/aqhome-react/units/u_zeroposnegstring.c b/apps/aqhome-react/units/u_zeroposnegstring.c index f41dd6c..2a77867 100644 --- a/apps/aqhome-react/units/u_zeroposnegstring.c +++ b/apps/aqhome-react/units/u_zeroposnegstring.c @@ -89,28 +89,20 @@ void _cbInputData(AQHREACT_UNIT *unit, int slotIdForUnit, const AQHREACT_DATAOBJ { if (unit && dataObject) { const char *result=NULL; - const AQHREACT_INPUT_SLOT *inputSlot; + double data; - inputSlot=AQHREACT_Unit_GetInputSlotByIdForUnit(unit, slotIdForUnit); - if (inputSlot) { - AQHREACT_DATAOBJECT *dataObject; + data=AQHREACT_DataObject_GetDoubleData(dataObject); + if (data>0.0) + result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_POS, NULL); + else if (data<0.0) + result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_NEG, NULL); + else + result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_ZERO, NULL); - dataObject=AQHREACT_InputSlot_GetCurrentDataObject(inputSlot); - if (dataObject) { - double data; - - data=AQHREACT_DataObject_GetDoubleData(dataObject); - if (data>0.0) - result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_POS, NULL); - else if (data<0.0) - result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_NEG, NULL); - else - result=AQHREACT_Unit_GetParamValueString(unit, AQHOMEREACT_UNIT_VALUESET_PARAM_VALUE_ZERO, NULL); - } - } - - if (result && *result) + if (result && *result) { + DBG_DEBUG(NULL, "Sending \"%s\" to output", result); AQHREACT_Unit_OutputStringData(unit, AQHOMEREACT_UNIT_ZEROPOSNEGSTRING_OUTSLOT_RESULT, result); + } } }