- tested AND network and new suntime units. - add unit XML property "invert" (inverts output for logical units)
823 lines
25 KiB
C
823 lines
25 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 "./u_module_p.h"
|
|
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/xml.h>
|
|
#include <gwenhywfar/text.h>
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* defines
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
GWEN_INHERIT(AQHREACT_UNIT, AQHREACT_UNIT_MODULE);
|
|
|
|
GWEN_LIST_FUNCTIONS(MODULE_PROXY_DESCR, ModuleProxyDescr);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
|
static void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject);
|
|
static AQHREACT_PARAM *_cbGetParamByName(const AQHREACT_UNIT *unit, const char *paramName);
|
|
static int _cbProcess(AQHREACT_UNIT *unit);
|
|
static void _cbDump(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent);
|
|
|
|
static void _readProxyFromXml(GWEN_XMLNODE *xmlNode,
|
|
MODULE_PROXY_DESCR_LIST *proxyDescrList,
|
|
const char *mainGroupName,
|
|
const char *groupName,
|
|
const char *nameProperty,
|
|
const char *targetObjectProperty,
|
|
const char *targetNameProperty);
|
|
static int _readInputPortsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode);
|
|
static int _readOutputPortsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode);
|
|
static int _finishParams(AQHREACT_UNIT *unit);
|
|
static void _readUnitsFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode);
|
|
static AQHREACT_UNIT *_readOneUnitFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *xmlNode);
|
|
static int _readParamsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNodeUnit, const char *mainGroupName);
|
|
static int _readParamFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *paramNode);
|
|
static int _setParamDataFromString(AQHREACT_PARAM *param, const char *value);
|
|
static int _readLinksFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode);
|
|
static int _readLinkFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *linkNode);
|
|
static int _linkFromThisModulesInput(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingPortName,
|
|
const char *receivingUnitName,
|
|
const char *receivingPortName);
|
|
static int _linkToThisModulesOutput(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingUnitName,
|
|
const char *emittingPortName,
|
|
const char *receivingPortName);
|
|
static int _linkBetweenUnits(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingUnitName,
|
|
const char *emittingPortName,
|
|
const char *receivingUnitName,
|
|
const char *receivingPortName);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* ModuleProxyDescr
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
*/
|
|
|
|
MODULE_PROXY_DESCR *ModuleProxyDescr_new(const char *name, const char *targetObject, const char *targetName)
|
|
{
|
|
MODULE_PROXY_DESCR *pd;
|
|
|
|
GWEN_NEW_OBJECT(MODULE_PROXY_DESCR, pd);
|
|
GWEN_LIST_INIT(MODULE_PROXY_DESCR, pd);
|
|
pd->name=name?strdup(name):NULL;
|
|
pd->targetObject=targetObject?strdup(targetObject):NULL;
|
|
pd->targetName=targetName?strdup(targetName):NULL;
|
|
|
|
return pd;
|
|
}
|
|
|
|
|
|
|
|
void ModuleProxyDescr_free(MODULE_PROXY_DESCR *pd)
|
|
{
|
|
if (pd) {
|
|
GWEN_LIST_FINI(MODULE_PROXY_DESCR, pd);
|
|
free(pd->targetName);
|
|
free(pd->targetObject);
|
|
free(pd->name);
|
|
GWEN_FREE_OBJECT(pd);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
MODULE_PROXY_DESCR *ModuleProxyDescr_List_FindByName(const MODULE_PROXY_DESCR_LIST *pdList, const char *s)
|
|
{
|
|
if (pdList && s && *s) {
|
|
MODULE_PROXY_DESCR *pd;
|
|
|
|
pd=ModuleProxyDescr_List_First(pdList);
|
|
while(pd) {
|
|
if (pd->name && strcasecmp(pd->name, s)==0)
|
|
return pd;
|
|
pd=ModuleProxyDescr_List_Next(pd);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
* AqHomeReact_UnitModule
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
*/
|
|
|
|
AQHREACT_UNIT *AqHomeReact_UnitModule_new(AQHOME_REACT *aqh)
|
|
{
|
|
AQHREACT_UNIT *unit;
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
|
|
unit=AQHREACT_Unit_new(aqh);
|
|
GWEN_NEW_OBJECT(AQHREACT_UNIT_MODULE, xunit);
|
|
GWEN_INHERIT_SETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit, xunit, _freeData);
|
|
|
|
xunit->paramProxyList=ModuleProxyDescr_List_new();
|
|
xunit->unitList=AQHREACT_Unit_List_new();
|
|
|
|
AQHREACT_Unit_SetInputDataFn(unit, _cbInputData);
|
|
AQHREACT_Unit_SetGetParamByNameFn(unit, _cbGetParamByName);
|
|
AQHREACT_Unit_SetProcessFn(unit, _cbProcess);
|
|
AQHREACT_Unit_SetDumpFn(unit, _cbDump);
|
|
|
|
return unit;
|
|
}
|
|
|
|
|
|
|
|
void _freeData(GWEN_UNUSED void *bp, void *p)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*) p;
|
|
|
|
AQHREACT_Unit_List_free(xunit->unitList);
|
|
ModuleProxyDescr_List_free(xunit->paramProxyList);
|
|
|
|
GWEN_FREE_OBJECT(xunit);
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *AqHomeReact_UnitModule_fromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
AQHREACT_UNIT *unit;
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
int rv;
|
|
|
|
unit=AqHomeReact_UnitModule_new(aqh);
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
AQHREACT_Unit_SetTypeName(unit, GWEN_XMLNode_GetProperty(xmlNode, "type", NULL));
|
|
AQHREACT_Unit_SetId(unit, GWEN_XMLNode_GetProperty(xmlNode, "id", NULL));
|
|
|
|
_readProxyFromXml(xmlNode, xunit->paramProxyList, "paramdefs", "param", "name", "targetModule", "targetParam");
|
|
|
|
rv=_readInputPortsFromXml(unit, xmlNode);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
|
|
rv=_readOutputPortsFromXml(unit, xmlNode);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
|
|
_readUnitsFromXml(aqh, unit, xmlNode);
|
|
|
|
rv=_finishParams(unit);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
|
|
rv=_readParamsFromXml(unit, xmlNode, "paramDefs");
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
|
|
rv=_readLinksFromXml(aqh, unit, xmlNode);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(unit);
|
|
return NULL;
|
|
}
|
|
|
|
return unit;
|
|
}
|
|
|
|
|
|
|
|
void _cbInputData(GWEN_UNUSED AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject)
|
|
{
|
|
if (port)
|
|
AQHREACT_Port_SendData(port, dataObject);
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_PARAM *_cbGetParamByName(const AQHREACT_UNIT *unit, const char *paramName)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
|
|
DBG_INFO(NULL, "Looking for param \"%s\" in proxy descr of module \"%s\"", paramName, AQHREACT_Unit_GetTypeName(unit));
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
if (xunit) {
|
|
const MODULE_PROXY_DESCR *pd;
|
|
|
|
pd=ModuleProxyDescr_List_FindByName(xunit->paramProxyList, paramName);
|
|
if (pd) {
|
|
DBG_INFO(NULL, "Found proxydescr for param (-> %s:%s)",
|
|
(pd->targetObjectPtr)?AQHREACT_Unit_GetTypeName(pd->targetObjectPtr):"<no unit>",
|
|
(pd->targetName)?(pd->targetName):"<no param>");
|
|
return AQHREACT_Unit_GetParamByName(pd->targetObjectPtr, pd->targetName);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
int _cbProcess(AQHREACT_UNIT *unit)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
int result=0;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
if (xunit) {
|
|
AQHREACT_UNIT *subUnit;
|
|
|
|
subUnit=AQHREACT_Unit_List_First(xunit->unitList);
|
|
while(subUnit) {
|
|
int rv;
|
|
|
|
rv=AQHREACT_Unit_Process(subUnit);
|
|
if (rv<0)
|
|
result=rv;
|
|
else if (result>=0)
|
|
result=rv;
|
|
subUnit=AQHREACT_Unit_List_Next(subUnit);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void _cbDump(const AQHREACT_UNIT *unit, GWEN_BUFFER *buf, int indent)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
if (xunit)
|
|
AQHREACT_Unit_List_Dump(xunit->unitList, buf, indent, "Sub Units:");
|
|
}
|
|
|
|
|
|
|
|
void _readProxyFromXml(GWEN_XMLNODE *xmlNode,
|
|
MODULE_PROXY_DESCR_LIST *proxyDescrList,
|
|
const char *mainGroupName,
|
|
const char *groupName,
|
|
const char *nameProperty,
|
|
const char *targetObjectProperty,
|
|
const char *targetNameProperty)
|
|
{
|
|
GWEN_XMLNODE *nGroup;
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNode, mainGroupName, NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, groupName, NULL, NULL);
|
|
while(n) {
|
|
const char *name;
|
|
const char *targetObject;
|
|
const char *targetName;
|
|
|
|
name=GWEN_XMLNode_GetProperty(n, nameProperty, NULL);
|
|
targetObject=GWEN_XMLNode_GetProperty(n, targetObjectProperty, NULL);
|
|
targetName=GWEN_XMLNode_GetProperty(n, targetNameProperty, NULL);
|
|
|
|
if (name && targetObject && targetName) {
|
|
MODULE_PROXY_DESCR *pd;
|
|
|
|
pd=ModuleProxyDescr_new(name, targetObject, targetName);
|
|
ModuleProxyDescr_List_Add(pd, proxyDescrList);
|
|
}
|
|
else {
|
|
DBG_ERROR(NULL, "Incomplete entry in list \"%s\", ignoring", mainGroupName);
|
|
}
|
|
n=GWEN_XMLNode_FindNextTag(n, groupName, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int _readInputPortsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
GWEN_XMLNODE *nGroup;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNode, "inputPorts", NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "inputPort", NULL, NULL);
|
|
while(n) {
|
|
const char *name;
|
|
int dataType;
|
|
AQHREACT_PORT *port;
|
|
|
|
name=GWEN_XMLNode_GetProperty(n, "name", NULL);
|
|
dataType=AQHREACT_DataObjectType_fromString(GWEN_XMLNode_GetProperty(n, "dataType", "double"));
|
|
if (dataType==AQHREACT_DATAOBJECTTYPE_UNKNOWN) {
|
|
DBG_ERROR(NULL, "Unknown dataType: %s", GWEN_XMLNode_GetProperty(n, "dataType", "double"));
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
if (name==NULL) {
|
|
DBG_ERROR(NULL, "Missing name in input port");
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
|
|
/* create input port */
|
|
port=AQHREACT_Port_new();
|
|
AQHREACT_Port_SetName(port, name);
|
|
AQHREACT_Port_SetIdForUnit(port, ++(xunit->lastPortId));
|
|
AQHREACT_Port_SetDataType(port, dataType);
|
|
AQHREACT_Unit_AddInputPort(unit, port);
|
|
n=GWEN_XMLNode_FindNextTag(n, "inputPort", NULL, NULL);
|
|
} /* while */
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _readOutputPortsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
GWEN_XMLNODE *nGroup;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNode, "outputPorts", NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "outputPort", NULL, NULL);
|
|
while(n) {
|
|
const char *name;
|
|
int dataType;
|
|
AQHREACT_PORT *port;
|
|
|
|
name=GWEN_XMLNode_GetProperty(n, "name", NULL);
|
|
dataType=AQHREACT_DataObjectType_fromString(GWEN_XMLNode_GetProperty(n, "dataType", "double"));
|
|
if (dataType==AQHREACT_DATAOBJECTTYPE_UNKNOWN) {
|
|
DBG_ERROR(NULL, "Unknown dataType: %s", GWEN_XMLNode_GetProperty(n, "dataType", "double"));
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
if (name==NULL) {
|
|
DBG_ERROR(NULL, "Missing name in output port");
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
|
|
/* create input port */
|
|
port=AQHREACT_Port_new();
|
|
AQHREACT_Port_SetName(port, name);
|
|
AQHREACT_Port_SetIdForUnit(port, ++(xunit->lastPortId));
|
|
AQHREACT_Port_SetDataType(port, dataType);
|
|
AQHREACT_Unit_AddOutputPort(unit, port);
|
|
n=GWEN_XMLNode_FindNextTag(n, "outputPort", NULL, NULL);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _finishParams(AQHREACT_UNIT *unit)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
MODULE_PROXY_DESCR *pd;
|
|
const char *unitName;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
unitName=AQHREACT_Unit_GetTypeName(unit);
|
|
pd=ModuleProxyDescr_List_First(xunit->paramProxyList);
|
|
while(pd) {
|
|
AQHREACT_UNIT *subUnit;
|
|
|
|
subUnit=AQHREACT_Unit_List_GetById(xunit->unitList, pd->targetObject);
|
|
if (subUnit==NULL) {
|
|
DBG_ERROR(NULL, "Unit %s: Subunit \"%s\" not found for param \"%s\"", unitName, pd->targetObject, pd->name);
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
pd->targetObjectPtr=subUnit;
|
|
|
|
pd=ModuleProxyDescr_List_Next(pd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _readUnitsFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
GWEN_XMLNODE *nGroup;
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNode, "units", NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "unit", NULL, NULL);
|
|
while(n) {
|
|
AQHREACT_UNIT *subUnit;
|
|
|
|
subUnit=_readOneUnitFromXml(aqh, n);
|
|
if (subUnit)
|
|
AQHREACT_Unit_List_Add(subUnit, xunit->unitList);
|
|
else {
|
|
DBG_INFO(NULL, "Error reading unit from XML node");
|
|
}
|
|
|
|
n=GWEN_XMLNode_FindNextTag(n, "unit", NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AQHREACT_UNIT *_readOneUnitFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
const char *id;
|
|
const char *t;
|
|
const char *s;
|
|
|
|
id=GWEN_XMLNode_GetProperty(xmlNode, "id", NULL);
|
|
t=GWEN_XMLNode_GetProperty(xmlNode, "type", NULL);
|
|
s=GWEN_XMLNode_GetProperty(xmlNode, "invert", NULL);
|
|
|
|
if (id && t) {
|
|
AQHREACT_UNIT *subUnit;
|
|
int rv;
|
|
|
|
subUnit=AqHomeReact_CreateUnitByName(aqh, t);
|
|
if (subUnit==NULL) {
|
|
DBG_INFO(NULL, "Could not create unit of type \"%s\"", t);
|
|
return NULL;
|
|
}
|
|
AQHREACT_Unit_SetId(subUnit, id);
|
|
if (s && strcasecmp(s, "TRUE")==0)
|
|
AQHREACT_Unit_AddFlags(subUnit, AQHREACT_UNIT_FLAGS_INVERT);
|
|
|
|
rv=_readParamsFromXml(subUnit, xmlNode, "params");
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
AQHREACT_Unit_free(subUnit);
|
|
return NULL;
|
|
}
|
|
return subUnit;
|
|
}
|
|
else {
|
|
DBG_ERROR(NULL, "Incomplete unit, ignoring");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int _readParamsFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNodeUnit, const char *mainGroupName)
|
|
{
|
|
GWEN_XMLNODE *nGroup;
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNodeUnit, mainGroupName, NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "param", NULL, NULL);
|
|
while(n) {
|
|
int rv;
|
|
|
|
rv=_readParamFromXml(unit, n);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
n=GWEN_XMLNode_FindNextTag(n, "param", NULL, NULL);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _readParamFromXml(AQHREACT_UNIT *unit, GWEN_XMLNODE *paramNode)
|
|
{
|
|
const char *paramName;
|
|
|
|
paramName=GWEN_XMLNode_GetProperty(paramNode, "name", NULL);
|
|
if (paramName && *paramName) {
|
|
AQHREACT_PARAM *param;
|
|
|
|
param=AQHREACT_Unit_GetParamByName(unit, paramName);
|
|
if (param) {
|
|
const char *value;
|
|
|
|
value=GWEN_XMLNode_GetCharValue(paramNode, NULL, NULL);
|
|
if (value && *value) {
|
|
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 unit \"%s\"", paramName, AQHREACT_Unit_GetTypeName(unit));
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
int _readLinksFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *xmlNode)
|
|
{
|
|
GWEN_XMLNODE *nGroup;
|
|
|
|
nGroup=GWEN_XMLNode_FindFirstTag(xmlNode, "links", NULL, NULL);
|
|
if (nGroup) {
|
|
GWEN_XMLNODE *n;
|
|
|
|
n=GWEN_XMLNode_FindFirstTag(nGroup, "link", NULL, NULL);
|
|
while(n) {
|
|
int rv;
|
|
|
|
rv=_readLinkFromXml(aqh, unit, n);
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "Error reading link in net \"%s\" (%d)", AQHREACT_Unit_GetTypeName(unit), rv);
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
n=GWEN_XMLNode_FindNextTag(n, "link", NULL, NULL);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _readLinkFromXml(AQHOME_REACT *aqh, AQHREACT_UNIT *unit, GWEN_XMLNODE *linkNode)
|
|
{
|
|
const char *emittingUnitName;
|
|
const char *emittingPortName;
|
|
const char *receivingUnitName;
|
|
const char *receivingPortName;
|
|
int rv;
|
|
|
|
emittingUnitName=GWEN_XMLNode_GetProperty(linkNode, "sourceUnit", ".");
|
|
emittingPortName=GWEN_XMLNode_GetProperty(linkNode, "sourcePort", NULL);
|
|
receivingUnitName=GWEN_XMLNode_GetProperty(linkNode, "targetUnit", ".");
|
|
receivingPortName=GWEN_XMLNode_GetProperty(linkNode, "targetPort", NULL);
|
|
|
|
if (!(emittingUnitName && *emittingUnitName && emittingPortName && *emittingPortName &&
|
|
receivingUnitName && *receivingUnitName && receivingPortName && *receivingPortName)) {
|
|
DBG_ERROR(NULL,
|
|
"Link in net \"%s\" needs properties sourceUnit, sourcePort, targetUnit and targetPort",
|
|
AQHREACT_Unit_GetTypeName(unit));
|
|
return GWEN_ERROR_BAD_DATA;
|
|
}
|
|
|
|
if (strcasecmp(emittingUnitName, ".")==0)
|
|
rv=_linkFromThisModulesInput(aqh, unit, emittingPortName, receivingUnitName, receivingPortName);
|
|
else if (strcasecmp(receivingUnitName, ".")==0)
|
|
rv=_linkToThisModulesOutput(aqh, unit, emittingUnitName, emittingPortName, receivingPortName);
|
|
else
|
|
rv=_linkBetweenUnits(aqh, unit, emittingUnitName, emittingPortName, receivingUnitName, receivingPortName);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "Error creating link: %s:%s -> %s:%s (%d)",
|
|
emittingUnitName, emittingPortName, receivingUnitName, receivingPortName, rv);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _linkFromThisModulesInput(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingPortName,
|
|
const char *receivingUnitName,
|
|
const char *receivingPortName)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
AQHREACT_UNIT *receivingUnit;
|
|
AQHREACT_PORT *receivingPort;
|
|
AQHREACT_PORT *emittingPort;
|
|
AQHREACT_LINK *link;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
receivingUnit=AQHREACT_Unit_List_GetById(xunit->unitList, receivingUnitName);
|
|
if (receivingUnit==NULL)
|
|
receivingUnit=AqHomeReact_FindUnitByUnitId(aqh, receivingUnitName);
|
|
if (receivingUnit==NULL) {
|
|
DBG_ERROR(NULL, "Target unit \"%s\" not found", receivingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
emittingPort=AQHREACT_Unit_GetInputPortByName(unit, emittingPortName); /* find in modules input port list! */
|
|
if (emittingPort==NULL) {
|
|
DBG_ERROR(NULL, "Target port \"%s\" not found for source unit \"%s\"", emittingPortName, AQHREACT_Unit_GetTypeName(unit));
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
receivingPort=AQHREACT_Unit_GetOrCreateUnusedInputPortByName(receivingUnit, receivingPortName);
|
|
/*receivingPort=AQHREACT_Unit_GetInputPortByName(receivingUnit, receivingPortName);*/
|
|
if (receivingPort==NULL) {
|
|
DBG_ERROR(NULL, "Input port \"%s\" not found for target unit \"%s\"", receivingPortName, receivingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
AQHREACT_Port_AddFlags(receivingPort, AQHREACT_UNIT_FLAGS_INUSE);
|
|
|
|
link=AQHREACT_Link_new();
|
|
AQHREACT_Link_SetTargetUnit(link, receivingUnit);
|
|
AQHREACT_Link_SetTargetPort(link, receivingPort);
|
|
AQHREACT_Port_AddLink(emittingPort, link);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _linkToThisModulesOutput(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingUnitName,
|
|
const char *emittingPortName,
|
|
const char *receivingPortName)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
AQHREACT_UNIT *receivingUnit;
|
|
AQHREACT_PORT *receivingPort;
|
|
AQHREACT_UNIT *emittingUnit;
|
|
AQHREACT_PORT *emittingPort;
|
|
AQHREACT_LINK *link;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
emittingUnit=AQHREACT_Unit_List_GetById(xunit->unitList, emittingUnitName);
|
|
if (emittingUnit==NULL)
|
|
emittingUnit=AqHomeReact_FindUnitByUnitId(aqh, emittingUnitName);
|
|
if (emittingUnit==NULL) {
|
|
DBG_ERROR(NULL, "Source unit \"%s\" not found", emittingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
receivingUnit=unit;
|
|
|
|
emittingPort=AQHREACT_Unit_GetOutputPortByName(emittingUnit, emittingPortName);
|
|
if (emittingPort==NULL) {
|
|
DBG_ERROR(NULL, "Output port \"%s\" not found", emittingPortName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
receivingPort=AQHREACT_Unit_GetOutputPortByName(unit, receivingPortName); /* find in modules output port list! */
|
|
if (receivingPort==NULL) {
|
|
DBG_ERROR(NULL, "Target port \"%s\" not found", receivingPortName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
link=AQHREACT_Link_new();
|
|
AQHREACT_Link_SetTargetUnit(link, receivingUnit);
|
|
AQHREACT_Link_SetTargetPort(link, receivingPort);
|
|
AQHREACT_Port_AddLink(emittingPort, link);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _linkBetweenUnits(AQHOME_REACT *aqh,
|
|
AQHREACT_UNIT *unit,
|
|
const char *emittingUnitName,
|
|
const char *emittingPortName,
|
|
const char *receivingUnitName,
|
|
const char *receivingPortName)
|
|
{
|
|
AQHREACT_UNIT_MODULE *xunit;
|
|
AQHREACT_UNIT *receivingUnit;
|
|
AQHREACT_PORT *receivingPort;
|
|
AQHREACT_UNIT *emittingUnit;
|
|
AQHREACT_PORT *emittingPort;
|
|
AQHREACT_LINK *link;
|
|
|
|
xunit=(AQHREACT_UNIT_MODULE*)GWEN_INHERIT_GETDATA(AQHREACT_UNIT, AQHREACT_UNIT_MODULE, unit);
|
|
|
|
emittingUnit=AQHREACT_Unit_List_GetById(xunit->unitList, emittingUnitName);
|
|
if (emittingUnit==NULL)
|
|
emittingUnit=AqHomeReact_FindUnitByUnitId(aqh, emittingUnitName);
|
|
if (emittingUnit==NULL) {
|
|
DBG_ERROR(NULL, "Source unit \"%s\" not found", emittingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
receivingUnit=AQHREACT_Unit_List_GetById(xunit->unitList, receivingUnitName);
|
|
if (receivingUnit==NULL)
|
|
receivingUnit=AqHomeReact_FindUnitByUnitId(aqh, receivingUnitName);
|
|
if (receivingUnit==NULL) {
|
|
DBG_ERROR(NULL, "Target unit \"%s\" not found", receivingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
emittingPort=AQHREACT_Unit_GetOutputPortByName(emittingUnit, emittingPortName);
|
|
if (emittingPort==NULL) {
|
|
DBG_ERROR(NULL, "Output port \"%s\" not found for source unit \"%s\"", emittingPortName, emittingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
receivingPort=AQHREACT_Unit_GetOrCreateUnusedInputPortByName(receivingUnit, receivingPortName);
|
|
if (receivingPort==NULL) {
|
|
DBG_ERROR(NULL, "Input port \"%s\" not found for target unit \"%s\"", receivingPortName, receivingUnitName);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
AQHREACT_Port_AddFlags(receivingPort, AQHREACT_UNIT_FLAGS_INUSE);
|
|
|
|
link=AQHREACT_Link_new();
|
|
AQHREACT_Link_SetTargetUnit(link, receivingUnit);
|
|
AQHREACT_Link_SetTargetPort(link, receivingPort);
|
|
AQHREACT_Port_AddLink(emittingPort, link);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|