/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2025 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 #endif #include "./mdevices_page.h" #include "aqhome-cgi/service/module.h" #include "aqhome-cgi/modules/mdataclient.h" #include #include #include #include #include #include #include #include #include #include /* ------------------------------------------------------------------------------------------------ * defs and enums * ------------------------------------------------------------------------------------------------ */ #define GBAS GWEN_Buffer_AppendString #define GBAA GWEN_Buffer_AppendArgs enum { MY_LAYOUT_NONE=0, MY_LAYOUT_HORIZONTAL, MY_LAYOUT_VERTICAL }; /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _writePage(AQH_MODULE *m, AQH_DATACLIENT *dc, GWEN_XMLNODE *nPage, GWEN_BUFFER *dbuf); static void _writeItem(AQH_MODULE *m, AQH_DATACLIENT *dc, const char *sPageId, GWEN_XMLNODE *nItem, GWEN_BUFFER *dbuf); static void _writeActor(AQH_DATACLIENT *dc, const char *sPageId, GWEN_XMLNODE *n, int layout, GWEN_BUFFER *dbuf); static void _writeGraph(const char *sPageId, GWEN_XMLNODE *n, int layout, GWEN_BUFFER *dbuf); static void _handlePageActor(AQCGI_REQUEST *rq, AQH_DATACLIENT *dc, const char *sActorId, GWEN_XMLNODE *nActor); static void _handlePageGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_DATACLIENT *dc, const char *sGraphId, GWEN_XMLNODE *nGraph, GWEN_BUFFER *dbuf); static void _genPageGraph(AQH_DATACLIENT *dc, const char *sGraphId, const char *sFilename, GWEN_XMLNODE *nGraph); static void _addCurves(AQH_DATACLIENT *dc, AQDG_GRAPH *g, GWEN_XMLNODE *nGraph, uint64_t tsBegin, uint64_t tsEnd); static AQDG_GRAPH_DATAPAIR_LIST *_readCurveData(AQH_DATACLIENT *dc, GWEN_XMLNODE *nCurve, uint64_t tsBegin, uint64_t tsEnd); static uint64_t _parseTime(const char *s); static GWEN_XMLNODE *_getSubItemNode(GWEN_XMLNODE *nPage, const char *sId, const char *sElementName); static void _mkPathForGraph(AQH_MODULE *m, const char *sGraphId, GWEN_BUFFER *dbuf); static void _addGraphLink(const char *sPageId, const char *sGraphId, int w, int h, GWEN_BUFFER *dbuf); static void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf); static void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf); static void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf); static void _setRgbwData(AQH_DATACLIENT *dc, GWEN_DB_NODE *dbPost, const char *sValueName, const AQH_VALUE *value); static int _getColorComponent(GWEN_DB_NODE *dbPost, const char *sValueName, const char *sComponent, int defaultValue); static void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); static void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); static GWEN_XMLNODE *_readPage(AQH_MODULE *m, const char *sPageName); static GWEN_XMLNODE *_readPageFile(const char *sFilename); static int _layoutFromString(const char *s); /* ------------------------------------------------------------------------------------------------ * code * ------------------------------------------------------------------------------------------------ */ void AQH_ModDevices_RunPageGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) { GWEN_DB_NODE *dbQuery; const char *sPageId; DBG_INFO(NULL, "RunPageGet"); dbQuery=AQCGI_Request_GetDbQuery(rq); sPageId=GWEN_DB_GetCharValue(dbQuery, "page", 0, NULL); if (sPageId && *sPageId) { GWEN_XMLNODE *fileNode; fileNode=_readPage(m, sPageId); if (fileNode) { GWEN_XMLNODE *nPage; nPage=GWEN_XMLNode_FindFirstTag(fileNode, "page", NULL, NULL); if (nPage) { _writePage(m, dc, nPage, dbuf); AQCGI_Request_AddResponseHeaderData(rq, "Refresh: 120"); } else { DBG_ERROR(NULL, "No page element in file for \"%s\"", sPageId); } GWEN_XMLNode_free(fileNode); } else { DBG_INFO(NULL, "here"); } } } void AQH_ModDevices_RunPageGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) { GWEN_DB_NODE *dbQuery; const char *sPageId; const char *sGraphId; DBG_INFO(NULL, "RunPageGraphGet"); dbQuery=AQCGI_Request_GetDbQuery(rq); sPageId=GWEN_DB_GetCharValue(dbQuery, "page", 0, NULL); sGraphId=GWEN_DB_GetCharValue(dbQuery, "graph", 0, NULL); if (sPageId && *sPageId && sGraphId && *sGraphId) { GWEN_XMLNODE *fileNode; fileNode=_readPage(m, sPageId); if (fileNode) { GWEN_XMLNODE *nPage; GWEN_XMLNODE *nGraph; nPage=GWEN_XMLNode_FindFirstTag(fileNode, "page", "id", sPageId); nGraph=_getSubItemNode(nPage, sGraphId, "graph"); if (nPage && nGraph) _handlePageGraph(m, rq, dc, sGraphId, nGraph, dbuf); else { DBG_ERROR(NULL, "Graph %s/%s not found", sPageId, sGraphId); } GWEN_XMLNode_free(fileNode); } else { DBG_INFO(NULL, "here"); } } } void AQH_ModDevices_RunPagePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) { GWEN_DB_NODE *dbPost; const char *sPageId; const char *sActorId; DBG_INFO(NULL, "RunPagePost"); dbPost=AQCGI_Request_GetDbPostBody(rq); sPageId=GWEN_DB_GetCharValue(dbPost, "page", 0, NULL); sActorId=GWEN_DB_GetCharValue(dbPost, "actor", 0, NULL); if (sPageId && *sPageId && sActorId && *sActorId) { GWEN_XMLNODE *fileNode; fileNode=_readPage(m, sPageId); if (fileNode) { GWEN_XMLNODE *nPage; GWEN_XMLNODE *nActor; nPage=GWEN_XMLNode_FindFirstTag(fileNode, "page", "id", sPageId); nActor=_getSubItemNode(nPage, sActorId, "actor"); if (nPage && nActor) { _handlePageActor(rq, dc, sActorId, nActor); } else { DBG_ERROR(NULL, "Actor %s/%s not found", sPageId, sActorId); } GWEN_XMLNode_free(fileNode); } else { DBG_INFO(NULL, "here"); } } if (sPageId && *sPageId) { GWEN_BUFFER *pbuf; pbuf=GWEN_Buffer_new(0, 256, 0, 1); GBAS(pbuf, "Location: page.html?page="); GWEN_Text_EscapeToBuffer(sPageId, pbuf); AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf)); GWEN_Buffer_free(pbuf); } AQCGI_Request_SetResponseCode(rq, 303); AQCGI_Request_SetResponseText(rq, "See other"); } void _handlePageActor(AQCGI_REQUEST *rq, AQH_DATACLIENT *dc, const char *sActorId, GWEN_XMLNODE *nActor) { GWEN_DB_NODE *dbPost; const char *sDeviceName; const char *sValueName; dbPost=AQCGI_Request_GetDbPostBody(rq); sDeviceName=GWEN_XMLNode_GetProperty(nActor, "device", NULL); sValueName=GWEN_XMLNode_GetProperty(nActor, "value", NULL); if (sDeviceName && *sDeviceName && sValueName && *sValueName) { AQH_VALUE *value; value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName); if (value) { const char *sSystemValueName; sSystemValueName=AQH_Value_GetNameForSystem(value); if (sSystemValueName) { const char *sData; sData=GWEN_DB_GetCharValue(dbPost, sActorId, 0, NULL); DBG_INFO(NULL, "Setting value %s to %s", sSystemValueName, sData?sData:"empty/no value"); switch(AQH_Value_GetModality(value)) { case AQH_ValueModality_RGBW: _setRgbwData(dc, dbPost, sActorId, value); break; case AQH_ValueModality_OnOff: _setOnOffData(dc, value, sData); break; case AQH_ValueModality_OnOffAuto: _setOnOffAutoData(dc, value, sData); break; default: break; } /* switch */ } } } } void _handlePageGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_DATACLIENT *dc, const char *sGraphId, GWEN_XMLNODE *nGraph, GWEN_BUFFER *dbuf) { GWEN_BUFFER *fbuf; int refreshTime; refreshTime=GWEN_XMLNode_GetIntProperty(nGraph, "refreshTime", 120); fbuf=GWEN_Buffer_new(0, 256, 0, 1); _mkPathForGraph(m, sGraphId, fbuf); if (!AQH_ModService_FileIsCurrent(GWEN_Buffer_GetStart(fbuf), refreshTime)) { _genPageGraph(dc, sGraphId, GWEN_Buffer_GetStart(fbuf), nGraph); } AQH_ModService_RespondWithMimeFile(rq, GWEN_Buffer_GetStart(fbuf), "image/png", dbuf); GWEN_Buffer_free(fbuf); } void _genPageGraph(AQH_DATACLIENT *dc, const char *sGraphId, const char *sFilename, GWEN_XMLNODE *nGraph) { const char *s; const char *sTitle; int w; int h; int precision; uint64_t tsBegin; uint64_t tsEnd; AQDG_GRAPH *g; AQDG_DRAW_CONTEXT *drawContext; AQDG_OBJECT *graphObject; uint32_t tickFlags=0; double upperLimit; double lowerLimit; sTitle=GWEN_XMLNode_GetProperty(nGraph, "title", "untitled"); w=GWEN_XMLNode_GetIntProperty(nGraph, "width", AQH_MODDEVICES_GRAPH_WIDTH); h=GWEN_XMLNode_GetIntProperty(nGraph, "height", AQH_MODDEVICES_GRAPH_HEIGHT); precision=GWEN_XMLNode_GetIntProperty(nGraph, "precision", 2); tsBegin=_parseTime(GWEN_XMLNode_GetProperty(nGraph, "begin", "-4h")); tsEnd=_parseTime(GWEN_XMLNode_GetProperty(nGraph, "end", "0")); s=GWEN_XMLNode_GetProperty(nGraph, "lowerLimit", NULL); if (s && *s) { if (1==sscanf(s, "%lf", &lowerLimit)) tickFlags|=AQDG_TIMEGRAPH_SETUPTICKS_FLAGS_MINY; else { DBG_ERROR(NULL, "Ignoring invalid lowerLimit (%s)", s); } } s=GWEN_XMLNode_GetProperty(nGraph, "upperLimit", NULL); if (s && *s) { if (1==sscanf(s, "%lf", &upperLimit)) tickFlags|=AQDG_TIMEGRAPH_SETUPTICKS_FLAGS_MAXY; else { DBG_ERROR(NULL, "Ignoring invalid upperLimit (%s)", s); } } g=AQDG_TimeGraph_new(sTitle, NULL, "Value", NULL, precision); _addCurves(dc, g, nGraph, tsBegin, tsEnd); AQDG_TimeGraph_SetupTicks(g, tickFlags, lowerLimit, upperLimit); DBG_DEBUG(NULL, "Draw graph for %s", sGraphId); drawContext=AQDG_Draw_ContextCairo_Png_new(sFilename, w, h); graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, drawContext); AQDG_Object_SetWidth(graphObject, w); AQDG_Object_SetHeight(graphObject, h); AQDG_GraphWidget_SetupDefaultPens(graphObject); AQDG_GraphWidget_SetupDefaultFonts(graphObject); AQDG_GraphWidget_FinishWithGraph(graphObject, g); AQDG_Object_free(graphObject); } void _addCurves(AQH_DATACLIENT *dc, AQDG_GRAPH *g, GWEN_XMLNODE *nGraph, uint64_t tsBegin, uint64_t tsEnd) { GWEN_XMLNODE *nCurve; nCurve=GWEN_XMLNode_FindFirstTag(nGraph, "curve", NULL, NULL); while(nCurve) { const char *sModifier; sModifier=GWEN_XMLNode_GetProperty(nCurve, "modifier", NULL); if (sModifier && *sModifier) { AQDG_GRAPH_DATAPAIR_LIST *dpList; dpList=_readCurveData(dc, nCurve, tsBegin, tsEnd); if (dpList) { const char *sCurveLabel; sCurveLabel=GWEN_XMLNode_GetProperty(nCurve, "title", NULL); DBG_DEBUG(NULL, "Adding data for %s", sCurveLabel?sCurveLabel:""); AQDG_TimeGraph_ModifyDataAndAddCurve(g, sCurveLabel?sCurveLabel:"", sModifier, dpList); } } nCurve=GWEN_XMLNode_FindNextTag(nCurve, "curve", NULL, NULL); } } AQDG_GRAPH_DATAPAIR_LIST *_readCurveData(AQH_DATACLIENT *dc, GWEN_XMLNODE *nCurve, uint64_t tsBegin, uint64_t tsEnd) { const char *sDeviceName; const char *sValueName; sDeviceName=GWEN_XMLNode_GetProperty(nCurve, "device", NULL); sValueName=GWEN_XMLNode_GetProperty(nCurve, "value", NULL); if (sDeviceName && *sDeviceName && sValueName && *sValueName) { AQDG_GRAPH_DATAPAIR_LIST *dpList; GWEN_BUFFER *vbuf; vbuf=GWEN_Buffer_new(0, 64, 0, 1); GBAA(vbuf, "%s/%s", sDeviceName, sValueName); dpList=AQH_ModDevices_RequestDataPairList(dc, GWEN_Buffer_GetStart(vbuf), tsBegin, tsEnd, 100000); if (dpList) { GWEN_Buffer_free(vbuf); return dpList; } GWEN_Buffer_free(vbuf); } return NULL; } // TODO: move to aqhome.{c,h} uint64_t _parseTime(const char *s) { if (s && *s) { if (*s=='-') { uint64_t x=0; uint64_t now=time(NULL); s++; while(*s && isdigit(*s)) { unsigned int i; i=*(s++)-'0'; x*=10; x+=i; } if (*s) { switch(*s) { case 0: case 'm': x*=60; break; case 'h': x*=(60*60); break; case 'd': x*=(60*60*24); break; case 'w': x*=(60*60*24*7); break; case 'M': x*=(60*60*24*30); break; case 'y': x*=(60*60*24*365); break; default: break; } } return (now-x); } if (*s=='@') { int y, m, d, H, M, S; if (6==sscanf(s+1, "%d/%d/%d-%d:%d:%d", &y, &m, &d, &H, &M, &S)) { GWEN_TIMESTAMP *ts; uint64_t x=0; ts=GWEN_Timestamp_new(y, m, d, H, M, S); x=GWEN_Timestamp_toTimeT(ts); GWEN_Timestamp_free(ts); return x; } else { DBG_ERROR(NULL, "Invalid timespec [%s], expected: @YYYY/MM/DD-HH:MM:SS", s); return (uint64_t) (-1); } } else { unsigned long int x; if (1!=sscanf(s, "%lu", &x)) { DBG_ERROR(NULL, "ERROR: Invalid timestamp"); return (uint64_t) (-1); } return (uint64_t) x; } } return 0; } GWEN_XMLNODE *_getSubItemNode(GWEN_XMLNODE *nPage, const char *sId, const char *sElementName) { GWEN_XMLNODE *nItem; nItem=GWEN_XMLNode_FindFirstTag(nPage, "item", NULL, NULL); while(nItem) { GWEN_XMLNODE *nGraph; nGraph=GWEN_XMLNode_FindFirstTag(nItem, sElementName, "id", sId); if (nGraph) return nGraph; nItem=GWEN_XMLNode_FindNextTag(nItem, "item", NULL, NULL); } return NULL; } void _mkPathForGraph(AQH_MODULE *m, const char *sGraphId, GWEN_BUFFER *buf) { AQH_SERVICE *sv; const char *s; sv=AQH_ModService_GetService(m); s=AQH_Service_GetCacheFolder(sv); GBAA(buf, "%s%s%s", s, GWEN_DIR_SEPARATOR_S, sGraphId); AQH_ModService_EscapeToBuffer(s, buf); GBAS(buf, ".png"); } void _writePage(AQH_MODULE *m, AQH_DATACLIENT *dc, GWEN_XMLNODE *nPage, GWEN_BUFFER *dbuf) { const char *sPageId; GWEN_XMLNODE *nItem; int layout; const char *s; sPageId=GWEN_XMLNode_GetProperty(nPage, "id", NULL); /* title */ s=GWEN_XMLNode_GetProperty(nPage, "title", NULL); if (s && *s) GBAA(dbuf, "

