aqhome-react: major rebuild of unit handling.
now nested networks are allowed to allow for complex networks.
This commit is contained in:
@@ -11,8 +11,10 @@
|
||||
#endif
|
||||
|
||||
#include "./net_read.h"
|
||||
#include "aqhome-react/aqhome_react_p.h"
|
||||
#include "aqhome-react/types/unit.h"
|
||||
#include "aqhome-react/types/unitnet.h"
|
||||
#include "aqhome-react/units/u_module.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
|
||||
@@ -32,25 +34,10 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static time_t _getNewestFiletimeFromFileList(const AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl);
|
||||
static AQHREACT_UNIT_NET_LIST *_readUnitNetFiles(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl);
|
||||
static int _readAllNetworksFromFileIntoList(AQHOME_REACT *aqh, const char *sFilename, AQHREACT_UNIT_NET_LIST *unitNetList);
|
||||
static GWEN_XMLNODE *_readNetworkFromDatadirIntoXml(AQHOME_REACT *aqh, const char *networkName);
|
||||
static AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode);
|
||||
static AQHREACT_UNIT_NET *_readUnitNetWithTemplate(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode);
|
||||
static AQHREACT_UNIT_NET *_readUnitNetNoTemplate(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, GWEN_DB_NODE *dbNetParams);
|
||||
static int _readLinks(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode, GWEN_DB_NODE *dbNetParams);
|
||||
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);
|
||||
static int _treeExpandProperties(const GWEN_XMLNODE *n, GWEN_DB_NODE *dbVars);
|
||||
static time_t _getNewestFiletimeFromFileList(const GWEN_STRINGLIST *sl);
|
||||
static AQHREACT_UNIT *_readNetworkFromFile(AQHOME_REACT *aqh, const char *filename);
|
||||
static GWEN_XMLNODE *_readUnitNetFileToXml(const char *sFilename);
|
||||
static int _readUnitNetFilesIntoList(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl, AQHREACT_UNIT_LIST *unitList);
|
||||
|
||||
|
||||
|
||||
@@ -60,18 +47,18 @@ static int _treeExpandProperties(const GWEN_XMLNODE *n, GWEN_DB_NODE *dbVars);
|
||||
*/
|
||||
|
||||
|
||||
time_t AQHomeReact_GetNewestUnitNetFiletime(const AQHOME_REACT *aqh)
|
||||
time_t AQHomeReact_GetNewestUnitNetFiletime(void)
|
||||
{
|
||||
GWEN_STRINGLIST *sl;
|
||||
time_t t1;
|
||||
time_t t2;
|
||||
|
||||
sl=AQH_GetListOfMatchingDataFiles("aqhome/react/networks", "*.xml");
|
||||
t1=_getNewestFiletimeFromFileList(aqh, sl);
|
||||
t1=_getNewestFiletimeFromFileList(sl);
|
||||
GWEN_StringList_free(sl);
|
||||
|
||||
sl=AQH_GetListOfMatchingSysconfFiles("aqhome/react/networks", "*.xml");
|
||||
t2=_getNewestFiletimeFromFileList(aqh, sl);
|
||||
t2=_getNewestFiletimeFromFileList(sl);
|
||||
GWEN_StringList_free(sl);
|
||||
|
||||
return (t1>t2)?t1:t2;
|
||||
@@ -79,32 +66,60 @@ time_t AQHomeReact_GetNewestUnitNetFiletime(const AQHOME_REACT *aqh)
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT_NET_LIST *AQHomeReact_ReadUnitNetFiles(AQHOME_REACT *aqh)
|
||||
int AQHomeReact_ReadUnitNetFiles(AQHOME_REACT *aqh)
|
||||
{
|
||||
GWEN_STRINGLIST *sl;
|
||||
|
||||
sl=AQH_GetListOfMatchingSysconfFiles("aqhome/react/networks", "*.xml");
|
||||
if (sl) {
|
||||
AQHREACT_UNIT_NET_LIST *unitNetList;
|
||||
int rv;
|
||||
|
||||
GWEN_StringList_Sort(sl, 1, GWEN_StringList_SortModeNoCase);
|
||||
unitNetList=_readUnitNetFiles(aqh, sl);
|
||||
rv=_readUnitNetFilesIntoList(aqh, sl, aqh->unitList);
|
||||
GWEN_StringList_free(sl);
|
||||
if (unitNetList==NULL) {
|
||||
DBG_INFO(NULL, "Error reading unit network files");
|
||||
return NULL;
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "Error reading unit network files (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
return unitNetList;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No unit network files");
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t _getNewestFiletimeFromFileList(const AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl)
|
||||
AQHREACT_UNIT *AQHomeReact_FindAndReadDataDirNetwork(AQHOME_REACT *aqh, const char *networkName)
|
||||
{
|
||||
AQHREACT_UNIT *unit;
|
||||
GWEN_BUFFER *bufFilename;
|
||||
GWEN_BUFFER *bufPath;
|
||||
|
||||
bufFilename=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(bufFilename, "aqhome/react/networks/%s.xml", networkName);
|
||||
bufPath=AQH_FindPathOfDataFile(GWEN_Buffer_GetStart(bufFilename));
|
||||
if (bufPath==NULL) {
|
||||
DBG_ERROR(NULL, "Network file \"%s\" not found in data folders", GWEN_Buffer_GetStart(bufFilename));
|
||||
GWEN_Buffer_free(bufFilename);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(bufFilename);
|
||||
|
||||
unit=_readNetworkFromFile(aqh, GWEN_Buffer_GetStart(bufPath));
|
||||
if (unit==NULL) {
|
||||
DBG_ERROR(NULL, "Error reading network from file \"%s\"", GWEN_Buffer_GetStart(bufPath));
|
||||
GWEN_Buffer_free(bufPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GWEN_Buffer_free(bufPath);
|
||||
return unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t _getNewestFiletimeFromFileList(const GWEN_STRINGLIST *sl)
|
||||
{
|
||||
time_t resultTime=0;
|
||||
|
||||
@@ -138,263 +153,31 @@ time_t _getNewestFiletimeFromFileList(const AQHOME_REACT *aqh, const GWEN_STRING
|
||||
|
||||
|
||||
|
||||
GWEN_XMLNODE *_readNetworkFromDatadirIntoXml(AQHOME_REACT *aqh, const char *networkName)
|
||||
AQHREACT_UNIT *_readNetworkFromFile(AQHOME_REACT *aqh, const char *filename)
|
||||
{
|
||||
GWEN_XMLNODE *n;
|
||||
GWEN_BUFFER *bufFilename;
|
||||
GWEN_BUFFER *bufPath;
|
||||
AQHREACT_UNIT *unit;
|
||||
|
||||
bufFilename=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(bufFilename, "aqhome/react/networks/");
|
||||
GWEN_Buffer_AppendString(bufFilename, networkName);
|
||||
GWEN_Buffer_AppendString(bufFilename, ".xml");
|
||||
|
||||
bufPath=AQH_FindPathOfDataFile(GWEN_Buffer_GetStart(bufFilename));
|
||||
if (bufPath==NULL) {
|
||||
DBG_ERROR(NULL, "Network file \"%s\" not found in sysconf folders", GWEN_Buffer_GetStart(bufFilename));
|
||||
GWEN_Buffer_free(bufFilename);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(bufFilename);
|
||||
|
||||
n=_readUnitNetFileToXml(aqh, GWEN_Buffer_GetStart(bufPath));
|
||||
n=_readUnitNetFileToXml(filename);
|
||||
if (n==NULL) {
|
||||
DBG_ERROR(NULL, "Error reading network file \"%s\" from sysconf dir", GWEN_Buffer_GetStart(bufPath));
|
||||
GWEN_Buffer_free(bufPath);
|
||||
DBG_ERROR(NULL, "Error reading network file \"%s\"", filename);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(bufPath);
|
||||
return n;
|
||||
|
||||
unit=AqHomeReact_UnitModule_fromXml(aqh, n);
|
||||
if (unit==NULL) {
|
||||
DBG_ERROR(NULL, "Error reading network from file \"%s\"", filename);
|
||||
GWEN_XMLNode_free(n);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GWEN_XMLNode_free(n);
|
||||
return unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT_NET_LIST *_readUnitNetFiles(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl)
|
||||
{
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
AQHREACT_UNIT_NET_LIST *unitNetList;
|
||||
|
||||
unitNetList=AQHREACT_UnitNet_List_new();
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se) {
|
||||
const char *s;
|
||||
|
||||
s=GWEN_StringListEntry_Data(se);
|
||||
if (s && *s) {
|
||||
int rv;
|
||||
|
||||
DBG_INFO(NULL, "Reading unit network file \"%s\"", s);
|
||||
rv=_readAllNetworksFromFileIntoList(aqh, s, unitNetList);
|
||||
if (rv<0 && rv!=GWEN_ERROR_NO_DATA) {
|
||||
DBG_WARN(NULL, "Error reading unit network file \"%s\" (%d), ignoring", s, rv);
|
||||
}
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
|
||||
if (AQHREACT_UnitNet_List_GetCount(unitNetList)<1) {
|
||||
AQHREACT_UnitNet_List_free(unitNetList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return unitNetList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readAllNetworksFromFileIntoList(AQHOME_REACT *aqh, const char *sFilename, AQHREACT_UNIT_NET_LIST *unitNetList)
|
||||
{
|
||||
GWEN_XMLNODE *rootNode;
|
||||
GWEN_XMLNODE *netListNode;
|
||||
GWEN_XMLNODE *netNode;
|
||||
int rv;
|
||||
|
||||
rootNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, NULL);
|
||||
rv=GWEN_XML_ReadFile(rootNode, sFilename, GWEN_XML_FLAGS_DEFAULT);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading XML file \"%s\": %d", sFilename, rv);
|
||||
GWEN_XMLNode_free(rootNode);
|
||||
return rv;
|
||||
}
|
||||
|
||||
netListNode=GWEN_XMLNode_FindFirstTag(rootNode, "networks", NULL, NULL);
|
||||
if (netListNode==NULL)
|
||||
netListNode=rootNode;
|
||||
|
||||
netNode=GWEN_XMLNode_FindFirstTag(netListNode, "network", NULL, NULL);
|
||||
while(netNode) {
|
||||
AQHREACT_UNIT_NET *unitNet;
|
||||
|
||||
unitNet=_readUnitNetFromXml(aqh, netNode);
|
||||
if (unitNet)
|
||||
AQHREACT_UnitNet_List_Add(unitNet, unitNetList);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Error loading network from file \"%s\", ignoring.", sFilename);
|
||||
}
|
||||
netNode=GWEN_XMLNode_FindNextTag(netNode, "network", NULL, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT_NET *_readUnitNetFromXml(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode)
|
||||
{
|
||||
AQHREACT_UNIT_NET *unitNet;
|
||||
const char *s;
|
||||
|
||||
s=GWEN_XMLNode_GetProperty(unitNetNode, "type", NULL);
|
||||
if (s && *s)
|
||||
unitNet=_readUnitNetWithTemplate(aqh, unitNetNode);
|
||||
else
|
||||
unitNet=_readUnitNetNoTemplate(aqh, unitNetNode);
|
||||
if (unitNet==NULL) {
|
||||
DBG_INFO(NULL, "Error reading unit");
|
||||
return NULL;
|
||||
}
|
||||
return unitNet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT_NET *_readUnitNetWithTemplate(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetXml)
|
||||
{
|
||||
AQHREACT_UNIT_NET *unitNet;
|
||||
GWEN_XMLNODE *templateNetXml;
|
||||
const char *s;
|
||||
int rv;
|
||||
GWEN_DB_NODE *dbNetParams=NULL;
|
||||
|
||||
unitNet=AQHREACT_UnitNet_new();
|
||||
s=GWEN_XMLNode_GetProperty(unitNetXml, "id", NULL);
|
||||
AQHREACT_UnitNet_SetName(unitNet, s);
|
||||
|
||||
s=GWEN_XMLNode_GetProperty(unitNetXml, "type", NULL);
|
||||
DBG_INFO(NULL, "Loading base network \"%s\"", s);
|
||||
templateNetXml=_readNetworkFromDatadirIntoXml(aqh, s);
|
||||
if (templateNetXml==NULL) {
|
||||
DBG_ERROR(NULL, "Base network \"%s\" not available (error or missing)", s);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read netParam definitions from template file */
|
||||
_readNetParamDefsWithList(AQHREACT_UnitNet_GetParamList(unitNet), templateNetXml);
|
||||
|
||||
/* also read netParams from this file (after reading from template) */
|
||||
rv=_readParamValuesForList(AQHREACT_UnitNet_GetParamList(unitNet), unitNetXml, NULL);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first read units from this file (if any) */
|
||||
rv=_readUnits(aqh, unitNet, unitNetXml, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(dbNetParams);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* then read units from template file */
|
||||
rv=_readUnits(aqh, unitNet, templateNetXml, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(dbNetParams);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read links from template file */
|
||||
rv=_readLinks(aqh, unitNet, templateNetXml, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(dbNetParams);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read additional links from this file (if any) */
|
||||
rv=_readLinks(aqh, unitNet, unitNetXml, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(dbNetParams);
|
||||
AQHREACT_UnitNet_free(unitNet);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GWEN_DB_Group_free(dbNetParams);
|
||||
GWEN_XMLNode_free(templateNetXml);
|
||||
|
||||
return unitNet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT_NET *_readUnitNetNoTemplate(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNetNode)
|
||||
{
|
||||
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);
|
||||
AQHREACT_UnitNet_SetName(unitNet, s);
|
||||
|
||||
/* just directly read network from given XML node (no need to load a template file) */
|
||||
_readNetParamDefsWithList(AQHREACT_UnitNet_GetParamList(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;
|
||||
}
|
||||
|
||||
rv=_readLinks(aqh, unitNet, unitNetNode, dbNetParams);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_XMLNODE *_readUnitNetFileToXml(AQHOME_REACT *aqh, const char *sFilename)
|
||||
GWEN_XMLNODE *_readUnitNetFileToXml(const char *sFilename)
|
||||
{
|
||||
GWEN_XMLNODE *rootNode;
|
||||
GWEN_XMLNODE *netNode;
|
||||
@@ -422,404 +205,30 @@ GWEN_XMLNODE *_readUnitNetFileToXml(AQHOME_REACT *aqh, const char *sFilename)
|
||||
|
||||
|
||||
|
||||
int _readUnits(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode, GWEN_DB_NODE *dbNetParams)
|
||||
int _readUnitNetFilesIntoList(AQHOME_REACT *aqh, const GWEN_STRINGLIST *sl, AQHREACT_UNIT_LIST *unitList)
|
||||
{
|
||||
GWEN_XMLNODE *nGroup;
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
nGroup=GWEN_XMLNode_FindFirstTag(unitNetNode, "units", NULL, NULL);
|
||||
if (nGroup) {
|
||||
GWEN_XMLNODE *n;
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se) {
|
||||
const char *s;
|
||||
|
||||
if (dbNetParams) {
|
||||
int rv;
|
||||
|
||||
rv=_treeExpandProperties(nGroup, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
n=GWEN_XMLNode_FindFirstTag(nGroup, "unit", NULL, NULL);
|
||||
while(n) {
|
||||
s=GWEN_StringListEntry_Data(se);
|
||||
if (s && *s) {
|
||||
AQHREACT_UNIT *unit;
|
||||
|
||||
unit=_readUnit(aqh, n, dbNetParams);
|
||||
if (unit)
|
||||
AQHREACT_UnitNet_AddUnit(unitNet, unit);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Error reading unit in net \"%s\"", AQHREACT_UnitNet_GetName(unitNet));
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
DBG_INFO(NULL, "Reading unit network file \"%s\"", s);
|
||||
unit=_readNetworkFromFile(aqh, s);
|
||||
if (unit==NULL) {
|
||||
DBG_WARN(NULL, "No network read from network file \"%s\"", s);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
n=GWEN_XMLNode_FindNextTag(n, "unit", NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readLinks(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *unitNetNode, GWEN_DB_NODE *dbNetParams)
|
||||
{
|
||||
GWEN_XMLNODE *nGroup;
|
||||
|
||||
nGroup=GWEN_XMLNode_FindFirstTag(unitNetNode, "links", NULL, NULL);
|
||||
if (nGroup) {
|
||||
GWEN_XMLNODE *n;
|
||||
|
||||
if (dbNetParams) {
|
||||
int rv;
|
||||
|
||||
rv=_treeExpandProperties(nGroup, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
n=GWEN_XMLNode_FindFirstTag(nGroup, "link", NULL, NULL);
|
||||
while(n) {
|
||||
int rv;
|
||||
|
||||
rv=_readLink(aqh, unitNet, n);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading link in net \"%s\" (%d)", AQHREACT_UnitNet_GetName(unitNet), rv);
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
n=GWEN_XMLNode_FindNextTag(n, "link", NULL, NULL);
|
||||
AQHREACT_Unit_List_Add(unit, unitList);
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_UNIT *_readUnit(AQHOME_REACT *aqh, GWEN_XMLNODE *unitNode, GWEN_DB_NODE *dbNetParams)
|
||||
{
|
||||
AQHREACT_UNIT *unit;
|
||||
const char *unitType;
|
||||
const char *unitId;
|
||||
int rv;
|
||||
|
||||
unitType=GWEN_XMLNode_GetProperty(unitNode, "type", NULL);
|
||||
if (!(unitType && *unitType)) {
|
||||
DBG_ERROR(NULL, "No type name in unit node");
|
||||
return NULL;
|
||||
}
|
||||
unit=AqHomeReact_CreateUnitByName(aqh, unitType);
|
||||
|
||||
unitId=GWEN_XMLNode_GetProperty(unitNode, "id", NULL);
|
||||
AQHREACT_Unit_SetId(unit, unitId);
|
||||
|
||||
rv=_readParamValuesForList(AQHREACT_Unit_GetParamList(unit), unitNode, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHREACT_Unit_free(unit);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readParamValuesForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *parentNode, GWEN_DB_NODE *dbNetParams)
|
||||
{
|
||||
GWEN_XMLNODE *nGroup;
|
||||
|
||||
nGroup=GWEN_XMLNode_FindFirstTag(parentNode, "params", NULL, NULL);
|
||||
if (nGroup) {
|
||||
GWEN_XMLNODE *n;
|
||||
|
||||
n=GWEN_XMLNode_FindFirstTag(nGroup, "param", NULL, NULL);
|
||||
while(n) {
|
||||
int rv;
|
||||
|
||||
rv=_readParamValueForList(paramList, n, dbNetParams);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
n=GWEN_XMLNode_FindNextTag(n, "param", NULL, NULL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readParamValueForList(const AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *paramNode, GWEN_DB_NODE *dbNetParams)
|
||||
{
|
||||
const char *paramName;
|
||||
|
||||
paramName=GWEN_XMLNode_GetProperty(paramNode, "name", NULL);
|
||||
if (paramName && *paramName) {
|
||||
AQHREACT_PARAM *param;
|
||||
|
||||
param=AQHREACT_Param_List_GetParamByName(paramList, paramName);
|
||||
if (param) {
|
||||
const char *value;
|
||||
|
||||
value=GWEN_XMLNode_GetCharValue(paramNode, NULL, NULL);
|
||||
if (value && *value) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _readNetParamDefsWithList(AQHREACT_PARAM_LIST *paramList, GWEN_XMLNODE *unitNetNode)
|
||||
{
|
||||
GWEN_XMLNODE *nGroup;
|
||||
|
||||
nGroup=GWEN_XMLNode_FindFirstTag(unitNetNode, "params", NULL, NULL);
|
||||
if (nGroup) {
|
||||
GWEN_XMLNODE *n;
|
||||
|
||||
n=GWEN_XMLNode_FindFirstTag(nGroup, "param", NULL, NULL);
|
||||
while(n) {
|
||||
AQHREACT_PARAM *param;
|
||||
|
||||
param=_readNetParamDef(n);
|
||||
if (param)
|
||||
AQHREACT_Param_List_Add(param, paramList);
|
||||
n=GWEN_XMLNode_FindNextTag(n, "param", NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQHREACT_PARAM *_readNetParamDef(GWEN_XMLNODE *paramNode)
|
||||
{
|
||||
const char *paramName;
|
||||
const char *paramType;
|
||||
const char *paramValue;
|
||||
|
||||
paramName=GWEN_XMLNode_GetProperty(paramNode, "name", NULL);
|
||||
paramType=GWEN_XMLNode_GetProperty(paramNode, "type", "string");
|
||||
paramValue=GWEN_XMLNode_GetCharValue(paramNode, NULL, NULL);
|
||||
|
||||
if (paramName && *paramName) {
|
||||
int t=AQHREACT_DATAOBJECTTYPE_STRING;
|
||||
AQHREACT_PARAM *param;
|
||||
|
||||
if (paramType) {
|
||||
if (strcasecmp(paramType, "string")==0)
|
||||
t=AQHREACT_DATAOBJECTTYPE_STRING;
|
||||
else if (strcasecmp(paramType, "double")==0)
|
||||
t=AQHREACT_DATAOBJECTTYPE_DOUBLE;
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid data type in parameter (%s), assuming string", paramType);
|
||||
t=AQHREACT_DATAOBJECTTYPE_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
param=AQHREACT_Param_new();
|
||||
AQHREACT_Param_SetName(param, paramName);
|
||||
AQHREACT_Param_SetDataType(param, t);
|
||||
if (paramValue && *paramValue) {
|
||||
int rv;
|
||||
|
||||
switch(t) {
|
||||
case AQHREACT_DATAOBJECTTYPE_STRING:
|
||||
AQHREACT_Param_SetStringValue(param, paramValue);
|
||||
break;
|
||||
case AQHREACT_DATAOBJECTTYPE_DOUBLE:
|
||||
rv=_setParamDoubleValueFromString(param, paramValue);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQHREACT_Param_free(param);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _setParamDoubleValueFromString(AQHREACT_PARAM *param, const char *s)
|
||||
{
|
||||
int rv;
|
||||
double value;
|
||||
|
||||
rv=GWEN_Text_StringToDouble(s, &value);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
AQHREACT_Param_SetDoubleValue(param, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _readLink(AQHOME_REACT *aqh, AQHREACT_UNIT_NET *unitNet, GWEN_XMLNODE *linkNode)
|
||||
{
|
||||
const char *sourceNetName;
|
||||
const char *sourceUnitName;
|
||||
const char *sourceSlotName;
|
||||
const char *targetNetName;
|
||||
const char *targetUnitName;
|
||||
const char *targetSlotName;
|
||||
AQHREACT_UNIT *sourceUnit;
|
||||
AQHREACT_UNIT *targetUnit;
|
||||
AQHREACT_INPUT_SLOT *inputSlot;
|
||||
AQHREACT_OUTPUT_SLOT *outputSlot;
|
||||
AQHREACT_LINK *link;
|
||||
|
||||
sourceNetName=GWEN_XMLNode_GetProperty(linkNode, "sourceNet", NULL);
|
||||
sourceUnitName=GWEN_XMLNode_GetProperty(linkNode, "sourceUnit", NULL);
|
||||
sourceSlotName=GWEN_XMLNode_GetProperty(linkNode, "sourceSlot", NULL);
|
||||
targetNetName=GWEN_XMLNode_GetProperty(linkNode, "targetNet", NULL);
|
||||
targetUnitName=GWEN_XMLNode_GetProperty(linkNode, "targetUnit", NULL);
|
||||
targetSlotName=GWEN_XMLNode_GetProperty(linkNode, "targetSlot", NULL);
|
||||
|
||||
if (!(sourceUnitName && *sourceUnitName && sourceSlotName && *sourceSlotName &&
|
||||
targetUnitName && *targetUnitName && targetSlotName && *targetSlotName)) {
|
||||
DBG_ERROR(NULL,
|
||||
"Link in net \"%s\" needs properties sourceUnit, sourceSlot, targetUnit and targetSlot",
|
||||
AQHREACT_UnitNet_GetName(unitNet));
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
sourceUnit=AQHREACT_UnitNet_GetUnitById(unitNet, sourceUnitName);
|
||||
if (sourceUnit==NULL && sourceNetName && *sourceNetName)
|
||||
sourceUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, sourceNetName, sourceUnitName);
|
||||
if (sourceUnit==NULL)
|
||||
sourceUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, NULL, sourceUnitName);
|
||||
if (sourceUnit==NULL) {
|
||||
DBG_ERROR(NULL, "Source unit \"%s\" not found", sourceUnitName);
|
||||
return GWEN_ERROR_NOT_FOUND;
|
||||
}
|
||||
outputSlot=AQHREACT_Unit_GetOutputSlotByName(sourceUnit, sourceSlotName);
|
||||
if (outputSlot==NULL) {
|
||||
DBG_ERROR(NULL, "Output slot \"%s\" not found for source unit \"%s\"", sourceSlotName, sourceUnitName);
|
||||
return GWEN_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
targetUnit=AQHREACT_UnitNet_GetUnitById(unitNet, targetUnitName);
|
||||
if (targetUnit==NULL && targetNetName && *targetNetName)
|
||||
targetUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, targetNetName, targetUnitName);
|
||||
if (targetUnit==NULL)
|
||||
targetUnit=AqHomeReact_FindUnitByNetNameAndUnitId(aqh, NULL, targetUnitName);
|
||||
if (targetUnit==NULL) {
|
||||
DBG_ERROR(NULL, "Target unit \"%s\" not found", targetUnitName);
|
||||
return GWEN_ERROR_NOT_FOUND;
|
||||
}
|
||||
inputSlot=AQHREACT_Unit_GetOrCreateUnusedInputSlotByName(targetUnit, targetSlotName);
|
||||
if (inputSlot==NULL) {
|
||||
DBG_ERROR(NULL, "Input slot \"%s\" not found for target unit \"%s\"", targetSlotName, targetUnitName);
|
||||
return GWEN_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
link=AQHREACT_Link_new();
|
||||
AQHREACT_Link_SetTargetUnitId(link, targetUnitName);
|
||||
AQHREACT_Link_SetTargetUnit(link, targetUnit);
|
||||
AQHREACT_Link_SetTargetInputSlotIdForUnit(link, AQHREACT_InputSlot_GetIdForUnit(inputSlot));
|
||||
AQHREACT_OutputSlot_AddLink(outputSlot, link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _treeExpandProperties(const GWEN_XMLNODE *n, GWEN_DB_NODE *dbVars)
|
||||
{
|
||||
int rv;
|
||||
const GWEN_XMLNODE *nn;
|
||||
|
||||
rv=GWEN_XMLNode_ExpandProperties(n, dbVars);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nn=GWEN_XMLNode_GetFirstTag(n);
|
||||
while(nn) {
|
||||
rv=_treeExpandProperties(nn, dbVars);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
nn=GWEN_XMLNode_GetNextTag(nn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user