%s

\n", s); layout=_layoutFromString(GWEN_XMLNode_GetProperty(nPage, "layout", "none")); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); if (layout==MY_LAYOUT_HORIZONTAL) GBAS(dbuf, "\n"); nItem=GWEN_XMLNode_FindFirstTag(nPage, "item", NULL, NULL); while(nItem) { if (layout==MY_LAYOUT_VERTICAL) GBAS(dbuf, "\n"); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, ""); if (layout==MY_LAYOUT_VERTICAL) GBAS(dbuf, "\n"); nItem=GWEN_XMLNode_FindNextTag(nItem, "item", NULL, NULL); } /* while */ if (layout==MY_LAYOUT_HORIZONTAL) GBAS(dbuf, "\n"); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "
"); _writeItem(m, dc, sPageId, nItem, dbuf); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "
\n"); } void _writeItem(AQH_MODULE *m, AQH_DATACLIENT *dc, const char *sPageId, GWEN_XMLNODE *nItem, GWEN_BUFFER *dbuf) { GWEN_XMLNODE *n; uint32_t perms; int layout; perms=AQH_ModService_GetUserPerms(m); layout=_layoutFromString(GWEN_XMLNode_GetProperty(nItem, "layout", "none")); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); if (layout==MY_LAYOUT_HORIZONTAL) GBAS(dbuf, "\n"); n=GWEN_XMLNode_GetFirstTag(nItem); while(n) { const char *sName; if (layout==MY_LAYOUT_VERTICAL) GBAS(dbuf, "\n"); sName=GWEN_XMLNode_GetData(n); if (sName && *sName) { if (strcasecmp(sName, "actor")==0) { if (perms && AQH_MODDEVICES_PERMS_VALUEWRITE) _writeActor(dc, sPageId, n, layout, dbuf); else { DBG_ERROR(NULL, "No permissions to write values"); } } else if (strcasecmp(sName, "graph")==0) _writeGraph(sPageId, n, layout, dbuf); else { DBG_ERROR(NULL, "Ignoring element \"%s\"", sName); } } if (layout==MY_LAYOUT_VERTICAL) GBAS(dbuf, "\n"); n=GWEN_XMLNode_GetNextTag(n); } if (layout==MY_LAYOUT_HORIZONTAL) GBAS(dbuf, "\n"); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "
\n"); } void _writeActor(AQH_DATACLIENT *dc, const char *sPageId, GWEN_XMLNODE *n, int layout, GWEN_BUFFER *dbuf) { const char *sActorId; const char *sDeviceName; const char *sValueName; const char *sLabel; sActorId=GWEN_XMLNode_GetProperty(n, "id", NULL); sLabel=GWEN_XMLNode_GetProperty(n, "label", NULL); sDeviceName=GWEN_XMLNode_GetProperty(n, "device", NULL); sValueName=GWEN_XMLNode_GetProperty(n, "value", NULL); if (sActorId && *sActorId && sDeviceName && *sDeviceName && sValueName && *sValueName) { AQH_VALUE *value; value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName); if (value) { uint32_t lastData; if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); lastData=AQH_ModDevices_ValueGetLastDataAsUint32(dc, value, 0); GBAS(dbuf,"
\n"); GBAA(dbuf, "\n", sPageId); GBAA(dbuf, "\n", sActorId); DBG_INFO(NULL, "Adding actor"); if (sLabel && *sLabel) GBAA(dbuf,"", sActorId, sLabel); if (layout!=MY_LAYOUT_NONE) { GBAS(dbuf, "\n"); GBAS(dbuf, "\n"); } switch(AQH_Value_GetModality(value)) { case AQH_ValueModality_RGBW: _writeRgbwToForm(sActorId, lastData, dbuf); break; case AQH_ValueModality_OnOff: _writeOnOffToForm(sActorId, lastData, dbuf); break; case AQH_ValueModality_OnOffAuto: _writeOnOffAutoToForm(sActorId, lastData, dbuf); break; default: GBAA(dbuf, "%d", lastData); break; } /* switch */ if (layout!=MY_LAYOUT_NONE) { GBAS(dbuf, "\n"); GBAS(dbuf, "\n"); } GBAS(dbuf,""); GBAS(dbuf, "
\n\n"); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); } } } void _writeGraph(const char *sPageId, GWEN_XMLNODE *n, int layout, GWEN_BUFFER *dbuf) { const char *sGraphId; int w; int h; w=GWEN_XMLNode_GetIntProperty(n, "width", AQH_MODDEVICES_GRAPH_WIDTH); h=GWEN_XMLNode_GetIntProperty(n, "height", AQH_MODDEVICES_GRAPH_HEIGHT); sGraphId=GWEN_XMLNode_GetProperty(n, "id", NULL); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); if (sGraphId && *sGraphId) _addGraphLink(sPageId, sGraphId, w, h, dbuf); if (layout!=MY_LAYOUT_NONE) GBAS(dbuf, "\n"); } void _addGraphLink(const char *sPageId, const char *sGraphId, int w, int h, GWEN_BUFFER *dbuf) { GBAS(dbuf, "\"%s\""); } void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf) { #if 1 DBG_ERROR(NULL, "Color=%08x (%d, %d, %d, %d)", color, AQH_ModDevices_RgbwGetR(color), AQH_ModDevices_RgbwGetG(color), AQH_ModDevices_RgbwGetB(color), AQH_ModDevices_RgbwGetW(color)); GBAA(dbuf, "", sValueName); GBAA(dbuf, "", sValueName, sValueName, AQH_ModDevices_RgbwGetR(color)); GBAA(dbuf, "", sValueName); GBAA(dbuf, "", sValueName, sValueName, AQH_ModDevices_RgbwGetG(color)); GBAA(dbuf, "", sValueName); GBAA(dbuf, "", sValueName, sValueName, AQH_ModDevices_RgbwGetB(color)); GBAA(dbuf, "", sValueName); GBAA(dbuf, "", sValueName, sValueName, AQH_ModDevices_RgbwGetW(color)); #else GBAA(dbuf, "", sValueName, sValueName, color); // else GBAA(dbuf, "#%08x (#%08x)", sValueName, sValueName, AQH_ModDevices_RgbwToHtmlColor(color), AQH_ModDevices_RgbwToHtmlColor(color), color); #endif } void _setRgbwData(AQH_DATACLIENT *dc, GWEN_DB_NODE *dbPost, const char *sValueName, const AQH_VALUE *value) { const char *sValueSystemName; uint32_t color; int rv; sValueSystemName=AQH_Value_GetNameForSystem(value); DBG_INFO(NULL, "Set value %s", sValueName); color=AQH_ModDevices_RgbwFromComponents(_getColorComponent(dbPost, sValueName, "r", 0), _getColorComponent(dbPost, sValueName, "g", 0), _getColorComponent(dbPost, sValueName, "b", 0), _getColorComponent(dbPost, sValueName, "w", 0)); DBG_INFO(NULL, "Send value [#%08x] to %s", color, sValueSystemName); rv=AQH_DataClient_SetData(dc, value, (double) color); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } int _getColorComponent(GWEN_DB_NODE *dbPost, const char *sValueName, const char *sComponent, int defaultValue) { GWEN_BUFFER *buf; const char *sData; int result; buf=GWEN_Buffer_new(0, 64, 0, 1); GBAA(buf, "%s_%s", sValueName, sComponent); DBG_INFO(NULL, "Read value %s", GWEN_Buffer_GetStart(buf)); sData=GWEN_DB_GetCharValue(dbPost, GWEN_Buffer_GetStart(buf), 0, NULL); GWEN_Buffer_free(buf); if (sData) { if (1==sscanf(sData, "%u", &result)) return result; } return defaultValue; } void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf) { GBAA(dbuf, ""); } void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) { if (sValue) { const char *sValueSystemName; int rv; sValueSystemName=AQH_Value_GetNameForSystem(value); if (strcasecmp(sValue, "unchanged")==0) { DBG_INFO(NULL, "Value %s unchanged", sValueSystemName); } else if (strcasecmp(sValue, "on")==0) { DBG_INFO(NULL, "Send value 1 to %s", sValueSystemName); rv=AQH_DataClient_SetData(dc, value, 1.0); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } else if (strcasecmp(sValue, "off")==0) { DBG_INFO(NULL, "Send value 0 to %s", sValueSystemName); rv=AQH_DataClient_SetData(dc, value, 0.0); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } else { } } } void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf) { GBAA(dbuf, ""); } void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) { if (sValue) { const char *sValueSystemName; int rv; sValueSystemName=AQH_Value_GetNameForSystem(value); if (strcasecmp(sValue, "unchanged")==0) { DBG_INFO(NULL, "Value %s unchanged", sValueSystemName); } else if (strcasecmp(sValue, "on")==0) { DBG_INFO(NULL, "Send value 1 to %s", sValueSystemName); rv=AQH_DataClient_SetData(dc, value, 1.0); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } else if (strcasecmp(sValue, "off")==0) { DBG_INFO(NULL, "Send value 0 to %s", sValueSystemName); rv=AQH_DataClient_SetData(dc, value, 0.0); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } else if (strcasecmp(sValue, "auto")==0) { DBG_INFO(NULL, "Send value 2 to %s", sValueSystemName); rv=AQH_DataClient_SetData(dc, value, 2.0); if (rv<0) { DBG_INFO(NULL, "Error sending data: %d", rv); } } else { DBG_INFO(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName); } } } GWEN_XMLNODE *_readPage(AQH_MODULE *m, const char *sPageName) { GWEN_BUFFER *fbuf; AQH_SERVICE *sv; GWEN_XMLNODE *fileNode; sv=AQH_ModService_GetService(m); fbuf=GWEN_Buffer_new(0, 256, 0, 1); GBAA(fbuf, "%s%spages%s", AQH_Service_GetRuntimeFolder(sv), GWEN_DIR_SEPARATOR_S, GWEN_DIR_SEPARATOR_S); AQH_ModService_EscapeToBuffer(sPageName, fbuf); GBAS(fbuf, ".xml"); fileNode=_readPageFile(GWEN_Buffer_GetStart(fbuf)); if (fileNode==NULL) { DBG_INFO(NULL, "here"); GWEN_Buffer_free(fbuf); return NULL; } GWEN_Buffer_free(fbuf); return fileNode; } GWEN_XMLNODE *_readPageFile(const char *sFilename) { GWEN_XMLNODE *fileNode; int rv; fileNode=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, sFilename); rv=GWEN_XML_ReadFile(fileNode, sFilename, GWEN_XML_FLAGS_DEFAULT); if (rv<0) { DBG_ERROR(NULL, "Error reading \"%s\": %s (%d)", sFilename?sFilename:"", strerror(errno), errno); GWEN_XMLNode_free(fileNode); return NULL; } return fileNode; } int _layoutFromString(const char *s) { if (s && *s) { if (strcasecmp(s, "none")==0) return MY_LAYOUT_NONE; else if (strcasecmp(s, "horizontal")==0) return MY_LAYOUT_HORIZONTAL; else if (strcasecmp(s, "vertical")==0) return MY_LAYOUT_VERTICAL; } return MY_LAYOUT_NONE; }