diff --git a/0BUILD b/0BUILD index 36425b2..dec59b0 100644 --- a/0BUILD +++ b/0BUILD @@ -2,7 +2,7 @@ - + $(project_name) $(project_vmajor).$(project_vminor).$(project_vpatchlevel) diff --git a/apps/aqhome-cgi/0BUILD b/apps/aqhome-cgi/0BUILD index 12c94a1..2f65c35 100644 --- a/apps/aqhome-cgi/0BUILD +++ b/apps/aqhome-cgi/0BUILD @@ -8,6 +8,7 @@ $(gwenhywfar_cflags) $(aqcgi_cflags) + $(aqdiagram_cflags) -I$(topsrcdir) -I$(topbuilddir) -I$(topsrcdir)/apps @@ -58,6 +59,7 @@ $(gwenhywfar_libs) -lm $(aqcgi_libs) + $(aqdiagram_libs) @@ -127,6 +129,7 @@ $(gwenhywfar_libs) -lm $(aqcgi_libs) + $(aqdiagram_libs) diff --git a/apps/aqhome-cgi/main.c b/apps/aqhome-cgi/main.c index 096f7f6..b9e52c9 100644 --- a/apps/aqhome-cgi/main.c +++ b/apps/aqhome-cgi/main.c @@ -5,11 +5,12 @@ #include "aqhome-cgi/modules/common/madmin.h" #include "aqhome-cgi/modules/common/mmodules.h" #include "aqhome-cgi/modules/common/musers.h" -#include "aqhome-cgi/modules/mdevices.h" +#include "aqhome-cgi/modules/devices/mdevices.h" #include "aqhome/aqhome.h" #include #include +#include #include #include @@ -26,21 +27,34 @@ #define AQHOME_CGI_DEFAULT_STATIC_FILES AQHOME_CGI_WWWDIR"/static" #define AQHOME_CGI_DEFAULT_RUNTIME_FILES AQHOME_CGI_WWWDIR"/data" +#define AQHOME_CGI_DEFAULT_CACHE_FILES AQHOME_CGI_WWWDIR"/cache" +#define AQHOME_CGI_DEFAULT_BASE_URL "http://127.0.0.1/aqbt" -static void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles); +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl); static int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles); static void logStart(void); -static int _init(const char *sPathRuntimeFiles); +static int _init(const char *sPathRuntimeFiles, const char *sBaseUrl); +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + int main(int argc, char **argv) { GWEN_GUI *gui; const char *sPathStaticFiles; const char *sPathRuntimeFiles; + const char *sBaseUrl; sPathStaticFiles=getenv("AQHOME_STATIC_FILES"); if (!(sPathStaticFiles && *sPathStaticFiles)) @@ -50,6 +64,10 @@ int main(int argc, char **argv) if (!(sPathRuntimeFiles && *sPathRuntimeFiles)) sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES; + sBaseUrl=getenv("AQHOME_BASE_URL"); + if (!(sBaseUrl && *sBaseUrl)) + sBaseUrl=AQHOME_CGI_DEFAULT_BASE_URL; + GWEN_Init(); gui=GWEN_NoGui_new(); GWEN_Gui_SetGui(gui); @@ -58,6 +76,7 @@ int main(int argc, char **argv) GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon); GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon); GWEN_Logger_Open(AQCGI_LOGDOMAIN, "aqcgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon); + GWEN_Logger_Open(AQDG_LOGDOMAIN, "aqdiagram", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon); GWEN_Logger_Open(NULL, "aqhome-cgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon); GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug); @@ -69,13 +88,14 @@ int main(int argc, char **argv) GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug); GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug); + GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, GWEN_LoggerLevel_Debug); GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug); if (argc>1 && argv[1]) { if (0==strcasecmp(argv[1], "init")) { int rv; - rv=_init(sPathRuntimeFiles); + rv=_init(sPathRuntimeFiles, sBaseUrl); if (rv<0) { fprintf(stderr, "Error on init (%d)\n", rv); return 2; @@ -90,7 +110,7 @@ int main(int argc, char **argv) AQCGI_Init(); rq=AQCGI_ReadRequest(); if (rq) { - _handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles); + _handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles, sBaseUrl); } else { fprintf(stdout, "Content-type: text/plain\n\n"); @@ -104,12 +124,12 @@ int main(int argc, char **argv) -void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles) +void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl) { AQH_SERVICE *sv; int rv; - sv=AQH_ServiceFiles_new(sPathRuntimeFiles); + sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl); rv=_handlePath(sv, rq, sPathStaticFiles); if (rv<0) { @@ -160,6 +180,7 @@ int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles int rv; /* last, let module handle remaining part */ + DBG_ERROR(NULL, "Entry: %s (last)", s); rv=AQH_ModService_HandleRequest(mParent, rq, session, s); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); @@ -199,13 +220,13 @@ void logStart() -int _init(const char *sPathRuntimeFiles) +int _init(const char *sPathRuntimeFiles, const char *sBaseUrl) { AQH_SERVICE *sv; int rv; - fprintf(stdout, "Creating aqhome-cgi environment in \"%s\"\n", sPathRuntimeFiles); - sv=AQH_ServiceFiles_new(sPathRuntimeFiles); + DBG_ERROR(NULL, "Creating aqhome-cgi environment in \"%s\"", sPathRuntimeFiles); + sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl); rv=AQH_ModAdmin_Create(sv); if (rv<0) { DBG_ERROR(NULL, "Error creating module \"admin\""); diff --git a/apps/aqhome-cgi/modules/0BUILD b/apps/aqhome-cgi/modules/0BUILD index 2cd35ae..435afe9 100644 --- a/apps/aqhome-cgi/modules/0BUILD +++ b/apps/aqhome-cgi/modules/0BUILD @@ -50,7 +50,6 @@ mdataclient.h - mdevices.h mroot.h @@ -64,7 +63,6 @@ $(local/typefiles) mdataclient.c - mdevices.c mroot.c @@ -75,10 +73,12 @@ aqhcgi_modcom + aqhcgi_mdevices common + devices static diff --git a/apps/aqhome-cgi/modules/common/mservice.c b/apps/aqhome-cgi/modules/common/mservice.c index 0ae0754..f4df10f 100644 --- a/apps/aqhome-cgi/modules/common/mservice.c +++ b/apps/aqhome-cgi/modules/common/mservice.c @@ -518,9 +518,13 @@ void AQH_ModService_HandleRequestWithTable(AQH_MODULE *m, } } - AQH_ModService_AddFooter(m, "en", dbuf); + if (!(AQCGI_Request_GetFlags(rq) & AQH_MODSERVICE_RQFLAGS_RAWFILE)) { + DBG_ERROR(NULL, "Not adding footer"); + AQH_ModService_AddFooter(m, "en", dbuf); + } AQCGI_Request_SetBufferResponseBody(rq, dbuf); - AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html"); + if (AQCGI_Request_GetFlags(rq) & AQCGI_FLAGS_HAS_CONTENT_HEADER) + AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html"); } diff --git a/apps/aqhome-cgi/modules/common/mservice.h b/apps/aqhome-cgi/modules/common/mservice.h index 3cd1b76..8a578ce 100644 --- a/apps/aqhome-cgi/modules/common/mservice.h +++ b/apps/aqhome-cgi/modules/common/mservice.h @@ -18,6 +18,10 @@ #include +#define AQH_MODSERVICE_RQFLAGS_RAWFILE 0x10000000 + + + typedef int (*AQH_MODSERVICE_HANDLEREQUEST_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem); typedef AQH_MODULE* (*AQH_MODSERVICE_LOADSUBMODULE_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName); typedef void (*AQH_MODSERVICE_ADDHEADER_FN)(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf); diff --git a/apps/aqhome-cgi/modules/devices/0BUILD b/apps/aqhome-cgi/modules/devices/0BUILD new file mode 100644 index 0000000..051c8ae --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/0BUILD @@ -0,0 +1,99 @@ + + + + + + + + $(gwenhywfar_cflags) + $(aqcgi_cflags) + $(aqdiagram_cflags) + -I$(topsrcdir) + -I$(topbuilddir) + -I$(topsrcdir)/apps + -I$(topbuilddir)/apps + -I$(builddir) + -I$(srcdir) + + + + --include=$(builddir) + --include=$(srcdir) + + + + + + $(visibility_cflags) + + + + --api=AQHOME_API + + + + + + + + + + + + + + + + + + $(local/built_headers_pub) + + + + + mdevices.h + mdevices_init.h + mdevices_index.h + mdevices_valuestable.h + mdevices_valuesgraph.h + mdevices_value.h + mdevices_setdata.h + mdevices_vgraph.h + mdevices_device.h + mdevices_setdevice.h + + + + + + + + + $(local/typefiles) + + mdevices.c + mdevices_init.c + mdevices_index.c + mdevices_valuestable.c + mdevices_valuesgraph.c + mdevices_value.c + mdevices_setdata.c + mdevices_vgraph.c + mdevices_device.c + mdevices_setdevice.c + + + + + + + + + + + + + + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices.c b/apps/aqhome-cgi/modules/devices/mdevices.c new file mode 100644 index 0000000..70e1e2d --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices.c @@ -0,0 +1,395 @@ +/**************************************************************************** + * 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.h" + +#include "aqhome-cgi/modules/devices/mdevices_index.h" +#include "aqhome-cgi/modules/devices/mdevices_valuestable.h" +#include "aqhome-cgi/modules/devices/mdevices_valuesgraph.h" +#include "aqhome-cgi/modules/devices/mdevices_value.h" +#include "aqhome-cgi/modules/devices/mdevices_setdata.h" +#include "aqhome-cgi/modules/devices/mdevices_vgraph.h" +#include "aqhome-cgi/modules/devices/mdevices_device.h" +#include "aqhome-cgi/modules/devices/mdevices_setdevice.h" +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + +#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD +#define P_DEVICEWRITE AQH_MODDEVICES_PERMS_DEVICEWRITE +#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD +#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName); +static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem); + +static void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqValuesTableGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqValuesGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqValueGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqDeviceGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); +static void _handleRqDevicePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); + +static void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf); +static void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf); + + + +/* ------------------------------------------------------------------------------------------------ + * vars + * ------------------------------------------------------------------------------------------------ + */ + +static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={ + {"index.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD, _handleRqIndexGet}, + {"device.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqDeviceGet}, + {"device.html", AQCGI_REQUEST_METHOD_POST, P_DEVICEWRITE, _handleRqDevicePost}, + {"vtable.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesTableGet}, + {"vgraph.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesGraphGet}, + {"value.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValueGet}, + {"setdata.html", AQCGI_REQUEST_METHOD_POST, P_VALUEWRITE, _handleRqSetDataPost}, + {"graph.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqGraphGet}, + {NULL, 0, 0, NULL} +}; + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder) +{ + AQH_ModService_Extend(m, sv, baseFolder); + AQH_ModService_SetHandleRequestFn(m, _handleRequest); + AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule); +} + + + +AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName) +{ + return NULL; +} + + + +int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem) +{ + AQH_ModService_HandleRequestWithTable(m, rq, session, sLastPathElem, _requestTable); + return AQCGI_SendResponse(rq); +} + + + +void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunIndex, dbuf); +} + + + +void _handleRqValuesTableGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValuesAsTable, dbuf); +} + + + +void _handleRqValuesGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValuesAsGraph, dbuf); +} + + + +void _handleRqValueGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunValue, dbuf); +} + + + +void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunSetData, dbuf); +} + + + +void _handleRqGraphGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunGraphValue, dbuf); +} + + + +void _handleRqDeviceGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunDevice, dbuf); +} + + + +void _handleRqDevicePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) +{ + AQH_ModDataClient_HandleRequest(m, rq, session, AQH_ModDevices_RunSetDevice, dbuf); +} + + + + + + + + + + +uint32_t AQH_ModDevices_ColorFromHexString(const char *s) +{ + uint32_t colorIn=0; + + while(*s && *s<33) + s++; + if (*s=='#') + s++; + while(*s) { + uint c; + + c=(*s)-'0'; + if (c>9) + c-=7; + colorIn<<=4; + colorIn|=c & 0xf; + s++; + } + + /* hex 00RRGGBB -> GGRRWWBB */ + //return _htmlColorToValueRGBW(colorIn); + return colorIn; +} + + + +uint32_t AQH_ModDevices_HtmlColorToValueRGBW(uint32_t colorIn) +{ + uint32_t colorOut; + /* hex 00RRGGBB -> GGRRWWBB */ + /* RGBW GGRRWWBB GGRRWWBB GGRRWWBB */ + /* html 00RRGGBB 00RRGGBB 00RRGGBB*/ + colorOut=(colorIn & 0x00ff0000) | ((colorIn<<16) & 0xff000000) | (colorIn & 0x000000ff); + return colorOut; +} + + + +uint32_t AQH_ModDevices_RgbwToHtmlColor(uint32_t colorIn) +{ + uint32_t colorOut; + /* RGBW GGRRWWBB GGRRWWBB GGRRWWBB */ + /* hex 00RRGGBB 00RRGGBB 00RRGGBB*/ + colorOut=(colorIn & 0x00ff0000) | ( (colorIn>>16) & 0x0000ff00) | (colorIn & 0x000000ff); + return colorOut; +} + + + +void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueName; + + sValueName=AQH_Value_GetName(value); + switch(AQH_Value_GetModality(value)) { + case AQH_ValueModality_RGBW: + GBAA(dbuf, "", sValueName); + break; + case AQH_ValueModality_OnOff: + GBAA(dbuf, + "", + sValueName); + break; + case AQH_ValueModality_OnOffAuto: + GBAA(dbuf, + "", + sValueName); + break; + default: + break; + } +} + + + +void _addLastValueToForm(AQH_DATACLIENT *dc, const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueSystemName; + const char *sValueName; + uint64_t dataPoints[2]; + uint64_t recvdNum; +// uint64_t timestamp; + union {double f; uint64_t i;} u; + int intVal; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + sValueName=AQH_Value_GetName(value); + recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1); + if (recvdNum>0) { +// timestamp=dataPoints[0]; + u.i=dataPoints[1]; + intVal=(int) u.f; + } + else { + u.i=0; + intVal=-1; + } + + if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { + DBG_ERROR(NULL, "Adding actor"); + switch(AQH_Value_GetModality(value)) { + case AQH_ValueModality_RGBW: + DBG_ERROR(NULL, "Color: %.f RGBW=%08x HTML=%08x, RGBW2=%08x", + u.f, + (uint32_t) (u.f), + AQH_ModDevices_RgbwToHtmlColor(u.f), + AQH_ModDevices_HtmlColorToValueRGBW(AQH_ModDevices_RgbwToHtmlColor(u.f))); +#if 1 + GBAA(dbuf, "", sValueName, (uint32_t) (u.f)); +#else + GBAA(dbuf, "#%08x (#%08x)", + sValueName, + _rgbwToHtmlColor((unsigned int) (u.f)), + _rgbwToHtmlColor((unsigned int) (u.f)), + (uint32_t) (u.f)); +#endif + break; + case AQH_ValueModality_OnOff: + GBAA(dbuf, ""); + break; + case AQH_ValueModality_OnOffAuto: + GBAA(dbuf, ""); + break; + default: + // GBAA(dbuf, "", sValueName, u.f); + GBAA(dbuf, "%.2f", u.f); + break; + } /* switch */ + } /* if actor */ + else { + DBG_ERROR(NULL, "Adding sensor (%s=%.2f)", sValueName, u.f); + GBAA(dbuf, "%.2f", u.f); + } +} + + + +AQH_VALUE *AQH_ModDevices_GetValueForDevice(AQH_DATACLIENT *dc, const char *sDeviceName, const char *sValueName) +{ + AQH_VALUE_LIST *valueList; + + valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0); + if (valueList) { + AQH_VALUE *value; + + value=AQH_Value_List_First(valueList); + while(value) { + const char *s; + + s=AQH_Value_GetName(value); + if (s && *s && strcasecmp(s, sValueName)==0) { + break; + } + value=AQH_Value_List_Next(value); + } + + if (value) { + AQH_Value_List_Del(value); + AQH_Value_List_free(valueList); + return value; + } + + AQH_Value_List_free(valueList); + } + + return NULL; +} + + + +AQH_DEVICE *AQH_ModDevices_GetDevice(AQH_DATACLIENT *dc, const char *sDeviceName) +{ + AQH_DEVICE_LIST *deviceList; + + deviceList=AQH_DataClient_GetDevices(dc, sDeviceName); + if (deviceList) { + AQH_DEVICE *device; + + device=AQH_Device_List_First(deviceList); + while(device) { + const char *s; + + s=AQH_Device_GetNameForSystem(device); + if (s && *s && 0==strcasecmp(s, sDeviceName)) { + AQH_Device_List_Del(device); + AQH_Device_List_free(deviceList); + return device; + } + device=AQH_Device_List_Next(device); + } + AQH_Device_List_free(deviceList); + } + + return NULL; +} + + + + diff --git a/apps/aqhome-cgi/modules/mdevices.h b/apps/aqhome-cgi/modules/devices/mdevices.h similarity index 72% rename from apps/aqhome-cgi/modules/mdevices.h rename to apps/aqhome-cgi/modules/devices/mdevices.h index 0c1205f..15b0476 100644 --- a/apps/aqhome-cgi/modules/mdevices.h +++ b/apps/aqhome-cgi/modules/devices/mdevices.h @@ -32,11 +32,22 @@ #define AQH_MODDEVICES_PERMS_VALUESET 0x100 +#define AQH_MODDEVICES_GRAPH_WIDTH 640 +#define AQH_MODDEVICES_GRAPH_HEIGHT 480 + + void AQH_ModDevices_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder); int AQH_ModDevices_Create(AQH_SERVICE *sv); +uint32_t AQH_ModDevices_ColorFromHexString(const char *s); +uint32_t AQH_ModDevices_HtmlColorToValueRGBW(uint32_t colorIn); +uint32_t AQH_ModDevices_RgbwToHtmlColor(uint32_t colorIn); + +AQH_VALUE *AQH_ModDevices_GetValueForDevice(AQH_DATACLIENT *dc, const char *sDeviceName, const char *sValueName); +AQH_DEVICE *AQH_ModDevices_GetDevice(AQH_DATACLIENT *dc, const char *sDeviceName); + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_device.c b/apps/aqhome-cgi/modules/devices/mdevices_device.c new file mode 100644 index 0000000..ff70697 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_device.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * 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_device.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + +#define I18N(msg) msg + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _runDeviceWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_SESSION *session, + AQH_DATACLIENT *dc, + const char *sDeviceName, + GWEN_BUFFER *dbuf); +static void _mkDeviceForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_DEVICE *device, GWEN_BUFFER *dbuf); +static void _addFieldToForm(const char *sFieldTitle, const char *sFieldName, const char *sFieldContent, GWEN_BUFFER *dbuf); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + const char *sDeviceName; + + DBG_ERROR(NULL, "RunValue"); + dbQuery=AQCGI_Request_GetDbQuery(rq); + sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); + if (sDeviceName && *sDeviceName) { + GWEN_BUFFER *bufDeviceName; + + bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName); + _runDeviceWithArgs(m, rq, session, dc, GWEN_Buffer_GetStart(bufDeviceName), dbuf); + GWEN_Buffer_free(bufDeviceName); + } +} + + + +void _runDeviceWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_SESSION *session, + AQH_DATACLIENT *dc, + const char *sDeviceName, + GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + AQH_DEVICE *device; + + dbQuery=AQCGI_Request_GetDbQuery(rq); + DBG_ERROR(NULL, "Device=%s", sDeviceName?sDeviceName:""); + + GBAA(dbuf,"

Device %s

\n", sDeviceName); + + device=AQH_ModDevices_GetDevice(dc, sDeviceName); + if (device) { + _mkDeviceForm(dc, sDeviceName, device, dbuf); + AQH_Device_free(device); + } +} + + + +void _mkDeviceForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_DEVICE *device, GWEN_BUFFER *dbuf) +{ + const char *s; + + GBAS(dbuf,"
\n"); + GBAA(dbuf, "\n", sDeviceName); + + GBAS(dbuf,"\n"); + _addFieldToForm(I18N("Room"), "roomName", AQH_Device_GetRoomName(device), dbuf); + _addFieldToForm(I18N("GUI Name"), "nameForGui", AQH_Device_GetNameForGui(device), dbuf); + _addFieldToForm(I18N("Location"), "location", AQH_Device_GetLocation(device), dbuf); + _addFieldToForm(I18N("Description"), "description", AQH_Device_GetDescription(device), dbuf); + GBAS(dbuf,"
\n"); + GBAS(dbuf,"
\n"); + + GBAS(dbuf,""); + GBAS(dbuf, "
\n\n"); +} + + + +void _addFieldToForm(const char *sFieldTitle, const char *sFieldName, const char *sFieldContent, GWEN_BUFFER *dbuf) +{ + GBAS(dbuf, ""); + GBAA(dbuf, "", sFieldName, sFieldTitle); + GBAA(dbuf, "", sFieldName, sFieldContent?sFieldContent:""); + GBAS(dbuf, ""); +} + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_device.h b/apps/aqhome-cgi/modules/devices/mdevices_device.h new file mode 100644 index 0000000..aae3489 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_device.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_DEVICE_H +#define AQHOME_CGI_MDEVICES_DEVICE_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_index.c b/apps/aqhome-cgi/modules/devices/mdevices_index.c new file mode 100644 index 0000000..6381047 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_index.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * 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_index.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _addLinkForDevice(const char *page, const char *sDevice, const char *action, const char *imgName, GWEN_BUFFER *dbuf); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + AQH_DEVICE_LIST *deviceList; + AQH_DEVICE *device; + uint32_t perms; + + perms=AQH_ModService_GetUserPerms(m); + + deviceList=AQH_DataClient_GetDevices(dc, NULL); + if (deviceList==NULL) { + DBG_ERROR(NULL, "No device received"); + GBAS(dbuf, "

No devices.

"); + return; + } + + GBAS(dbuf, "

Devices

\n"); + GBAS(dbuf, + "\n" + "\n" + "" + "" + "" + "" + "" + "" + "" + "\n" + "\n" + "\n"); + + device=AQH_Device_List_First(deviceList); + while(device) { + const char *s; + const char *sDevice; + + GBAA(dbuf, ""); + /* name for system */ + sDevice=AQH_Device_GetNameForSystem(device); + GBAA(dbuf,"", sDevice?sDevice:""); + /* nameForGui */ + s=AQH_Device_GetNameForGui(device); + GBAA(dbuf, "", s?s:""); + /* room */ + s=AQH_Device_GetRoomName(device); + GBAA(dbuf, "", s?s:""); + /* location */ + s=AQH_Device_GetLocation(device); + GBAA(dbuf, "", s?s:""); + /* description */ + s=AQH_Device_GetDescription(device); + GBAA(dbuf, "", s?s:""); + + GBAS(dbuf, ""); + + GBAA(dbuf, ""); + device=AQH_Device_List_Next(device); + } + + GBAS(dbuf, + "\n" + "
Name For SystemName For GUIRoomLocationDescriptionActions
%s%s%s%s%s"); + if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) { + _addLinkForDevice("vtable.html", sDevice, "table view", "/pics/document-table.png", dbuf); + _addLinkForDevice("vgraph.html", sDevice, "graph view", "/pics/graph.png", dbuf); + } + + if (perms & AQH_MODDEVICES_PERMS_DEVICEWRITE) { + _addLinkForDevice("device.html", sDevice, "edit device", "/pics/edit.png", dbuf); + } + + GBAS(dbuf, "
\n"); + AQH_Device_List_free(deviceList); +} + + + +void _addLinkForDevice(const char *page, const char *sDevice, const char *action, const char *imgName, GWEN_BUFFER *dbuf) +{ + GBAA(dbuf,""); + GBAA(dbuf,"\"%s\"", imgName, action, action); + GBAS(dbuf,""); +} + + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_index.h b/apps/aqhome-cgi/modules/devices/mdevices_index.h new file mode 100644 index 0000000..f5347df --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_index.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_INDEX_H +#define AQHOME_CGI_MDEVICES_INDEX_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_init.c b/apps/aqhome-cgi/modules/devices/mdevices_init.c new file mode 100644 index 0000000..f35f480 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_init.c @@ -0,0 +1,129 @@ +/**************************************************************************** + * 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_init.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + +#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD +#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD +#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _createPermDefList(AQH_MODULE *m); +static void _createRoleList(AQH_MODULE *m); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +int AQH_ModDevices_Create(AQH_SERVICE *sv) +{ + AQH_MODULE *m; + int rv; + + m=AQH_Module_new(); + AQH_Module_SetName(m, "devices"); + AQH_Module_SetDescr(m, "device module"); + AQH_Module_SetGuestPerms(m, 0); + + _createPermDefList(m); + _createRoleList(m); + + rv=AQH_Service_AddModule(sv, m); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + } + AQH_Module_free(m); + return rv; +} + + + +void _createPermDefList(AQH_MODULE *m) +{ + AQH_PERMDEF_LIST *permDefList; + + permDefList=AQH_PermDef_List_new(); + + AQH_ModService_AddPermDef(permDefList, "DeviceRead", 0x001, "Read and list devices"); + AQH_ModService_AddPermDef(permDefList, "DeviceWrite", 0x002, "Modify devices"); + AQH_ModService_AddPermDef(permDefList, "DeviceAdd", 0x004, "Add devices"); + AQH_ModService_AddPermDef(permDefList, "DeviceDel", 0x008, "Remove devices"); + + AQH_ModService_AddPermDef(permDefList, "ValueRead", 0x010, "Read and list values"); + AQH_ModService_AddPermDef(permDefList, "ValueWrite", 0x020, "Modify values"); + AQH_ModService_AddPermDef(permDefList, "ValueAdd", 0x040, "Add values"); + AQH_ModService_AddPermDef(permDefList, "ValueDel", 0x080, "Remove values"); + AQH_ModService_AddPermDef(permDefList, "ValueSet", 0x100, "Set values"); + + AQH_Module_SetPermDefList(m, permDefList); +} + + + +void _createRoleList(AQH_MODULE *m) +{ + AQH_ROLE_LIST *roleList; + int id=0; + + roleList=AQH_Role_List_new(); + AQH_ModService_AddRole(roleList, id++, "Reader", + AQH_MODDEVICES_PERMS_DEVICEREAD | + AQH_MODDEVICES_PERMS_VALUEREAD, + "Read devices and values"); + AQH_ModService_AddRole(roleList, id++, "Writer", + AQH_MODDEVICES_PERMS_DEVICEREAD | + AQH_MODDEVICES_PERMS_DEVICEWRITE | + AQH_MODDEVICES_PERMS_DEVICEADD | + AQH_MODDEVICES_PERMS_DEVICEDEL | + AQH_MODDEVICES_PERMS_VALUEREAD | + AQH_MODDEVICES_PERMS_VALUEWRITE | + AQH_MODDEVICES_PERMS_VALUEADD | + AQH_MODDEVICES_PERMS_VALUEDEL | + AQH_MODDEVICES_PERMS_VALUESET, + "Read and write devices and values"); + AQH_ModService_AddRole(roleList, id++, "Setter", + AQH_MODDEVICES_PERMS_DEVICEREAD | + AQH_MODDEVICES_PERMS_VALUEREAD | + AQH_MODDEVICES_PERMS_VALUESET, + "Set values"); + AQH_Module_SetRoleList(m, roleList); +} + + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_init.h b/apps/aqhome-cgi/modules/devices/mdevices_init.h new file mode 100644 index 0000000..6456e24 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_init.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_INIT_H +#define AQHOME_CGI_MDEVICES_INIT_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +int AQH_ModDevices_Create(AQH_SERVICE *sv); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_setdata.c b/apps/aqhome-cgi/modules/devices/mdevices_setdata.c new file mode 100644 index 0000000..5a16bd8 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_setdata.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * 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_setdata.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue); +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); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + AQH_SERVICE *sv; + GWEN_DB_NODE *dbPost; + const char *sDeviceName; + const char *sValueName; + const AQH_VALUE *value; + + /* sample data */ + sv=AQH_ModService_GetService(m); + dbPost=AQCGI_Request_GetDbPostBody(rq); + sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL; + sValueName=dbPost?GWEN_DB_GetCharValue(dbPost, "value", 0, NULL):NULL; + DBG_ERROR(NULL, "Device=[%s], value=[%s]", sDeviceName?sDeviceName:"", sValueName?sValueName:""); + + value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName); + if(value && AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { + const char *sValueName; + const char *sValue; + + sValueName=AQH_Value_GetName(value); + sValue=GWEN_DB_GetCharValue(dbPost, sValueName, 0, NULL); + if (sValueName && *sValueName) { + DBG_ERROR(NULL, "Setting value %s to %s", sValueName?sValueName:"no name", sValue?sValue:"no value"); + switch(AQH_Value_GetModality(value)) { + case AQH_ValueModality_RGBW: _setRgbwData(dc, value, sValue); break; + case AQH_ValueModality_OnOff: _setOnOffData(dc, value, sValue); break; + case AQH_ValueModality_OnOffAuto: _setOnOffAutoData(dc, value, sValue); break; + default: + break; + } /* switch */ + } /* if (sValueName) */ + } + + if (sDeviceName && *sDeviceName) { + GWEN_BUFFER *pbuf; + + pbuf=GWEN_Buffer_new(0, 256, 0, 1); + if (sValueName && *sValueName) { + GBAS(pbuf, "Location: /aqbt/devices/value.html?device="); + GWEN_Text_EscapeToBuffer(sDeviceName, pbuf); + GBAS(pbuf, "&value="); + GWEN_Text_EscapeToBuffer(sValueName, pbuf); + } + else { + GBAS(pbuf, "Location: /aqbt/devices/values.html?device="); + GWEN_Text_EscapeToBuffer(sDeviceName, 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 _setRgbwData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue) +{ + if (sValue) { + const char *sValueSystemName; + uint32_t color; + int rv; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + color=AQH_ModDevices_ColorFromHexString(sValue); + DBG_ERROR(NULL, "Send value [#%08x] to %s", color, sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, (double) color); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } +} + + + +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_ERROR(NULL, "Value %s unchanged", sValueSystemName); + } + else if (strcasecmp(sValue, "on")==0) { + DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 1.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "off")==0) { + DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 0.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else { + } + } +} + + + +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_ERROR(NULL, "Value %s unchanged", sValueSystemName); + } + else if (strcasecmp(sValue, "on")==0) { + DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 1.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "off")==0) { + DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 0.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else if (strcasecmp(sValue, "auto")==0) { + DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName); + rv=AQH_DataClient_SetData(dc, value, 2.0); + if (rv<0) { + DBG_ERROR(NULL, "Error sending data: %d", rv); + } + } + else { + DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName); + } + } +} + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_setdata.h b/apps/aqhome-cgi/modules/devices/mdevices_setdata.h new file mode 100644 index 0000000..ac1263a --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_setdata.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_SETVALUE_H +#define AQHOME_CGI_MDEVICES_SETVALUE_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_setdevice.c b/apps/aqhome-cgi/modules/devices/mdevices_setdevice.c new file mode 100644 index 0000000..6edfd72 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_setdevice.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * 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_setdevice.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _handleDeviceForm(AQH_DATACLIENT *dc, AQH_DEVICE *device, GWEN_DB_NODE *dbPost, GWEN_BUFFER *dbuf); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunSetDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + AQH_SERVICE *sv; + GWEN_DB_NODE *dbPost; + const char *sDeviceName; + AQH_DEVICE *device; + + DBG_ERROR(NULL, "Post device.html"); + /* sample data */ + sv=AQH_ModService_GetService(m); + dbPost=AQCGI_Request_GetDbPostBody(rq); + sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL; + DBG_ERROR(NULL, "Device=[%s]", sDeviceName?sDeviceName:""); + + device=AQH_ModDevices_GetDevice(dc, sDeviceName); + if (device) { + int rv; + + DBG_ERROR(NULL, "Reading data from form"); + _handleDeviceForm(dc, device, dbPost, dbuf); + DBG_ERROR(NULL, "Updating device on server"); + rv=AQH_DataClient_ModDevice(dc, device); + if (rv<0) { + DBG_ERROR(NULL, "here (%d)", rv); + } + AQH_Device_free(device); + } + else { + DBG_ERROR(NULL, "device not found"); + } + + if (sDeviceName && *sDeviceName) { + GWEN_BUFFER *pbuf; + + pbuf=GWEN_Buffer_new(0, 256, 0, 1); + GBAS(pbuf, "Location: /aqbt/devices/device.html?device="); + GWEN_Text_EscapeToBuffer(sDeviceName, 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 _handleDeviceForm(AQH_DATACLIENT *dc, AQH_DEVICE *device, GWEN_DB_NODE *dbPost, GWEN_BUFFER *dbuf) +{ + AQH_Device_SetRoomName(device, GWEN_DB_GetCharValue(dbPost, "roomName", 0, NULL)); + AQH_Device_SetNameForGui(device, GWEN_DB_GetCharValue(dbPost, "nameForGui", 0, NULL)); + AQH_Device_SetLocation(device, GWEN_DB_GetCharValue(dbPost, "location", 0, NULL)); + AQH_Device_SetDescription(device, GWEN_DB_GetCharValue(dbPost, "description", 0, NULL)); +} + + + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_setdevice.h b/apps/aqhome-cgi/modules/devices/mdevices_setdevice.h new file mode 100644 index 0000000..d370f40 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_setdevice.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_SETDEVICE_H +#define AQHOME_CGI_MDEVICES_SETDEVICE_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunSetDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_value.c b/apps/aqhome-cgi/modules/devices/mdevices_value.c new file mode 100644 index 0000000..61fc436 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_value.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * 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_value.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _runValueWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_SESSION *session, + AQH_DATACLIENT *dc, + const char *sDeviceName, + const char *sValueName, + GWEN_BUFFER *dbuf); +static void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, 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); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + const char *sDeviceName; + const char *sValueName; + + DBG_ERROR(NULL, "RunValue"); + dbQuery=AQCGI_Request_GetDbQuery(rq); + sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); + sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL); + if (sDeviceName && *sDeviceName && sValueName && *sValueName) { + GWEN_BUFFER *bufDeviceName; + GWEN_BUFFER *bufValueName; + + bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName); + bufValueName=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Text_UnescapeToBufferTolerant(sValueName, bufValueName); + _runValueWithArgs(m, rq, session, dc, + GWEN_Buffer_GetStart(bufDeviceName), + GWEN_Buffer_GetStart(bufValueName), + dbuf); + GWEN_Buffer_free(bufValueName); + GWEN_Buffer_free(bufDeviceName); + } + +#if 0 + if (sDeviceName && *sDeviceName && sValueName && *sValueName) { + GWEN_BUFFER *pbuf; + + pbuf=GWEN_Buffer_new(0, 256, 0, 1); + GBAS(pbuf, "Location: /aqbt/devices/value.html?device="); + GWEN_Text_EscapeToBufferTolerant(sDeviceName, pbuf); + GBAS(pbuf, "&value="); + GWEN_Text_EscapeToBufferTolerant(sValueName, pbuf); + AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(pbuf)); + GWEN_Buffer_free(pbuf); + } + AQCGI_Request_SetResponseCode(rq, 303); + AQCGI_Request_SetResponseText(rq, "See other"); +#endif +} + + + +void _runValueWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_SESSION *session, + AQH_DATACLIENT *dc, + const char *sDeviceName, + const char *sValueName, + GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + AQH_VALUE_LIST *valueList; + + dbQuery=AQCGI_Request_GetDbQuery(rq); + DBG_ERROR(NULL, "Device=%s, value=%s", sDeviceName?sDeviceName:"", sValueName?sValueName:""); + + GBAA(dbuf,"

Value %s/%s

\n", sDeviceName, sValueName); + + valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0); + if (valueList) { + const AQH_VALUE *value; + + value=AQH_Value_List_First(valueList); + while(value) { + const char *s; + + s=AQH_Value_GetName(value); + if (s && *s && strcasecmp(s, sValueName)==0) + break; + value=AQH_Value_List_Next(value); + } + if (value && AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { + _mkValueForm(dc, sDeviceName, value, dbuf); + } + else { + GBAS(dbuf, "\n"); + GBAS(dbuf, ""); + + GBAS(dbuf, ""); + + GBAS(dbuf, ""); + + GBAS(dbuf, "
"); + GBAS(dbuf, ""); + GBAS(dbuf, "
"); + GBAS(dbuf, ""); + GBAS(dbuf, "
"); + GBAS(dbuf, ""); + GBAS(dbuf, "
"); + } + AQH_Value_List_free(valueList); + } +} + + + +void _mkValueForm(AQH_DATACLIENT *dc, const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueSystemName; + const char *sValueName; + uint64_t dataPoints[2]; + uint64_t recvdNum; + // uint64_t timestamp; + union {double f; uint64_t i;} u; + int intVal; + + sValueSystemName=AQH_Value_GetNameForSystem(value); + sValueName=AQH_Value_GetName(value); + recvdNum=AQH_DataClient_GetLastData(dc, sValueSystemName, &dataPoints[0], 1); + if (recvdNum>0) { + // timestamp=dataPoints[0]; + u.i=dataPoints[1]; + intVal=(int) u.f; + } + else { + u.i=0; + intVal=-1; + } + + GBAS(dbuf,"
\n"); + GBAA(dbuf, "\n", sDeviceName); + GBAA(dbuf, "\n", sValueName); + + DBG_ERROR(NULL, "Adding actor"); + switch(AQH_Value_GetModality(value)) { + case AQH_ValueModality_RGBW: _writeRgbwToForm(sValueName, u.f, dbuf); break; + case AQH_ValueModality_OnOff: _writeOnOffToForm(sValueName, intVal, dbuf); break; + case AQH_ValueModality_OnOffAuto: _writeOnOffAutoToForm(sValueName, intVal, dbuf); break; + default: GBAA(dbuf, "%.2f", u.f); break; + } /* switch */ + + GBAS(dbuf,""); + GBAS(dbuf, "
\n\n"); +} + + + +void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf) +{ +#if 1 + GBAA(dbuf, "", sValueName, color); +#else + GBAA(dbuf, "#%08x (#%08x)", + sValueName, + AQH_ModDevices_RgbwToHtmlColor(color), + AQH_ModDevices_RgbwToHtmlColor(color), + color); +#endif +} + + + +void _writeOnOffToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf) +{ + GBAA(dbuf, ""); +} + + + +void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf) +{ + GBAA(dbuf, ""); +} + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_value.h b/apps/aqhome-cgi/modules/devices/mdevices_value.h new file mode 100644 index 0000000..c1843f4 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_value.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_VALUE_H +#define AQHOME_CGI_MDEVICES_VALUE_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c b/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c new file mode 100644 index 0000000..3163f0e --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c @@ -0,0 +1,175 @@ +/**************************************************************************** + * 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_valuesgraph.h" +#include "./mdevices_index.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _writeValueToDetailedTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf); +static void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf); +static void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf); +static void _addGraphLink(const char *sDeviceName, const char *sValueName, const char *sPeriod, GWEN_BUFFER *dbuf, int withLink); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunValuesAsGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + const char *sDeviceName; + + dbQuery=AQCGI_Request_GetDbQuery(rq); + sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); + if (!(sDeviceName && *sDeviceName)) + AQH_ModDevices_RunIndex(m, rq, session, dc, dbuf); + else { + const char *sValueName; + + sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL); + if (sValueName && *sValueName) { + AQH_VALUE *value; + + GBAA(dbuf,"

Value %s/%s

\n", sDeviceName, sValueName); + value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName); + if (value) { + _writeValueToDetailedTable(sDeviceName, value, dbuf); + AQH_Value_free(value); + AQCGI_Request_AddResponseHeaderData(rq, "Refresh: 120"); + } + } + else { + AQH_VALUE_LIST *valueList; + + valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0); + if (valueList && AQH_Value_List_GetCount(valueList)) { + + GBAA(dbuf,"

Values for Device %s

\n", sDeviceName); + _writeValueListToTable(sDeviceName, valueList, dbuf); + GBAS(dbuf, "\n"); + } + else { + GBAS(dbuf,"

No values.

\n"); + } + AQH_Value_List_free(valueList); + AQCGI_Request_AddResponseHeaderData(rq, "Refresh: 305"); + } + } +} + + + +void _writeValueToDetailedTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueName; + + GBAS(dbuf, "\n"); + sValueName=AQH_Value_GetName(value); + + GBAS(dbuf, "\n"); +} + + + +void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) +{ + const AQH_VALUE *value; + + GBAS(dbuf, "
"); + _addGraphLink(sDeviceName, sValueName, "4h", dbuf, 0); + GBAS(dbuf, ""); + _addGraphLink(sDeviceName, sValueName, "1d", dbuf, 0); + GBAS(dbuf, "
"); + _addGraphLink(sDeviceName, sValueName, "1w", dbuf, 0); + GBAS(dbuf, ""); + _addGraphLink(sDeviceName, sValueName, "12m", dbuf, 0); + GBAS(dbuf, "
\n"); + + + value=AQH_Value_List_First(valueList); + while(value) { + if (AQH_Value_GetValueType(value)!=AQH_ValueType_Actor) + _writeValueToTable(sDeviceName, value, dbuf); + value=AQH_Value_List_Next(value); + } + GBAS(dbuf, "
\n"); +} + + + +void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf) +{ + const char *sValueName; + + /* name */ + sValueName=AQH_Value_GetName(value); + + GBAS(dbuf, ""); + _addGraphLink(sDeviceName, sValueName, "1d", dbuf, 1); + GBAS(dbuf, ""); + _addGraphLink(sDeviceName, sValueName, "1w", dbuf, 1); + GBAS(dbuf, "\n"); +} + + + +void _addGraphLink(const char *sDeviceName, const char *sValueName, const char *sPeriod, GWEN_BUFFER *dbuf, int withLink) +{ + if (withLink) { + GBAS(dbuf, ""); + } + + GBAS(dbuf, "\"%s\""); + + if (withLink) { + GBAS(dbuf, ""); + } +} + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h b/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h new file mode 100644 index 0000000..ff5c9a4 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_VALUESGRAPH_H +#define AQHOME_CGI_MDEVICES_VALUESGRAPH_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunValuesAsGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_valuestable.c b/apps/aqhome-cgi/modules/devices/mdevices_valuestable.c new file mode 100644 index 0000000..ef19476 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_valuestable.c @@ -0,0 +1,145 @@ +/**************************************************************************** + * 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_valuestable.h" +#include "./mdevices_index.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, uint32_t perms, GWEN_BUFFER *dbuf); +static void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, uint32_t perms, GWEN_BUFFER *dbuf); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunValuesAsTable(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + const char *sDeviceName; + uint32_t perms; + + perms=AQH_ModService_GetUserPerms(m); + + dbQuery=AQCGI_Request_GetDbQuery(rq); + sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); + if (!(sDeviceName && *sDeviceName)) + AQH_ModDevices_RunIndex(m, rq, session, dc, dbuf); + else { + AQH_VALUE_LIST *valueList; + + valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0); + if (valueList && AQH_Value_List_GetCount(valueList)) { + + GBAA(dbuf,"

Values for Device %s

\n", sDeviceName); + _writeValueListToTable(sDeviceName, valueList, perms, dbuf); + GBAS(dbuf, "\n"); + } + else { + GBAS(dbuf,"

No values.

\n"); + } + AQH_Value_List_free(valueList); + } +} + + + +void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, uint32_t perms, GWEN_BUFFER *dbuf) +{ + const AQH_VALUE *value; + + GBAS(dbuf, + "\n" + "" + "" + "" + "" + "" +#if 0 + "" + "" + "" +#endif + "" + "\n" + "\n"); + + value=AQH_Value_List_First(valueList); + while(value) { + //if (AQH_Value_GetModality(value)!=AQH_ValueModality_Stats) + _writeValueToTable(sDeviceName, value, perms, dbuf); + value=AQH_Value_List_Next(value); + } + GBAS(dbuf, + "\n" + "
NameTypeModalityDriverDeviceName for System
\n"); +} + + + +void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, uint32_t perms, GWEN_BUFFER *dbuf) +{ + const char *s; + + GBAS(dbuf, ""); + + /* name for system */ + s=AQH_Value_GetName(value); + if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) { + uint32_t pos; + + pos=GWEN_Buffer_GetPos(dbuf); + GBAS(dbuf,"%s", s); + } + else + GBAA(dbuf,"%s", s?s:""); + + s=AQH_ValueType_toString(AQH_Value_GetValueType(value)); + GBAA(dbuf, "%s", s?s:""); + + s=AQH_ValueModality_toString(AQH_Value_GetModality(value)); + GBAA(dbuf, "%s", s?s:""); + + GBAA(dbuf, "\n"); +} + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_valuestable.h b/apps/aqhome-cgi/modules/devices/mdevices_valuestable.h new file mode 100644 index 0000000..524ae05 --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_valuestable.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_VALUESTABLE_H +#define AQHOME_CGI_MDEVICES_VALUESTABLE_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunValuesAsTable(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/devices/mdevices_vgraph.c b/apps/aqhome-cgi/modules/devices/mdevices_vgraph.c new file mode 100644 index 0000000..ed3c0ae --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_vgraph.c @@ -0,0 +1,384 @@ +/**************************************************************************** + * 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_vgraph.h" + +#include "aqhome-cgi/service/module.h" +#include "aqhome-cgi/modules/mdataclient.h" + +#include +#include +#include +//#include +//#include + +#include +#include +#include + +#include +#include +#include + + + +/* ------------------------------------------------------------------------------------------------ + * defs and enums + * ------------------------------------------------------------------------------------------------ + */ + +#define GBAS GWEN_Buffer_AppendString +#define GBAA GWEN_Buffer_AppendArgs + + + +enum { + VALUEGRAPH_PERIOD_4H=1, + VALUEGRAPH_PERIOD_1D, + VALUEGRAPH_PERIOD_1W, + VALUEGRAPH_PERIOD_1M, + VALUEGRAPH_PERIOD_6M, + VALUEGRAPH_PERIOD_12M, +}; + + + +/* ------------------------------------------------------------------------------------------------ + * vars + * ------------------------------------------------------------------------------------------------ + */ + +typedef struct MY_GRAPH_PARAMS MY_GRAPH_PARAMS; +struct MY_GRAPH_PARAMS { + const char *name; + const char *title; + const char *modifiers; + int startTimeDiff; + int acceptedAgeInSeconds; +}; + + + +static MY_GRAPH_PARAMS _graphParams[]={ + {"4h", "last 4 hours", "Lm5", 4*60*60, 2*60}, + {"1d", "last 24 hours", "Lm30", 24*60*60, 5*60}, + {"1w", "last 7 days", "Lm240", 7*24*60*60, 15*60}, + {"1m", "last 30 days", "Lm480", 30*24*60*60, 60*60}, + {"6m", "last 6 months", "Lm720", 182*24*60*60, 60*60}, + {"12m","last 12 months", "Lm1440", 365*24*60*60, 60*60}, + {NULL, NULL, NULL, 0, 0} +}; + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void _runGraphValueWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_DATACLIENT *dc, + const char *sDeviceName, + const char *sValueName, + GWEN_BUFFER *dbuf); +static void _createGraph(AQH_DATACLIENT *dc, + const AQH_VALUE *v, + const MY_GRAPH_PARAMS *graphParams, + const char *graphTitle, int precision, const char *curveLabel, + const char *sImgFile, int imgWidth, int imgHeight, uint64_t numDataPoints); +static int _fileIsCurrent(const char *sPath, int seconds); +static AQDG_GRAPH *_mkGraphObjectWithTitle(const char *graphTitle, const MY_GRAPH_PARAMS *graphParams, int precision); +static void _mkPathForValueAndPeriod(AQH_MODULE *m, const AQH_VALUE *v, const MY_GRAPH_PARAMS *graphParams, GWEN_BUFFER *dbuf); +static AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName, + uint64_t tsBegin, uint64_t tsEnd, uint64_t num); +static AQDG_GRAPH_DATAPAIR_LIST *_createDataPairListFromDataPoints(const uint64_t *dataPoints, uint64_t numValues); +static const MY_GRAPH_PARAMS *_getParamsByName(const char *s); + + + +/* ------------------------------------------------------------------------------------------------ + * code + * ------------------------------------------------------------------------------------------------ + */ + +void AQH_ModDevices_RunGraphValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + const char *sDeviceName; + const char *sValueName; + + DBG_DEBUG(NULL, "GraphValue"); + dbQuery=AQCGI_Request_GetDbQuery(rq); + sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); + sValueName=GWEN_DB_GetCharValue(dbQuery, "value", 0, NULL); + DBG_DEBUG(NULL, "Device=%s, value=%s", sDeviceName?sDeviceName:"", sValueName?sValueName:""); + if (sDeviceName && *sDeviceName && sValueName && *sValueName) { + GWEN_BUFFER *bufDeviceName; + GWEN_BUFFER *bufValueName; + + bufDeviceName=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Text_UnescapeToBufferTolerant(sDeviceName, bufDeviceName); + bufValueName=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Text_UnescapeToBufferTolerant(sValueName, bufValueName); + _runGraphValueWithArgs(m, rq, dc, + GWEN_Buffer_GetStart(bufDeviceName), + GWEN_Buffer_GetStart(bufValueName), + dbuf); + GWEN_Buffer_free(bufValueName); + GWEN_Buffer_free(bufDeviceName); + } +} + + + +void _runGraphValueWithArgs(AQH_MODULE *m, + AQCGI_REQUEST *rq, + AQH_DATACLIENT *dc, + const char *sDeviceName, + const char *sValueName, + GWEN_BUFFER *dbuf) +{ + GWEN_DB_NODE *dbQuery; + AQH_VALUE *value; + const MY_GRAPH_PARAMS *graphParams; + const char *sPeriod; + + DBG_DEBUG(NULL, "GraphValue with args"); + dbQuery=AQCGI_Request_GetDbQuery(rq); + sPeriod=GWEN_DB_GetCharValue(dbQuery, "period", 0, NULL); + graphParams=_getParamsByName(sPeriod); + if (graphParams==NULL) + graphParams=&_graphParams[0]; + DBG_DEBUG(NULL, "Device=%s, value=%s, period=%s", + sDeviceName?sDeviceName:"", sValueName?sValueName:"", + sPeriod?sPeriod:""); + + value=AQH_ModDevices_GetValueForDevice(dc, sDeviceName, sValueName); + if (value) { + GWEN_BUFFER *fbuf; + int rv; + + fbuf=GWEN_Buffer_new(0, 256, 0, 1); + _mkPathForValueAndPeriod(m, value, graphParams, fbuf); + if (!_fileIsCurrent(GWEN_Buffer_GetStart(fbuf), graphParams->acceptedAgeInSeconds)) { + DBG_DEBUG(NULL, "Creating graph"); + _createGraph(dc, + value, + graphParams, + sValueName, + 2, + AQH_ValueModality_toString(AQH_Value_GetModality(value)), + GWEN_Buffer_GetStart(fbuf), + AQH_MODDEVICES_GRAPH_WIDTH, AQH_MODDEVICES_GRAPH_HEIGHT, + 100000); + } + + if (1) { + GWEN_BUFFER *ibuf; + + ibuf=GWEN_Buffer_new(0, 1024, 0, 1); + // return file + rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), ibuf); + if (rv<0) { + DBG_ERROR(NULL, "Error reading \"%s\" (%d)", GWEN_Buffer_GetStart(fbuf), rv); + } + else { + GWEN_Buffer_Reset(dbuf); + GWEN_Buffer_AppendBytes(dbuf, GWEN_Buffer_GetStart(ibuf), GWEN_Buffer_GetUsedBytes(ibuf)); + AQCGI_Request_AddResponseHeaderData(rq, "Content-type: image/png"); + AQCGI_Request_AddFlags(rq, AQH_MODSERVICE_RQFLAGS_RAWFILE); + } + GWEN_Buffer_free(ibuf); + } + + GWEN_Buffer_free(fbuf); + AQH_Value_free(value); + } + else { + DBG_ERROR(NULL, "Could not get value \"%s/%s\"", sDeviceName, sValueName); + } +} + + + +int _fileIsCurrent(const char *sPath, int seconds) +{ + struct stat sb; + time_t t1; + + if (lstat(sPath, &sb)==-1) { + DBG_ERROR(NULL, "Error on lstat(%s): %s (%d)", sPath, strerror(errno), errno); + return 0; + } + t1=time(0); + if ((t1-sb.st_mtime)<(time_t) seconds) { + DBG_DEBUG(NULL, "File %s is current", sPath); + return 1; + } + + return 0; +} + + + +void _createGraph(AQH_DATACLIENT *dc, + const AQH_VALUE *v, + const MY_GRAPH_PARAMS *graphParams, + const char *graphTitle, int precision, + const char *curveLabel, + const char *sImgFile, int imgWidth, int imgHeight, uint64_t numDataPoints) +{ + const char *sValue; + AQDG_GRAPH *g; + AQDG_DRAW_CONTEXT *drawContext; + AQDG_OBJECT *graphObject; + uint64_t tsBegin; + uint64_t tsEnd; + AQDG_GRAPH_DATAPAIR_LIST *dpList; + + sValue=AQH_Value_GetNameForSystem(v); + tsEnd=time(0); + tsBegin=time(0)-(graphParams->startTimeDiff); + g=_mkGraphObjectWithTitle(graphTitle, graphParams, precision); + + dpList=_requestDataPairList(dc, sValue, tsBegin, tsEnd, numDataPoints); + if (dpList) { + DBG_DEBUG(NULL, "Adding data for %s", sValue); + AQDG_TimeGraph_ModifyDataAndAddCurve(g, curveLabel?curveLabel:sValue, graphParams->modifiers, dpList); + } + else { + DBG_ERROR(NULL, "No data for %s", sValue); + AQDG_Graph_free(g); + return; + } + + AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0); + + DBG_DEBUG(NULL, "Draw graph for %s", sValue); + drawContext=AQDG_Draw_ContextCairo_Png_new(sImgFile, imgWidth, imgHeight); + graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, drawContext); + AQDG_Object_SetWidth(graphObject, imgWidth); + AQDG_Object_SetHeight(graphObject, imgHeight); + + AQDG_GraphWidget_SetupDefaultPens(graphObject); + AQDG_GraphWidget_SetupDefaultFonts(graphObject); + + AQDG_GraphWidget_FinishWithGraph(graphObject, g); + + AQDG_Object_free(graphObject); +} + + + +AQDG_GRAPH *_mkGraphObjectWithTitle(const char *graphTitle, const MY_GRAPH_PARAMS *graphParams, int precision) +{ + AQDG_GRAPH *g; + GWEN_BUFFER *tbuf; + + tbuf=GWEN_Buffer_new(0, 256, 0, 1); + + GBAA(tbuf, "%s - %s", graphTitle, graphParams->title); + + g=AQDG_TimeGraph_new(GWEN_Buffer_GetStart(tbuf), NULL, "Value", NULL, precision); + GWEN_Buffer_free(tbuf); + return g; +} + + +void _mkPathForValueAndPeriod(AQH_MODULE *m, const AQH_VALUE *v, const MY_GRAPH_PARAMS *graphParams, GWEN_BUFFER *dbuf) +{ + AQH_SERVICE *sv; + const char *s; + + sv=AQH_ModService_GetService(m); + + /* cache folder */ + s=AQH_Service_GetCacheFolder(sv); + GBAA(dbuf, "%s%s", s, GWEN_DIR_SEPARATOR_S); + + /* var name */ + s=AQH_Value_GetNameForSystem(v); + GWEN_Text_EscapeToBuffer(s, dbuf); + + GBAA(dbuf, "-%s.png", graphParams->name); +} + + + +AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName, + uint64_t tsBegin, uint64_t tsEnd, uint64_t num) +{ + uint64_t *dataPoints; + uint64_t recvdNum; + + dataPoints=malloc(num*sizeof(uint64_t)*2); + + recvdNum=AQH_DataClient_GetPeriodData(dc, valueName, dataPoints, num, tsBegin, tsEnd); + if (recvdNum>0) { + AQDG_GRAPH_DATAPAIR_LIST *dpList; + + dpList=_createDataPairListFromDataPoints(dataPoints, recvdNum); + free(dataPoints); + return dpList; + } + else { + DBG_ERROR(NULL, "No data received for %s", valueName); + free(dataPoints); + return NULL; + } +} + + + +AQDG_GRAPH_DATAPAIR_LIST *_createDataPairListFromDataPoints(const uint64_t *dataPoints, uint64_t numValues) +{ + AQDG_GRAPH_DATAPAIR_LIST *dpList; + uint64_t i; + + DBG_DEBUG(NULL, "Got %d datapoints", (int) numValues); + dpList=AQDG_Graph_DataPair_List_new(); + for(i=0; iname) { + if (strcasecmp(p->name, s)==0) + return p; + p++; + } + + return NULL; +} + + + diff --git a/apps/aqhome-cgi/modules/devices/mdevices_vgraph.h b/apps/aqhome-cgi/modules/devices/mdevices_vgraph.h new file mode 100644 index 0000000..a24dd9c --- /dev/null +++ b/apps/aqhome-cgi/modules/devices/mdevices_vgraph.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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. + ****************************************************************************/ + +#ifndef AQHOME_CGI_MDEVICES_VGRAPH_H +#define AQHOME_CGI_MDEVICES_VGRAPH_H + + +#include "aqhome-cgi/modules/devices/mdevices.h" + +#include "aqhome/aqhome.h" +#include "aqhome/dataclient/client.h" + +#include + +#include + + + +void AQH_ModDevices_RunGraphValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); + + +#endif diff --git a/apps/aqhome-cgi/modules/html/pics/cancel.png b/apps/aqhome-cgi/modules/html/pics/cancel.png new file mode 100644 index 0000000..20ada8f Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/cancel.png differ diff --git a/apps/aqhome-cgi/modules/html/pics/edit.png b/apps/aqhome-cgi/modules/html/pics/edit.png new file mode 100644 index 0000000..3e23e5f Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/edit.png differ diff --git a/apps/aqhome-cgi/modules/html/pics/graph.png b/apps/aqhome-cgi/modules/html/pics/graph.png new file mode 100644 index 0000000..77d7157 Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/graph.png differ diff --git a/apps/aqhome-cgi/modules/html/pics/minus.png b/apps/aqhome-cgi/modules/html/pics/minus.png new file mode 100644 index 0000000..6fe6cf6 Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/minus.png differ diff --git a/apps/aqhome-cgi/modules/html/pics/ok.png b/apps/aqhome-cgi/modules/html/pics/ok.png new file mode 100644 index 0000000..3a6984f Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/ok.png differ diff --git a/apps/aqhome-cgi/modules/html/pics/plus.png b/apps/aqhome-cgi/modules/html/pics/plus.png new file mode 100644 index 0000000..dd4a665 Binary files /dev/null and b/apps/aqhome-cgi/modules/html/pics/plus.png differ diff --git a/apps/aqhome-cgi/modules/html/style.css b/apps/aqhome-cgi/modules/html/style.css new file mode 100644 index 0000000..18a4b39 --- /dev/null +++ b/apps/aqhome-cgi/modules/html/style.css @@ -0,0 +1,63 @@ +body { + background-color: whitesmoke; +} + +table.datatable { + border: thin solid; + border-collapse: collapse; +} + + +table.datatable th, td { + border: thin solid; + border-collapse: collapse; + padding: 5px; +} + + +table.datatable tbody tr:nth-child(odd) { + background-color: #ffffff; +} + + + +table.formtable { + border: thin solid; + border-collapse: collapse; +} + + +table.formtable th, td { + border: thin solid; + border-collapse: collapse; + padding: 5px; +} + + + +ul.mainmenu { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + background-color: #333333; +} + + +ul.mainmenu li { + float: left; +} + +ul.mainmenu li a { + display: block; + color: white; + text-align: center; + padding: 14px 16px; + text-decoration: none; +} + +ul.mainmenu li a:hover { + background-color: #111111; +} + + diff --git a/apps/aqhome-cgi/modules/mdevices.c b/apps/aqhome-cgi/modules/mdevices.c deleted file mode 100644 index baca810..0000000 --- a/apps/aqhome-cgi/modules/mdevices.c +++ /dev/null @@ -1,584 +0,0 @@ -/**************************************************************************** - * 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.h" - -#include "aqhome-cgi/service/module.h" -#include "aqhome-cgi/modules/mdataclient.h" - -#include -#include -#include - - - -/* ------------------------------------------------------------------------------------------------ - * defs and enums - * ------------------------------------------------------------------------------------------------ - */ - -#define GBAS GWEN_Buffer_AppendString -#define GBAA GWEN_Buffer_AppendArgs - -#define P_DEVICEREAD AQH_MODDEVICES_PERMS_DEVICEREAD -#define P_VALUEREAD AQH_MODDEVICES_PERMS_VALUEREAD -#define P_VALUEWRITE AQH_MODDEVICES_PERMS_VALUEWRITE - - - -/* ------------------------------------------------------------------------------------------------ - * forward declarations - * ------------------------------------------------------------------------------------------------ - */ - -static void _createPermDefList(AQH_MODULE *m); -static void _createRoleList(AQH_MODULE *m); - -static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName); -static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem); - -static void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); -static void _handleRqValuesGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); -static void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); - -static void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); -static void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); - -static void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf); -static void _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf); -static void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf); -static void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf); -static uint32_t _colorFromHexString(const char *s); - - - -/* ------------------------------------------------------------------------------------------------ - * vars - * ------------------------------------------------------------------------------------------------ - */ - -static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={ - {"index.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD, _handleRqIndexGet}, - {"values.html", AQCGI_REQUEST_METHOD_GET, P_DEVICEREAD | P_VALUEREAD, _handleRqValuesGet}, - {"setdata.html", AQCGI_REQUEST_METHOD_POST, P_VALUEWRITE, _handleRqSetDataPost}, - {NULL, 0, 0, NULL} -}; - - - -/* ------------------------------------------------------------------------------------------------ - * code - * ------------------------------------------------------------------------------------------------ - */ - -void AQH_ModDevices_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder) -{ - AQH_ModService_Extend(m, sv, baseFolder); - AQH_ModService_SetHandleRequestFn(m, _handleRequest); - AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule); -} - - - -int AQH_ModDevices_Create(AQH_SERVICE *sv) -{ - AQH_MODULE *m; - int rv; - - m=AQH_Module_new(); - AQH_Module_SetName(m, "devices"); - AQH_Module_SetDescr(m, "device module"); - AQH_Module_SetGuestPerms(m, 0); - - _createPermDefList(m); - _createRoleList(m); - - rv=AQH_Service_AddModule(sv, m); - if (rv<0) { - DBG_INFO(NULL, "here (%d)", rv); - } - AQH_Module_free(m); - return rv; -} - - - -void _createPermDefList(AQH_MODULE *m) -{ - AQH_PERMDEF_LIST *permDefList; - - permDefList=AQH_PermDef_List_new(); - - AQH_ModService_AddPermDef(permDefList, "DeviceRead", 0x001, "Read and list devices"); - AQH_ModService_AddPermDef(permDefList, "DeviceWrite", 0x002, "Modify devices"); - AQH_ModService_AddPermDef(permDefList, "DeviceAdd", 0x004, "Add devices"); - AQH_ModService_AddPermDef(permDefList, "DeviceDel", 0x008, "Remove devices"); - - AQH_ModService_AddPermDef(permDefList, "ValueRead", 0x010, "Read and list values"); - AQH_ModService_AddPermDef(permDefList, "ValueWrite", 0x020, "Modify values"); - AQH_ModService_AddPermDef(permDefList, "ValueAdd", 0x040, "Add values"); - AQH_ModService_AddPermDef(permDefList, "ValueDel", 0x080, "Remove values"); - AQH_ModService_AddPermDef(permDefList, "ValueSet", 0x100, "Set values"); - - AQH_Module_SetPermDefList(m, permDefList); -} - - - -void _createRoleList(AQH_MODULE *m) -{ - AQH_ROLE_LIST *roleList; - int id=0; - - roleList=AQH_Role_List_new(); - AQH_ModService_AddRole(roleList, id++, "Reader", - AQH_MODDEVICES_PERMS_DEVICEREAD | - AQH_MODDEVICES_PERMS_VALUEREAD, - "Read devices and values"); - AQH_ModService_AddRole(roleList, id++, "Writer", - AQH_MODDEVICES_PERMS_DEVICEREAD | - AQH_MODDEVICES_PERMS_DEVICEWRITE | - AQH_MODDEVICES_PERMS_DEVICEADD | - AQH_MODDEVICES_PERMS_DEVICEDEL | - AQH_MODDEVICES_PERMS_VALUEREAD | - AQH_MODDEVICES_PERMS_VALUEWRITE | - AQH_MODDEVICES_PERMS_VALUEADD | - AQH_MODDEVICES_PERMS_VALUEDEL | - AQH_MODDEVICES_PERMS_VALUESET, - "Read and write devices and values"); - AQH_ModService_AddRole(roleList, id++, "Setter", - AQH_MODDEVICES_PERMS_DEVICEREAD | - AQH_MODDEVICES_PERMS_VALUEREAD | - AQH_MODDEVICES_PERMS_VALUESET, - "Set values"); - AQH_Module_SetRoleList(m, roleList); -} - - - -AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName) -{ - return NULL; -} - - - -int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem) -{ - AQH_ModService_HandleRequestWithTable(m, rq, session, sLastPathElem, _requestTable); - return AQCGI_SendResponse(rq); -} - - - -void _handleRqIndexGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) -{ - AQH_ModDataClient_HandleRequest(m, rq, session, _runIndex, dbuf); -} - - - -void _handleRqValuesGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) -{ - AQH_ModDataClient_HandleRequest(m, rq, session, _runValues, dbuf); -} - - - -void _handleRqSetDataPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) -{ - AQH_ModDataClient_HandleRequest(m, rq, session, _runSetData, dbuf); -} - - - -void _runIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) -{ - AQH_DEVICE_LIST *deviceList; - AQH_DEVICE *device; - uint32_t perms; - - perms=AQH_ModService_GetUserPerms(m); - - deviceList=AQH_DataClient_GetDevices(dc, NULL); - if (deviceList==NULL) { - DBG_ERROR(NULL, "No device received"); - GBAS(dbuf, "

No devices.

"); - return; - } - - GBAS(dbuf, "

Devices

\n"); - GBAS(dbuf, - "\n" - "\n" - "" - "" - "" - "" - "" -#if 0 - "" - "" - "" - "" - "" -#endif - "\n" - "\n" - "\n"); - - device=AQH_Device_List_First(deviceList); - while(device) { - const char *s; - - GBAA(dbuf, ""); - /* name for system */ - s=AQH_Device_GetNameForSystem(device); - if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) { - GBAS(dbuf,"", s?s:""); - } - else - GBAA(dbuf,"", s?s:""); - /* room */ - s=AQH_Device_GetRoomName(device); - GBAA(dbuf, "", s?s:""); - /* location */ - s=AQH_Device_GetLocation(device); - GBAA(dbuf, "", s?s:""); - /* description */ - s=AQH_Device_GetDescription(device); - GBAA(dbuf, "", s?s:""); -#if 0 - /* device type */ - s=AQH_Device_GetDeviceType(device); - GBAA(dbuf, "", s?s:""); - /* driver */ - s=AQH_Device_GetDriver(device); - GBAA(dbuf, "", s?s:""); - /* short device name */ - s=AQH_Device_GetName(device); - GBAA(dbuf, "", s?s:""); - /* GUI name for device */ - s=AQH_Device_GetNameForGui(device); - GBAA(dbuf, "", s?s:""); - /* manufacturer */ - s=AQH_Device_GetManufacturer(device); - GBAA(dbuf, "", s?s:""); -#endif - - GBAA(dbuf, ""); - device=AQH_Device_List_Next(device); - } - - GBAS(dbuf, - "\n" - "
Name For SystemRoomLocationDescriptionTypeDriverNameGUI NameManufacturer
%s%s%s%s%s%s%s%s%s%s
\n"); - AQH_Device_List_free(deviceList); -} - - - -void _runValues(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) -{ - GWEN_DB_NODE *dbQuery; - const char *sDeviceName; - - dbQuery=AQCGI_Request_GetDbQuery(rq); - sDeviceName=GWEN_DB_GetCharValue(dbQuery, "device", 0, NULL); - if (!(sDeviceName && *sDeviceName)) - _runIndex(m, rq, session, dc, dbuf); - else { - AQH_VALUE_LIST *valueList; - - valueList=AQH_DataClient_GetValues(dc, sDeviceName, 0); - if (valueList && AQH_Value_List_GetCount(valueList)) { - - GBAA(dbuf,"

Values for Device %s

\n", sDeviceName); - - GBAS(dbuf,"
\n"); - GBAA(dbuf, "\n", sDeviceName); - _writeValueListToTable(valueList, dbuf); - - GBAS(dbuf,""); - GBAS(dbuf, "
\n\n"); - } - else { - GBAS(dbuf,"

No values.

\n"); - } - AQH_Value_List_free(valueList); - } -} - - - -void _runSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf) -{ - AQH_SERVICE *sv; - GWEN_DB_NODE *dbPost; - const char *sDeviceName; - AQH_VALUE_LIST *valueList; - - /* sample data */ - sv=AQH_ModService_GetService(m); - dbPost=AQCGI_Request_GetDbPostBody(rq); - sDeviceName=dbPost?GWEN_DB_GetCharValue(dbPost, "device", 0, NULL):NULL; - valueList=sDeviceName?AQH_DataClient_GetValues(dc, sDeviceName, 0):NULL; - if (valueList && AQH_Value_List_GetCount(valueList)) { - const AQH_VALUE *value; - - value=AQH_Value_List_First(valueList); - while(value) { - if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) { - const char *sValueSystemName; - const char *sValueName; - const char *sValue; - int rv; - - sValueSystemName=AQH_Value_GetNameForSystem(value); - sValueName=AQH_Value_GetName(value); - sValue=GWEN_DB_GetCharValue(dbPost, sValueName, 0, NULL); - if (sValueName && *sValueName) { - DBG_ERROR(NULL, "Setting value %s to %s", sValueName?sValueName:"no name", sValue?sValue:"no value"); - switch(AQH_Value_GetModality(value)) { - case AQH_ValueModality_RGBW: - if (sValue) { - uint32_t color; - char colbuf[16]; - - color=_colorFromHexString(sValue); - snprintf(colbuf, sizeof(colbuf), "0x%08x", color); - DBG_ERROR(NULL, "Send value [%s] to %s", colbuf, sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, colbuf); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - GBAA(dbuf, "

Error setting value for %s

", sValueSystemName); - } - } - break; - case AQH_ValueModality_OnOff: - if (sValue) { - if (strcasecmp(sValue, "unchanged")==0) { - DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); - } - else if (strcasecmp(sValue, "on")==0) { - DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "1"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "off")==0) { - DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "0"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else { - } - } - break; - case AQH_ValueModality_OnOffAuto: - if (sValue) { - if (strcasecmp(sValue, "unchanged")==0) { - DBG_ERROR(NULL, "Value %s unchanged", sValueSystemName); - } - else if (strcasecmp(sValue, "on")==0) { - DBG_ERROR(NULL, "Send value 1 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "1"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "off")==0) { - DBG_ERROR(NULL, "Send value 0 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "0"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else if (strcasecmp(sValue, "auto")==0) { - DBG_ERROR(NULL, "Send value 2 to %s", sValueSystemName); - rv=AQH_DataClient_SetData(dc, value, "2"); - if (rv<0) { - DBG_ERROR(NULL, "Error sending data: %d", rv); - } - } - else { - DBG_ERROR(NULL, "Invalid value [%s] for %s", sValue, sValueSystemName); - } - } - break; - default: - break; - } /* switch */ - } /* if (sValueName) */ - } - value=AQH_Value_List_Next(value); - } /* while */ - - - } - AQH_Value_List_free(valueList); - - if (sDeviceName && *sDeviceName) { - GWEN_BUFFER *pbuf; - - pbuf=GWEN_Buffer_new(0, 256, 0, 1); - GBAS(pbuf, "Location: /aqbt/devices/values.html?device="); - GWEN_Text_EscapeToBufferTolerant(sDeviceName, 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 _writeValueListToTable(const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf) -{ - const AQH_VALUE *value; - - GBAS(dbuf, - "\n" - "" - "" - "" - "" - "" -#if 0 - "" - "" - "" -#endif - "" - "" - "\n" - "\n"); - - value=AQH_Value_List_First(valueList); - while(value) { - _writeValueToTable(value, dbuf); - value=AQH_Value_List_Next(value); - } - GBAS(dbuf, - "\n" - "
NameTypeModalityDriverDeviceName for SystemAction
\n"); -} - - - -void _writeValueToTable(const AQH_VALUE *value, GWEN_BUFFER *dbuf) -{ - const char *s; - - GBAS(dbuf, ""); - - s=AQH_Value_GetName(value); - GBAA(dbuf, "%s", s?s:""); - - s=AQH_ValueType_toString(AQH_Value_GetValueType(value)); - GBAA(dbuf, "%s", s?s:""); - - s=AQH_ValueModality_toString(AQH_Value_GetModality(value)); - GBAA(dbuf, "%s", s?s:""); - -#if 0 - s=AQH_Value_GetDriver(value); - GBAA(dbuf, "%s", s?s:""); - - s=AQH_Value_GetDeviceNameForSystem(value); - GBAA(dbuf, "%s", s?s:""); - - s=AQH_Value_GetNameForSystem(value); - GBAA(dbuf, "%s", s?s:""); -#endif - - GBAS(dbuf, ""); - if (AQH_Value_GetValueType(value)==AQH_ValueType_Actor) - _addValueActionToForm(value, dbuf); - GBAS(dbuf, ""); - - GBAA(dbuf, "\n"); -} - - - -void _addValueActionToForm(const AQH_VALUE *value, GWEN_BUFFER *dbuf) -{ - const char *sValueName; - - sValueName=AQH_Value_GetName(value); - switch(AQH_Value_GetModality(value)) { - case AQH_ValueModality_RGBW: - GBAA(dbuf, "", sValueName); - break; - case AQH_ValueModality_OnOff: - GBAA(dbuf, - "", - sValueName); - break; - case AQH_ValueModality_OnOffAuto: - GBAA(dbuf, - "", - sValueName); - break; - default: - break; - } -} - - - -uint32_t _colorFromHexString(const char *s) -{ - uint32_t colorIn=0; - uint32_t colorOut; - - while(*s && *s<33) - s++; - if (*s=='#') - s++; - while(*s) { - uint c; - - c=(*s)-'0'; - if (c>9) - c-=7; - colorIn<<=4; - colorIn|=c & 0xf; - s++; - } - - /* hex 00RRGGBB -> GGRRWWBB */ - colorOut=(colorIn & 0x00ff0000) | ((colorIn & 0x00ff00)<<16) | (colorIn & 0x0000ff); - return colorOut; -} - - - - - - diff --git a/apps/aqhome-cgi/modules/mroot.c b/apps/aqhome-cgi/modules/mroot.c index 84e9b74..e9a5c8d 100644 --- a/apps/aqhome-cgi/modules/mroot.c +++ b/apps/aqhome-cgi/modules/mroot.c @@ -14,7 +14,7 @@ #include "./mroot_p.h" #include "aqhome-cgi/service/module.h" -#include "aqhome-cgi/modules/mdevices.h" +#include "aqhome-cgi/modules/devices/mdevices.h" #include "aqhome-cgi/modules/common/madmin.h" #include diff --git a/apps/aqhome-cgi/service/service.c b/apps/aqhome-cgi/service/service.c index c163972..f0abdfd 100644 --- a/apps/aqhome-cgi/service/service.c +++ b/apps/aqhome-cgi/service/service.c @@ -27,7 +27,7 @@ GWEN_LIST_FUNCTIONS(AQH_SERVICE, AQH_Service); -AQH_SERVICE *AQH_Service_new(void) +AQH_SERVICE *AQH_Service_new(const char *baseFolder, const char *baseUrl) { AQH_SERVICE *sv; @@ -35,6 +35,32 @@ AQH_SERVICE *AQH_Service_new(void) GWEN_INHERIT_INIT(AQH_SERVICE, sv); GWEN_LIST_INIT(AQH_SERVICE, sv); + sv->baseUrl=baseUrl?strdup(baseUrl):NULL; + sv->baseFolder=baseFolder?strdup(baseFolder):NULL; + + if (sv->baseFolder) { + GWEN_BUFFER *dbuf; + uint32_t pos; + + dbuf=GWEN_Buffer_new(0, 256, 0, 1); + GWEN_Buffer_AppendArgs(dbuf, "%s%s", sv->baseFolder, GWEN_DIR_SEPARATOR_S); + pos=GWEN_Buffer_GetPos(dbuf); + + /* data folder */ + GWEN_Buffer_AppendString(dbuf, "data"); + sv->runtimeFolder=strdup(GWEN_Buffer_GetStart(dbuf)); + DBG_ERROR(NULL, "Runtime folder: %s", GWEN_Buffer_GetStart(dbuf)); + GWEN_Buffer_Crop(dbuf, 0, pos); + + /* cache folder */ + GWEN_Buffer_AppendString(dbuf, "cache"); + sv->cacheFolder=strdup(GWEN_Buffer_GetStart(dbuf)); + DBG_ERROR(NULL, "Cache folder: %s", GWEN_Buffer_GetStart(dbuf)); + GWEN_Buffer_Crop(dbuf, 0, pos); + + GWEN_Buffer_free(dbuf); + } + return sv; } @@ -46,11 +72,44 @@ void AQH_Service_free(AQH_SERVICE *sv) GWEN_LIST_FINI(AQH_SERVICE, sv); GWEN_INHERIT_FINI(AQH_SERVICE, sv); + free(sv->baseUrl); + free(sv->baseFolder); + free(sv->runtimeFolder); + free(sv->cacheFolder); GWEN_FREE_OBJECT(sv); } } + +const char *AQH_Service_GetBaseUrl(const AQH_SERVICE *sv) +{ + return sv?sv->baseUrl:NULL; +} + + + +const char *AQH_Service_GetBaseFolder(const AQH_SERVICE *sv) +{ + return sv?sv->baseFolder:NULL; +} + + + +const char *AQH_Service_GetRuntimeFolder(const AQH_SERVICE *sv) +{ + return sv?sv->runtimeFolder:NULL; +} + + + +const char *AQH_Service_GetCacheFolder(const AQH_SERVICE *sv) +{ + return sv?sv->cacheFolder:NULL; +} + + + #if 0 AQH_MODULE *AQH_Service_GetModuleByPath(const AQH_SERVICE *sv, const char *s) { diff --git a/apps/aqhome-cgi/service/service.h b/apps/aqhome-cgi/service/service.h index e8b258f..ae2e3b4 100644 --- a/apps/aqhome-cgi/service/service.h +++ b/apps/aqhome-cgi/service/service.h @@ -52,10 +52,13 @@ typedef GWEN_STRINGLIST* (*AQH_SERVICE_LISTSESSIONS_FN)(AQH_SERVICE *sv); -AQH_SERVICE *AQH_Service_new(void); +AQH_SERVICE *AQH_Service_new(const char *baseFolder, const char *baseUrl); void AQH_Service_free(AQH_SERVICE *sv); - +const char *AQH_Service_GetBaseUrl(const AQH_SERVICE *sv); +const char *AQH_Service_GetBaseFolder(const AQH_SERVICE *sv); +const char *AQH_Service_GetRuntimeFolder(const AQH_SERVICE *sv); +const char *AQH_Service_GetCacheFolder(const AQH_SERVICE *sv); int AQH_Service_HandleRequest(AQH_SERVICE *sv, AQCGI_REQUEST *req); diff --git a/apps/aqhome-cgi/service/service_p.h b/apps/aqhome-cgi/service/service_p.h index 7311e35..75a519c 100644 --- a/apps/aqhome-cgi/service/service_p.h +++ b/apps/aqhome-cgi/service/service_p.h @@ -17,6 +17,11 @@ struct AQH_SERVICE { GWEN_INHERIT_ELEMENT(AQH_SERVICE); GWEN_LIST_ELEMENT(AQH_SERVICE); + char *baseUrl; + char *baseFolder; + char *runtimeFolder; + char *cacheFolder; + AQH_SERVICE_HANDLEREQUEST_FN handleRequestFn; AQH_SERVICE_LOADUSER_FN loadUserFn; diff --git a/apps/aqhome-cgi/service_file.c b/apps/aqhome-cgi/service_file.c index eabafd0..5f5d6c3 100644 --- a/apps/aqhome-cgi/service_file.c +++ b/apps/aqhome-cgi/service_file.c @@ -79,16 +79,15 @@ static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName); * ------------------------------------------------------------------------------------------------ */ -AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder) +AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder, const char *baseUrl) { AQH_SERVICE *sv; AQH_SERVICE_FILE *xs; GWEN_BUFFER *dbuf; - sv=AQH_Service_new(); + sv=AQH_Service_new(baseFolder, baseUrl); GWEN_NEW_OBJECT(AQH_SERVICE_FILE, xs); GWEN_INHERIT_SETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv, xs, _freeData); - xs->baseFolder=strdup(baseFolder); AQH_Service_SetLoadUserFn(sv, _loadUser); AQH_Service_SetSaveUserFn(sv, _saveUser); @@ -109,7 +108,7 @@ AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder) AQH_Service_SetListSessionsFn(sv, _listSessions); dbuf=GWEN_Buffer_new(0, 256, 0, 1); - GWEN_Buffer_AppendArgs(dbuf, "dir://%s", baseFolder); + GWEN_Buffer_AppendArgs(dbuf, "dir://%s", AQH_Service_GetRuntimeFolder(sv)); DBG_ERROR(NULL, "Creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf)); xs->configMgr=GWEN_ConfigMgr_Factory(GWEN_Buffer_GetStart(dbuf)); if (xs->configMgr==NULL) { @@ -131,7 +130,6 @@ void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p) xs=(AQH_SERVICE_FILE*) p; GWEN_ConfigMgr_free(xs->configMgr); - free(xs->baseFolder); GWEN_FREE_OBJECT(xs); } diff --git a/apps/aqhome-cgi/service_file.h b/apps/aqhome-cgi/service_file.h index 85e1c44..b29052e 100644 --- a/apps/aqhome-cgi/service_file.h +++ b/apps/aqhome-cgi/service_file.h @@ -13,7 +13,7 @@ #include "aqhome-cgi/service/service.h" -AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder); +AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder, const char *baseUrl); diff --git a/apps/aqhome-cgi/service_file_p.h b/apps/aqhome-cgi/service_file_p.h index afee436..018c46f 100644 --- a/apps/aqhome-cgi/service_file_p.h +++ b/apps/aqhome-cgi/service_file_p.h @@ -1,6 +1,6 @@ /**************************************************************************** * This file is part of the project AqHome. - * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * 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. @@ -18,7 +18,6 @@ typedef struct AQH_SERVICE_FILE AQH_SERVICE_FILE; struct AQH_SERVICE_FILE { - char *baseFolder; GWEN_CONFIGMGR *configMgr; }; diff --git a/apps/aqhome-data/s_setdata.c b/apps/aqhome-data/s_setdata.c index a80e113..aa4360b 100644 --- a/apps/aqhome-data/s_setdata.c +++ b/apps/aqhome-data/s_setdata.c @@ -42,14 +42,15 @@ * ------------------------------------------------------------------------------------------------ */ +static void _storeDatapoint(AQHOME_SERVER *xo, const AQH_VALUE *v, double valueData); static AQH_MSG_REQUEST *_mkRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, uint32_t requestMsgId, AQH_OBJECT *epDriver, - const AQH_VALUE *v, const char *data); + const AQH_VALUE *v, double data); static void _rqSubRequestFinished(AQH_MSG_REQUEST *rq, AQH_MSG_REQUEST *subRq, int reason); static void _rqAbort(AQH_MSG_REQUEST *rq, int reason); -static AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, const char *data); +static AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, double data); static int _subRqHandleResponse(AQH_MSG_REQUEST *rq, const AQH_MESSAGE *msg); static void _subRqAbort(AQH_MSG_REQUEST *rq, int reason); @@ -76,11 +77,11 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ recvdValue=AQH_IpcdMessageSetData_ReadValue(tagList); if (recvdValue) { const char *valueName; - char *valueDataFreeable; + double valueData; AQH_VALUE *systemValue; valueName=AQH_Value_GetNameForSystem(recvdValue); - valueDataFreeable=AQH_IpcdMessageSetData_ReadData(tagList); + valueData=AQH_IpcdMessageSetData_ReadData(tagList); systemValue=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName); if (systemValue) { @@ -96,8 +97,10 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AQH_MSG_REQUEST *rq; DBG_ERROR(NULL, "Creating SETDATA request for driver endpoint (%s)", AQH_Endpoint_GetServiceName(epDriver)); - rq=_mkRequest_SetData(o, epSrc, msgId, epDriver, systemValue, valueDataFreeable); + rq=_mkRequest_SetData(o, epSrc, msgId, epDriver, systemValue, valueData); AqHomeDataServer_AddRequestToTree(o, rq); + + _storeDatapoint(xo, systemValue, valueData); } else { DBG_ERROR(NULL, "Driver \"%s\" not available", driverName); @@ -119,7 +122,6 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AqHomeDataServer_SendResponseResultToEndpoint(epSrc, msgId, AQH_MSGDATA_RESULT_ERROR_NOTFOUND); } AQH_Value_free(recvdValue); - free(valueDataFreeable); } /* if recvdValue */ else { DBG_ERROR(NULL, "No value in message"); @@ -131,6 +133,23 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ +void _storeDatapoint(AQHOME_SERVER *xo, const AQH_VALUE *v, double valueData) +{ + uint64_t timestamp; + int rv; + + timestamp=(uint64_t) time(NULL); + rv=AQH_Storage_AddDatapoint(xo->storage, AQH_Value_GetId(v), timestamp, valueData); + if (rv<0) { + DBG_INFO(NULL, "here (%d)", rv); + } + else { + DBG_INFO(NULL, "Datapoint added for value \"%s\"", AQH_Value_GetNameForSystem(v)); + } +} + + + /* ------------------------------------------------------------------------------------------------ * IPC Request SETDATA */ @@ -138,7 +157,7 @@ void AqHomeDataServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, const AQH_ AQH_MSG_REQUEST *_mkRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epSrc, uint32_t requestMsgId, AQH_OBJECT *epDriver, - const AQH_VALUE *v, const char *data) + const AQH_VALUE *v, double data) { AQH_MSG_REQUEST *rq; AQH_MSG_REQUEST *subRq; @@ -205,7 +224,7 @@ void _rqAbort(AQH_MSG_REQUEST *rq, int reason) */ -AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, const char *data) +AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_OBJECT *epDriver, const AQH_VALUE *v, double data) { AQH_MSG_REQUEST *rq; uint16_t msgId; diff --git a/apps/aqhome-mqttlog/s_setdata.c b/apps/aqhome-mqttlog/s_setdata.c index 13aa5ea..0cb54d6 100644 --- a/apps/aqhome-mqttlog/s_setdata.c +++ b/apps/aqhome-mqttlog/s_setdata.c @@ -30,8 +30,13 @@ */ static void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, - const char *valueName, const char *valueData); -static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData); + const char *valueName, double valueData); +static void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, + const AQHMQTT_DEVICE *device, + const AQHMQTT_TOPIC *topic, + const AQHMQTT_VALUE *value, + double valueData); +static const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double valueData); static GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic); @@ -65,12 +70,11 @@ void AQH_MqttLogServer_HandleSetData(AQH_OBJECT *o, device=AQH_MqttLogServer_FindRegisteredDevice(o, deviceName); if (device) { - char *valueDataFreeable; + double valueData; DBG_ERROR(NULL, "Sending data to value \"%s\" of device \"%s\"", valueName, deviceName); - valueDataFreeable=AQH_IpcdMessageSetData_ReadData(tagList); - _sendDataForDevice(xo, device, valueName, valueDataFreeable); - free(valueDataFreeable); + valueData=AQH_IpcdMessageSetData_ReadData(tagList); + _sendDataForDevice(xo, device, valueName, valueData); } else { DBG_ERROR(NULL, "Device \"%s\" not found", deviceName); @@ -93,7 +97,7 @@ void AQH_MqttLogServer_HandleSetData(AQH_OBJECT *o, void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, - const char *valueName, const char *valueData) + const char *valueName, double valueData) { const char *deviceId; @@ -116,7 +120,7 @@ void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, if (value) { /* found value, create publish msg, send */ DBG_ERROR(NULL, "Topic \"%s\" contains value \"%s\"", AQHMQTT_Topic_GetName(topic), valueName); - _sendValueToMqtt(xo, deviceId, topic, valueData); + _sendValueToMqtt(xo, device, topic, value, valueData); } } /* if out */ topic=AQHMQTT_Topic_List_Next(topic); @@ -130,32 +134,82 @@ void _sendDataForDevice(AQH_MQTTLOG_SERVER *xo, -void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, const char *deviceId, const AQHMQTT_TOPIC *topic, const char *valueData) +void _sendValueToMqtt(AQH_MQTTLOG_SERVER *xo, + const AQHMQTT_DEVICE *device, + const AQHMQTT_TOPIC *topic, + const AQHMQTT_VALUE *value, + double valueData) { + const char *deviceId; + const char *translatedValue; GWEN_BUFFER *buf; #if !DEBUG_DRY_RUN AQH_MESSAGE *msgOut; #endif + deviceId=AQHMQTT_Device_GetId(device); buf=_createBufferForTopic(deviceId, topic); + translatedValue=_valueTranslatedForDriver(value, valueData); + if (translatedValue && *translatedValue) { + DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), translatedValue); + msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), (const uint8_t*)translatedValue, strlen(translatedValue)); + } + else { + GWEN_BUFFER *vbuf; + + vbuf=GWEN_Buffer_new(0, 64, 0, 1); + GWEN_Buffer_AppendArgs(vbuf, "%f", valueData); + DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetStart(vbuf)); + msgOut=AQH_MqttMessagePublish_new(0, 0, + GWEN_Buffer_GetStart(buf), + (const uint8_t*)GWEN_Buffer_GetStart(vbuf), + GWEN_Buffer_GetUsedBytes(vbuf)); + GWEN_Buffer_free(vbuf); + } + #if !DEBUG_DRY_RUN - DBG_ERROR(NULL, "MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); - msgOut=AQH_MqttMessagePublish_new(0, 0, GWEN_Buffer_GetStart(buf), - (const uint8_t*) (valueData?valueData:NULL), - valueData?strlen(valueData):0); if (msgOut) AQH_Endpoint_AddMsgOut(xo->mqttEndpoint, msgOut); else { DBG_ERROR(NULL, "Error creating message"); } -#else - DBG_ERROR(NULL, "Would MQTT PUBLISH: %s = %s", GWEN_Buffer_GetStart(buf), valueData?valueData:""); #endif GWEN_Buffer_free(buf); } +const char *_valueTranslatedForDriver(const AQHMQTT_VALUE *value, double valueData) +{ + const AQHMQTT_TRANSLATION_LIST *translationList; + + translationList=AQHMQTT_Value_GetTranslationList(value); + if (translationList) { + const AQHMQTT_TRANSLATION *t; + int valueAsInt; + + valueAsInt=(int) valueData; + t=AQHMQTT_Translation_List_GetByAqhValue(translationList, valueAsInt); + if (t) { + const char *s; + + s=AQHMQTT_Translation_GetDriverValue(t); + DBG_ERROR(NULL, "Translated value %d to %s", valueAsInt, s); + return s; + } + else { + DBG_ERROR(NULL, "No translation found for %d", valueAsInt); + } + } + else { + DBG_ERROR(NULL, "No translation list"); + } + + return NULL; +} + + + GWEN_BUFFER *_createBufferForTopic(const char *deviceId, const AQHMQTT_TOPIC *topic) { GWEN_BUFFER *buf; diff --git a/apps/aqhome-mqttlog/types/translation.t2d b/apps/aqhome-mqttlog/types/translation.t2d index ce1d4dc..edf5e6c 100644 --- a/apps/aqhome-mqttlog/types/translation.t2d +++ b/apps/aqhome-mqttlog/types/translation.t2d @@ -32,18 +32,18 @@ - + 0 0 public - own + with_getByMember 0 0 public - own + own with_getByMember diff --git a/apps/aqhome-mqttlog/xmlread.c b/apps/aqhome-mqttlog/xmlread.c index 06649b1..e55504b 100644 --- a/apps/aqhome-mqttlog/xmlread.c +++ b/apps/aqhome-mqttlog/xmlread.c @@ -62,6 +62,7 @@ static AQHMQTT_TRANSLATION *_readXmlTranslation(GWEN_XMLNODE *translationNode); AQHMQTT_DEVICE_LIST *AQH_MqttLogServer_ReadDeviceFile(AQH_OBJECT *o, const char *sFilename) { + DBG_ERROR(NULL, "Reading device file \"%s\"", sFilename); if (o) { AQH_MQTTLOG_SERVER *xo; @@ -390,13 +391,15 @@ AQHMQTT_VALUE_LIST *_readXmlValueList(GWEN_XMLNODE *parentNode) AQHMQTT_VALUE *_readXmlValue(GWEN_XMLNODE *valueNode) { + const char *sValueName; AQHMQTT_VALUE *value; GWEN_XMLNODE *translationNode; const char *s; int i; + sValueName=GWEN_XMLNode_GetProperty(valueNode, "name", NULL); value=AQHMQTT_Value_new(); - AQHMQTT_Value_SetName(value, GWEN_XMLNode_GetProperty(valueNode, "name", NULL)); + AQHMQTT_Value_SetName(value, sValueName); AQHMQTT_Value_SetValueUnits(value, GWEN_XMLNode_GetProperty(valueNode, "units", NULL)); AQHMQTT_Value_SetPath(value, GWEN_XMLNode_GetProperty(valueNode, "path", NULL)); @@ -415,12 +418,12 @@ AQHMQTT_VALUE *_readXmlValue(GWEN_XMLNODE *valueNode) translationList=_readXmlTranslationList(translationNode); if (translationList) { - DBG_INFO(NULL, "Translations read"); + DBG_ERROR(NULL, "Translations read for value \"%s\"", sValueName); AQHMQTT_Value_SetTranslationList(value, translationList); } } else { - DBG_INFO(NULL, "No element"); + DBG_ERROR(NULL, "No element in value %s", sValueName); } return value; @@ -440,7 +443,7 @@ AQHMQTT_TRANSLATION_LIST *_readXmlTranslationList(GWEN_XMLNODE *parentNode) if (translation) AQHMQTT_Translation_List_Add(translation, translationList); else { - DBG_INFO(NULL, "Error reading element"); + DBG_ERROR(NULL, "Error reading element"); AQHMQTT_Translation_List_free(translationList); return NULL; } @@ -458,16 +461,16 @@ AQHMQTT_TRANSLATION_LIST *_readXmlTranslationList(GWEN_XMLNODE *parentNode) AQHMQTT_TRANSLATION *_readXmlTranslation(GWEN_XMLNODE *translationNode) { - const char *sAqhValue; + int aqhValue; const char *sDriverValue; - sAqhValue=GWEN_XMLNode_GetProperty(translationNode, "aqhValue", NULL); + aqhValue=GWEN_XMLNode_GetIntProperty(translationNode, "aqhValue", 0); sDriverValue=GWEN_XMLNode_GetProperty(translationNode, "driverValue", NULL); - if (sAqhValue && *sAqhValue && sDriverValue && *sDriverValue) { + if (sDriverValue && *sDriverValue) { AQHMQTT_TRANSLATION *translation; translation=AQHMQTT_Translation_new(); - AQHMQTT_Translation_SetAqhValue(translation, sAqhValue); + AQHMQTT_Translation_SetAqhValue(translation, aqhValue); AQHMQTT_Translation_SetDriverValue(translation, sDriverValue); return translation; } diff --git a/apps/aqhome-mqttlog/xmlwrite.c b/apps/aqhome-mqttlog/xmlwrite.c index d6ea5ea..af56843 100644 --- a/apps/aqhome-mqttlog/xmlwrite.c +++ b/apps/aqhome-mqttlog/xmlwrite.c @@ -222,7 +222,7 @@ void _writeValueToXml(const AQHMQTT_VALUE *value, GWEN_XMLNODE *node) void _writeTranslationToXml(const AQHMQTT_TRANSLATION *t, GWEN_XMLNODE *nTranslation) { - _setXmlPropertyIfNotNull(nTranslation, "aqhValue", AQHMQTT_Translation_GetAqhValue(t)); + GWEN_XMLNode_SetIntProperty(nTranslation, "aqhValue", AQHMQTT_Translation_GetAqhValue(t)); _setXmlPropertyIfNotNull(nTranslation, "driverValue", AQHMQTT_Translation_GetDriverValue(t)); } diff --git a/apps/aqhome-nodes/r_setdata.c b/apps/aqhome-nodes/r_setdata.c index 9ad5a22..96ddd73 100644 --- a/apps/aqhome-nodes/r_setdata.c +++ b/apps/aqhome-nodes/r_setdata.c @@ -92,69 +92,61 @@ void AQH_NodeServer_HandleSetData(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA varName=AQH_Value_GetName(value); if (varName) { - char *data; + double data; + AQH_NODE_INFO *nodeInfo; data=AQH_IpcdMessageSetData_ReadData(tagList); - if (data) { - AQH_NODE_INFO *nodeInfo; + nodeInfo=_getNodeInfoFromValue(xo, value); + if (nodeInfo) { + const char *devName; - nodeInfo=_getNodeInfoFromValue(xo, value); - if (nodeInfo) { - const char *devName; + devName=AQH_NodeInfo_GetDeviceId(nodeInfo); + if (devName) { + const AQHNODE_DEVICE *devInfo; - devName=AQH_NodeInfo_GetDeviceId(nodeInfo); - if (devName) { - const AQHNODE_DEVICE *devInfo; + devInfo=AQH_NodeServer_GetDeviceDefByName(o, devName); + if (devInfo) { + const AQHNODE_VALUE *devValue; - devInfo=AQH_NodeServer_GetDeviceDefByName(o, devName); - if (devInfo) { - const AQHNODE_VALUE *devValue; + devValue=AQHNODE_Value_List_GetByName(AQHNODE_Device_GetValueList(devInfo), varName); + if (devValue) { + uint16_t dataVal=0; + uint16_t dataDenom=0; - devValue=AQHNODE_Value_List_GetByName(AQHNODE_Device_GetValueList(devInfo), varName); - if (devValue) { - uint16_t dataVal=0; - uint16_t dataDenom=0; + if (AQH_ReadDataFromDouble(AQHNODE_Value_GetDataType(devValue), data, &dataVal, &dataDenom)==0) { + AQH_MSG_REQUEST *rq; + int destAddr; - if (AQH_ReadDataFromString(AQHNODE_Value_GetDataType(devValue), data, &dataVal, &dataDenom)==0) { - AQH_MSG_REQUEST *rq; - int destAddr; + destAddr=AQH_NodeInfo_GetBusAddress(nodeInfo); + DBG_DEBUG(NULL, "Creating SETDATA request"); - destAddr=AQH_NodeInfo_GetBusAddress(nodeInfo); - DBG_DEBUG(NULL, "Creating SETDATA request"); - - rq=_mkRequest_SetData(o, xo, ep, msgId, destAddr, AQHNODE_Value_GetId(devValue), dataVal, dataDenom); - AQH_NodeServer_AddRequestToTree(o, rq); - /* done */ - } - else { - DBG_ERROR(NULL, "Bad data \"%s\"", data); - _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_BADDATA); - } + rq=_mkRequest_SetData(o, xo, ep, msgId, destAddr, AQHNODE_Value_GetId(devValue), dataVal, dataDenom); + AQH_NodeServer_AddRequestToTree(o, rq); + /* done */ } else { - DBG_ERROR(NULL, "Invalid value name \"%s\"", varName); - _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); + DBG_ERROR(NULL, "Bad data \"%.2f\"", data); + _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_BADDATA); } } else { - DBG_ERROR(NULL, "Unknown node \"%s\"", devName); + DBG_ERROR(NULL, "Invalid value name \"%s\"", varName); _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); } } else { - DBG_ERROR(NULL, "Node not yet fully identified, come back later"); - _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_TRYAGAIN); + DBG_ERROR(NULL, "Unknown node \"%s\"", devName); + _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); } } else { - DBG_ERROR(NULL, "No matching nodeinfo"); - _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); + DBG_ERROR(NULL, "Node not yet fully identified, come back later"); + _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_TRYAGAIN); } - free(data); } else { - DBG_ERROR(NULL, "No data"); - _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_NODATA); + DBG_ERROR(NULL, "No matching nodeinfo"); + _sendResponseResultToBroker(ep, msgId, AQH_MSGDATA_RESULT_ERROR_INVALID); } } else { diff --git a/apps/aqhome-react/examples/001-tvlight.xml b/apps/aqhome-react/examples/001-tvlight.xml index 707e5a3..b8e7ec6 100644 --- a/apps/aqhome-react/examples/001-tvlight.xml +++ b/apps/aqhome-react/examples/001-tvlight.xml @@ -26,15 +26,6 @@ - - - OFF - OFF - ON - - - - mqtt/109C2F/power @@ -49,7 +40,6 @@ - - + diff --git a/apps/aqhome-react/networks/delayedoff.xml b/apps/aqhome-react/networks/delayedoff.xml index ec1fe52..587b201 100644 --- a/apps/aqhome-react/networks/delayedoff.xml +++ b/apps/aqhome-react/networks/delayedoff.xml @@ -12,7 +12,7 @@ - + diff --git a/apps/aqhome-react/types/prgrule.c b/apps/aqhome-react/types/prgrule.c index 8dcca13..965994c 100644 --- a/apps/aqhome-react/types/prgrule.c +++ b/apps/aqhome-react/types/prgrule.c @@ -349,13 +349,35 @@ const char *_readDouble(const char *s, double *ptrDouble) while(*s && isspace(*s)) s++; sStart=s; - while(*s && (isdigit(*s) || *s=='.' || *s=='+' || *s=='-')) - s++; + if (*s=='#') { + uint32_t v=0; - rv=GWEN_Text_StringToDouble(sStart, ptrDouble); - if (rv<0) { - DBG_ERROR(NULL, "Error reading double: %d", rv); - return NULL; + s++; + while(*s) { + unsigned char c; + + c=tolower(*s); + if ((c>='0' && c<='9') || (c>='a' && c<='f')) { + c-='0'; + if (c>9) + c-=7; + v<<=4; + v+=c; + } + else + break; + s++; + } + *ptrDouble=(double) v; + } + else { + while(*s && (isdigit(*s) || *s=='.' || *s=='+' || *s=='-')) + s++; + rv=GWEN_Text_StringToDouble(sStart, ptrDouble); + if (rv<0) { + DBG_ERROR(NULL, "Error reading double: %d", rv); + return NULL; + } } return s; diff --git a/apps/aqhome-react/units/u_valueset.c b/apps/aqhome-react/units/u_valueset.c index 2ac6fd4..ffb5389 100644 --- a/apps/aqhome-react/units/u_valueset.c +++ b/apps/aqhome-react/units/u_valueset.c @@ -38,7 +38,6 @@ */ static void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAOBJECT *dataObject); -static AQH_MESSAGE *_mkSetDataMsgString(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); static AQH_MESSAGE *_mkSetDataMsgDouble(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject); @@ -62,7 +61,7 @@ AQHREACT_UNIT *AqHomeReact_UnitValueSet_new(AQH_OBJECT *aqh) port=AQHREACT_Port_new(); AQHREACT_Port_SetName(port, "input"); AQHREACT_Port_SetIdForUnit(port, AQHOMEREACT_UNIT_VALUESET_INSLOT_VALUE); - AQHREACT_Port_SetDataType(port, AQHREACT_DATAOBJECTTYPE_STRING); + AQHREACT_Port_SetDataType(port, AQHREACT_DATAOBJECTTYPE_DOUBLE); AQHREACT_Unit_AddInputPort(unit, port); param=AQHREACT_Param_new(); @@ -92,9 +91,6 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO case AQHREACT_DATAOBJECTTYPE_DOUBLE: msgOut=_mkSetDataMsgDouble(brokerEndpoint, sValueName, dataObject); break; - case AQHREACT_DATAOBJECTTYPE_STRING: - msgOut=_mkSetDataMsgString(brokerEndpoint, sValueName, dataObject); - break; default: DBG_ERROR(NULL, "Unhandled data type (%d)", AQHREACT_DataObject_GetDataType(dataObject)); msgOut=NULL; @@ -130,47 +126,20 @@ void _cbInputData(AQHREACT_UNIT *unit, AQHREACT_PORT *port, const AQHREACT_DATAO -AQH_MESSAGE *_mkSetDataMsgString(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) -{ - AQH_MESSAGE *msgOut; - AQH_VALUE *v; - - v=AQH_Value_new(); - AQH_Value_SetNameForSystem(v, sValueName); - - msgOut=AQH_IpcdMessageSetData_new(AQH_MSGTYPE_IPC_DATA_SETDATA, - AQH_Endpoint_GetNextMessageId(brokerEndpoint), 0, - v, AQHREACT_DataObject_GetStringData(dataObject)); - AQH_Value_free(v); - return msgOut; -} - - - AQH_MESSAGE *_mkSetDataMsgDouble(AQH_OBJECT *brokerEndpoint, const char *sValueName, const AQHREACT_DATAOBJECT *dataObject) { AQH_MESSAGE *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_IpcdMessageSetData_new(AQH_MSGTYPE_IPC_DATA_SETDATA, AQH_Endpoint_GetNextMessageId(brokerEndpoint), 0, - v, GWEN_Buffer_GetStart(buf)); - GWEN_Buffer_free(buf); + v, data); AQH_Value_free(v); return msgOut; } diff --git a/apps/aqhome-tool/data/setdata.c b/apps/aqhome-tool/data/setdata.c index 2faee5a..e2b2024 100644 --- a/apps/aqhome-tool/data/setdata.c +++ b/apps/aqhome-tool/data/setdata.c @@ -45,6 +45,7 @@ */ static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId); +static int _readValueFromString(const char *s, double *pDouble); @@ -93,18 +94,30 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId) GWEN_DB_NODE *dbArgs; const char *valueName; const char *valueUnits; - const char *valueData; + const char *valueDataAsString; + double valueData; AQH_VALUE *v; + int rv; dbArgs=AQH_ToolClient_GetDbLocalArgs(o); valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL); valueUnits=GWEN_DB_GetCharValue(dbArgs, "valueUnits", 0, NULL); - valueData=GWEN_DB_GetCharValue(dbArgs, "value", 0, NULL); + valueDataAsString=GWEN_DB_GetCharValue(dbArgs, "value", 0, NULL); + + if (valueDataAsString && *valueDataAsString) { + rv=_readValueFromString(valueDataAsString, &valueData); + if (rv<0) { + DBG_ERROR(NULL, "ERROR: Bad value"); + return NULL; + } + } + if (!(valueName && *valueName)) { DBG_ERROR(NULL, "ERROR: Missing value name"); return NULL; } + v=AQH_Value_new(); AQH_Value_SetNameForSystem(v, valueName); AQH_Value_SetValueUnits(v, valueUnits); @@ -116,3 +129,40 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId) +int _readValueFromString(const char *s, double *pDouble) +{ + int l; + + l=strlen(s); + if (l) { + if (*s=='#') { + unsigned int h; + + if (1==sscanf(s+1, "%x", &h)) { + *pDouble=(double) h; + return 0; + } + } + else if (l>1 && s[0]=='0' && ((tolower(s[1])=='x') || tolower(s[1])=='b')) { + unsigned int h; + + if (1==sscanf(s, "%u", &h)) { + *pDouble=(double) h; + return 0; + } + } + else { + double d; + + if (1==sscanf(s, "%lf", &d)) { + return d; + } + } + DBG_ERROR(NULL, "Bad value \"%s\"", s); + return GWEN_ERROR_GENERIC; + } +} + + + + diff --git a/aqhome/aqhome.c b/aqhome/aqhome.c index bee2f17..39ff339 100644 --- a/aqhome/aqhome.c +++ b/aqhome/aqhome.c @@ -43,6 +43,10 @@ static void _definePath(const char *pathName, const char *pathValue); static GWEN_STRINGLIST *_getListOfMatchingFiles(const char *pathName, const char *subFolder, const char *mask); static GWEN_BUFFER *_getRuntimeFilePath(const char *pathName, const char *sFilename); static GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename); +static int _readUint8DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); +static int _readUint16DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); +static int _readUint32DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom); + static int _readUint8DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint16DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint32DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); @@ -469,6 +473,59 @@ GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename) +int AQH_ReadDataFromDouble(int dataType, double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + switch(dataType) { + case AQH_ValueDataType_Uint8: return _readUint8DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Int: + case AQH_ValueDataType_Uint16: return _readUint16DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Uint32: return _readUint32DataFromDouble(d, pDataVal, pDataDenom); + case AQH_ValueDataType_Rational: break; + default: break; + } + + return GWEN_ERROR_INVALID; +} + + + +int _readUint8DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint8_t v; + + v=((uint8_t) (d)) & 0xff; + *pDataVal=v & 0xff; + *pDataDenom=1; + return 0; +} + + + +int _readUint16DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint16_t v; + + v=((uint16_t) d) & 0xffff; + *pDataVal=v; + *pDataDenom=1; + return 0; +} + + + +int _readUint32DataFromDouble(double d, uint16_t *pDataVal, uint16_t *pDataDenom) +{ + uint32_t v; + + v=((uint32_t) d) & 0xffffffff; + + *pDataVal=(v>>16) & 0xffff; + *pDataDenom=v & 0xffff; + return 0; +} + + + int AQH_ReadDataFromString(int dataType, const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { if (s && *s) { diff --git a/aqhome/aqhome.h b/aqhome/aqhome.h index d86f540..ff159af 100644 --- a/aqhome/aqhome.h +++ b/aqhome/aqhome.h @@ -84,6 +84,7 @@ AQHOME_API int AQH_ValueModality_fromString(const char *s); AQHOME_API const char *AQH_ValueModality_toString(int i); AQHOME_API int AQH_ReadDataFromString(int dataType, const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); +AQHOME_API int AQH_ReadDataFromDouble(int dataType, double d, uint16_t *pDataVal, uint16_t *pDataDenom); #endif diff --git a/aqhome/data/storage.c b/aqhome/data/storage.c index ad3ffd1..f42ac59 100644 --- a/aqhome/data/storage.c +++ b/aqhome/data/storage.c @@ -404,7 +404,6 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t uint64_t *arrayPtr; uint64_t i; - DBG_ERROR(NULL, "Requested %d entries", (int) maxDataPointsRequested); df=_getDataFileByValueId(sto, valueId); if (df==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "No file for value id %lu", (unsigned long int) valueId); diff --git a/aqhome/dataclient/client.c b/aqhome/dataclient/client.c index 9b6336e..c335a8b 100644 --- a/aqhome/dataclient/client.c +++ b/aqhome/dataclient/client.c @@ -343,7 +343,7 @@ uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char *valueName, -int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, const char *data) +int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, double data) { if (dc) { AQH_MESSAGE *msgOut; @@ -379,6 +379,24 @@ int AQH_DataClient_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t t +int AQH_DataClient_ModDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *d) +{ + if (dc) { + AQH_MESSAGE *msgOut; + uint32_t msgId; + + msgId=++(dc->lastMsgId); + msgOut=AQH_IpcdMessageDevices_newForOneDevice(AQH_MSGTYPE_IPC_DATA_MODDEVICE_REQ, msgId, 0, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, d); + AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut); + + return _handleResult(dc, msgId); + } + + return GWEN_ERROR_INVALID; +} + + + diff --git a/aqhome/dataclient/client.h b/aqhome/dataclient/client.h index 1a77195..99f8266 100644 --- a/aqhome/dataclient/client.h +++ b/aqhome/dataclient/client.h @@ -43,8 +43,9 @@ AQHOME_API uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char uint64_t *dataPtr, uint64_t maxNum, uint64_t tsBegin, uint64_t tsEnd); -AQHOME_API int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, const char *data); +AQHOME_API int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, double data); AQHOME_API int AQH_DataClient_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t timeStamp, double dataPoint); +AQHOME_API int AQH_DataClient_ModDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *d); AQHOME_API int AQH_DataClient_ReadLocalArgs(AQH_DATACLIENT *dc, diff --git a/aqhome/events2/fdobject.c b/aqhome/events2/fdobject.c index d66ac04..73540c0 100644 --- a/aqhome/events2/fdobject.c +++ b/aqhome/events2/fdobject.c @@ -180,7 +180,7 @@ int AQH_FdObject_Read(AQH_OBJECT *o, uint8_t *ptrBuffer, uint32_t lenBuffer) return GWEN_ERROR_TRY_AGAIN; } else { - DBG_ERROR(AQH_LOGDOMAIN, "Error on read: %s (%d)", strerror(errno), errno); + DBG_INFO(AQH_LOGDOMAIN, "Error on read(%d): %s (%d)", xo->fd, strerror(errno), errno); close(xo->fd); xo->fd=-1; return GWEN_ERROR_IO; diff --git a/aqhome/ipc2/endpoint.c b/aqhome/ipc2/endpoint.c index d4c5100..7787bd9 100644 --- a/aqhome/ipc2/endpoint.c +++ b/aqhome/ipc2/endpoint.c @@ -531,7 +531,7 @@ int _handleMsgSent(AQH_OBJECT *o) if (xo) { AQH_MESSAGE *msg; - DBG_INFO(AQH_LOGDOMAIN, "Messages in outlist: %d", AQH_Message_List_GetCount(xo->msgOutList)); + DBG_DEBUG(AQH_LOGDOMAIN, "Messages in outlist: %d", AQH_Message_List_GetCount(xo->msgOutList)); msg=AQH_Message_List_First(xo->msgOutList); if (msg) { /* remove sent message from list */ diff --git a/aqhome/ipc2/msgreader.c b/aqhome/ipc2/msgreader.c index c2600a3..9fe903c 100644 --- a/aqhome/ipc2/msgreader.c +++ b/aqhome/ipc2/msgreader.c @@ -313,6 +313,7 @@ int _fillRingbuffer(AQH_OBJECT *o, AQH_MSG_READER *xo, AQH_OBJECT *fdObject) if (rv<0) { if (rv!=GWEN_ERROR_TRY_AGAIN) { DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + AQH_Object_EmitSignal(o, AQH_MSG_READER_SIGNAL_CLOSED, 0, NULL); } return rv; } diff --git a/aqhome/msg/ipc/data/m_ipcd_setdata.c b/aqhome/msg/ipc/data/m_ipcd_setdata.c index 63b71a5..ea0f85b 100644 --- a/aqhome/msg/ipc/data/m_ipcd_setdata.c +++ b/aqhome/msg/ipc/data/m_ipcd_setdata.c @@ -37,7 +37,7 @@ AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, - const AQH_VALUE *value, const char *data) + const AQH_VALUE *value, double data) { AQH_MESSAGE *msg; GWEN_BUFFER *buf; @@ -51,8 +51,7 @@ AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, GWEN_Buffer_free(buf); return NULL; } - if (data && *data) - GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_SET_TAGS_DATA, data, buf); + GWEN_Tag16_WriteDoubleTagToBuffer(AQH_MSGDATA_SET_TAGS_DATA, data, buf); msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId, GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf)); @@ -78,9 +77,9 @@ AQH_VALUE *AQH_IpcdMessageSetData_ReadValue(const GWEN_TAG16_LIST *tagList) -char *AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList) +double AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList) { - return AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_SET_TAGS_DATA, NULL); + return AQH_Tag16_GetTagDataAsDouble(tagList, AQH_MSGDATA_SET_TAGS_DATA, 0.0); } @@ -92,16 +91,16 @@ void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 const char *valueName; const char *valueUnits; int valueType; - char *data; + double data; value=tagList?AQH_IpcdMessageSetData_ReadValue(tagList):NULL; valueName=value?AQH_Value_GetNameForSystem(value):NULL; valueUnits=value?AQH_Value_GetValueUnits(value):NULL; valueType=value?AQH_Value_GetValueType(value):0; - data=tagList?AQH_IpcdMessageSetData_ReadData(tagList):NULL; + data=tagList?AQH_IpcdMessageSetData_ReadData(tagList):0.0; GWEN_Buffer_AppendArgs(dbuf, - "SETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, value=%s)\n", + "SETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, units=%s, type=%d, value=%.2f)\n", AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)), sText?sText:"", AQH_IpcMessage_GetCode(msg), @@ -110,8 +109,7 @@ void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1 valueName?valueName:"", valueUnits?valueUnits:"", valueType, - data?data:""); - free(data); + data); AQH_Value_free(value); } diff --git a/aqhome/msg/ipc/data/m_ipcd_setdata.h b/aqhome/msg/ipc/data/m_ipcd_setdata.h index 3aee4ba..c6c28d3 100644 --- a/aqhome/msg/ipc/data/m_ipcd_setdata.h +++ b/aqhome/msg/ipc/data/m_ipcd_setdata.h @@ -27,10 +27,10 @@ AQHOME_API AQH_MESSAGE *AQH_IpcdMessageSetData_new(uint16_t code, uint32_t msgId, uint32_t refMsgId, - const AQH_VALUE *value, const char *data); + const AQH_VALUE *value, double data); AQHOME_API AQH_VALUE *AQH_IpcdMessageSetData_ReadValue(const GWEN_TAG16_LIST *tagList); -AQHOME_API char *AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList); +AQHOME_API double AQH_IpcdMessageSetData_ReadData(const GWEN_TAG16_LIST *tagList); AQHOME_API void AQH_IpcdMessageSetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, GWEN_BUFFER *dbuf, const char *sText); diff --git a/aqhome/msg/ipc/m_ipc_tag16.c b/aqhome/msg/ipc/m_ipc_tag16.c index a7a2e6d..f151e75 100644 --- a/aqhome/msg/ipc/m_ipc_tag16.c +++ b/aqhome/msg/ipc/m_ipc_tag16.c @@ -161,6 +161,19 @@ uint64_t AQH_Tag16_GetTagDataAsUint64(const GWEN_TAG16_LIST *tagList, unsigned i +double AQH_Tag16_GetTagDataAsDouble(const GWEN_TAG16_LIST *tagList, unsigned int tagType, double defaultValue) +{ + if (tagList) { + const GWEN_TAG16 *tag; + + tag=GWEN_Tag16_List_FindFirstByTagType(tagList, tagType); + return tag?GWEN_Tag16_GetTagDataAsDouble(tag, defaultValue):defaultValue; + } + return defaultValue; +} + + + int AQH_Tag16_WriteValueListAsTagsToBuffer(unsigned int tagType, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *buf) { if (valueList) { diff --git a/aqhome/msg/ipc/m_ipc_tag16.h b/aqhome/msg/ipc/m_ipc_tag16.h index 044169a..1df64b3 100644 --- a/aqhome/msg/ipc/m_ipc_tag16.h +++ b/aqhome/msg/ipc/m_ipc_tag16.h @@ -27,6 +27,7 @@ AQHOME_API GWEN_TAG16_LIST *AQH_Tag16_ParseTags(const uint8_t *payloadPtr, uint3 AQHOME_API char *AQH_Tag16_GetTagDataAsNewString(const GWEN_TAG16_LIST *tagList, unsigned int tagType, const char *defaultValue); AQHOME_API uint32_t AQH_Tag16_GetTagDataAsUint32(const GWEN_TAG16_LIST *tagList, unsigned int tagType, uint32_t defaultValue); AQHOME_API uint64_t AQH_Tag16_GetTagDataAsUint64(const GWEN_TAG16_LIST *tagList, unsigned int tagType, uint64_t defaultValue); +AQHOME_API double AQH_Tag16_GetTagDataAsDouble(const GWEN_TAG16_LIST *tagList, unsigned int tagType, double defaultValue); /* utils */ AQHOME_API int AQH_Tag16_WriteValueListAsTagsToBuffer(unsigned int tagType, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *buf); diff --git a/avr/devices/c01/0BUILD b/avr/devices/c01/0BUILD index dc1bfd9..dc4c439 100644 --- a/avr/devices/c01/0BUILD +++ b/avr/devices/c01/0BUILD @@ -7,10 +7,6 @@ main
- - aqua_c01.xml - - defs.asm README diff --git a/avr/devices/c02/0BUILD b/avr/devices/c02/0BUILD index ba8c739..dc4c439 100644 --- a/avr/devices/c02/0BUILD +++ b/avr/devices/c02/0BUILD @@ -7,10 +7,6 @@ main
- - aqua_c02.xml - - defs.asm README diff --git a/avr/devices/n14/0BUILD b/avr/devices/n14/0BUILD index 58af77b..343465e 100644 --- a/avr/devices/n14/0BUILD +++ b/avr/devices/n14/0BUILD @@ -7,11 +7,6 @@ main - - aqua_n14.xml - - - defs.asm eeprom.asm diff --git a/avr/devices/n16/0BUILD b/avr/devices/n16/0BUILD index e54b57e..be449f6 100644 --- a/avr/devices/n16/0BUILD +++ b/avr/devices/n16/0BUILD @@ -7,10 +7,6 @@ main - - aqua_n16.xml - - defs.asm README diff --git a/avr/devices/n21/0BUILD b/avr/devices/n21/0BUILD index 8416b5b..472c33c 100644 --- a/avr/devices/n21/0BUILD +++ b/avr/devices/n21/0BUILD @@ -12,10 +12,5 @@ README - - aqua_n21.xml - - -
diff --git a/avr/devices/n24/0BUILD b/avr/devices/n24/0BUILD index 4ffa268..dc4c439 100644 --- a/avr/devices/n24/0BUILD +++ b/avr/devices/n24/0BUILD @@ -7,10 +7,6 @@ main - - aqua_n24.xml - - defs.asm README diff --git a/avr/devices/n25/0BUILD b/avr/devices/n25/0BUILD index 7d93fbf..343465e 100644 --- a/avr/devices/n25/0BUILD +++ b/avr/devices/n25/0BUILD @@ -7,10 +7,6 @@ main - - aqua_n25.xml - - defs.asm eeprom.asm diff --git a/avr/devices/n26/0BUILD b/avr/devices/n26/0BUILD index 8736df4..dc4c439 100644 --- a/avr/devices/n26/0BUILD +++ b/avr/devices/n26/0BUILD @@ -7,10 +7,6 @@ main - - aqua_n26.xml - - defs.asm README diff --git a/avr/devices/n27/0BUILD b/avr/devices/n27/0BUILD index 081044b..dc4c439 100644 --- a/avr/devices/n27/0BUILD +++ b/avr/devices/n27/0BUILD @@ -7,10 +7,6 @@ main - - aqua_n27.xml - - defs.asm README diff --git a/avr/devices/n28/0BUILD b/avr/devices/n28/0BUILD index a2d9bae..472c33c 100644 --- a/avr/devices/n28/0BUILD +++ b/avr/devices/n28/0BUILD @@ -12,10 +12,5 @@ README - - aqua_n28.xml - - - diff --git a/avr/devices/r05/0BUILD b/avr/devices/r05/0BUILD index 9e83ec2..25ab0fb 100644 --- a/avr/devices/r05/0BUILD +++ b/avr/devices/r05/0BUILD @@ -13,11 +13,6 @@ README - - aqua_r05.xml - - - diff --git a/avr/devices/r06/0BUILD b/avr/devices/r06/0BUILD index ef47309..dc4c439 100644 --- a/avr/devices/r06/0BUILD +++ b/avr/devices/r06/0BUILD @@ -7,10 +7,6 @@ main - - aqua_r06.xml - - defs.asm README diff --git a/avr/devices/s03/0BUILD b/avr/devices/s03/0BUILD index 0829603..dc4c439 100644 --- a/avr/devices/s03/0BUILD +++ b/avr/devices/s03/0BUILD @@ -7,10 +7,6 @@ main - - aqua_s03.xml - - defs.asm README diff --git a/avr/devices/t03/0BUILD b/avr/devices/t03/0BUILD index ba832c8..c1b8f79 100644 --- a/avr/devices/t03/0BUILD +++ b/avr/devices/t03/0BUILD @@ -9,10 +9,6 @@ uartfd - - aqua_t03.xml - - defs.asm README diff --git a/avr/devices/t04/0BUILD b/avr/devices/t04/0BUILD index 2775440..dc4c439 100644 --- a/avr/devices/t04/0BUILD +++ b/avr/devices/t04/0BUILD @@ -7,10 +7,6 @@ main - - aqua_t04.xml - - defs.asm README diff --git a/avr/modules/network/iface.asm b/avr/modules/network/iface.asm index 4313716..d1e584f 100644 --- a/avr/modules/network/iface.asm +++ b/avr/modules/network/iface.asm @@ -241,7 +241,7 @@ NET_Interface_ResetStats: mov xl, yl mov xh, yh adiw xh:xl, NET_IFACE_OFFS_PACKETSIN_LOW - ldi r17, ((NET_IFACE_OFFS_ERR_BUSY_HIGH+1)-NET_IFACE_OFFS_PACKETSIN_LOW) + ldi r17, ((NET_IFACE_OFFS_ERR_MISSED_HIGH+1)-NET_IFACE_OFFS_PACKETSIN_LOW) clr r16 rcall Utils_FillSram ; (R17, X) out SREG, r15 diff --git a/avr/modules/sk6812/main.asm b/avr/modules/sk6812/main.asm index 15acdd6..432f771 100644 --- a/avr/modules/sk6812/main.asm +++ b/avr/modules/sk6812/main.asm @@ -148,8 +148,9 @@ SK6812_SetMode: sts sk6812Mode, r18 cpi r18, SK6812_MODE_OFF breq SK6812_SetState_off - cpi r18, SK6812_MODE_ON - breq SK6812_SetState_on +; cpi r18, SK6812_MODE_ON +; breq SK6812_SetState_on + rjmp SK6812_SetState_on ret SK6812_SetState_off: clr r18 diff --git a/devices/mqtt/tasmota_plug.xml b/devices/mqtt/tasmota_plug.xml index b6b4e49..cb53d46 100644 --- a/devices/mqtt/tasmota_plug.xml +++ b/devices/mqtt/tasmota_plug.xml @@ -27,8 +27,8 @@ - - + + diff --git a/devices/mqtt/tasmota_plug_old.xml b/devices/mqtt/tasmota_plug_old.xml index 7f7c708..f20d994 100644 --- a/devices/mqtt/tasmota_plug_old.xml +++ b/devices/mqtt/tasmota_plug_old.xml @@ -27,8 +27,8 @@ - - + + diff --git a/devices/nodes/0BUILD b/devices/nodes/0BUILD index ed2e335..bf990a7 100644 --- a/devices/nodes/0BUILD +++ b/devices/nodes/0BUILD @@ -2,15 +2,30 @@ + aqua_c01.xml + aqua_c02.xml aqua_n06.xml aqua_n11.xml aqua_n12.xml + aqua_n14.xml aqua_n15.xml + aqua_n16.xml aqua_n17.xml aqua_n18.xml aqua_n19.xml aqua_n20.xml + aqua_n21.xml aqua_n22.xml + aqua_n24.xml + aqua_n25.xml + aqua_n26.xml + aqua_n27.xml + aqua_n28.xml + aqua_r05.xml + aqua_r06.xml + aqua_s03.xml + aqua_t03.xml + aqua_t04.xml diff --git a/avr/devices/c01/aqua_c01.xml b/devices/nodes/aqua_c01.xml similarity index 100% rename from avr/devices/c01/aqua_c01.xml rename to devices/nodes/aqua_c01.xml diff --git a/avr/devices/c02/aqua_c02.xml b/devices/nodes/aqua_c02.xml similarity index 100% rename from avr/devices/c02/aqua_c02.xml rename to devices/nodes/aqua_c02.xml diff --git a/avr/devices/n14/aqua_n14.xml b/devices/nodes/aqua_n14.xml similarity index 100% rename from avr/devices/n14/aqua_n14.xml rename to devices/nodes/aqua_n14.xml diff --git a/avr/devices/n16/aqua_n16.xml b/devices/nodes/aqua_n16.xml similarity index 100% rename from avr/devices/n16/aqua_n16.xml rename to devices/nodes/aqua_n16.xml diff --git a/avr/devices/n21/aqua_n21.xml b/devices/nodes/aqua_n21.xml similarity index 100% rename from avr/devices/n21/aqua_n21.xml rename to devices/nodes/aqua_n21.xml diff --git a/avr/devices/n24/aqua_n24.xml b/devices/nodes/aqua_n24.xml similarity index 100% rename from avr/devices/n24/aqua_n24.xml rename to devices/nodes/aqua_n24.xml diff --git a/avr/devices/n25/aqua_n25.xml b/devices/nodes/aqua_n25.xml similarity index 100% rename from avr/devices/n25/aqua_n25.xml rename to devices/nodes/aqua_n25.xml diff --git a/avr/devices/n26/aqua_n26.xml b/devices/nodes/aqua_n26.xml similarity index 100% rename from avr/devices/n26/aqua_n26.xml rename to devices/nodes/aqua_n26.xml diff --git a/avr/devices/n27/aqua_n27.xml b/devices/nodes/aqua_n27.xml similarity index 100% rename from avr/devices/n27/aqua_n27.xml rename to devices/nodes/aqua_n27.xml diff --git a/avr/devices/n28/aqua_n28.xml b/devices/nodes/aqua_n28.xml similarity index 100% rename from avr/devices/n28/aqua_n28.xml rename to devices/nodes/aqua_n28.xml diff --git a/avr/devices/r05/aqua_r05.xml b/devices/nodes/aqua_r05.xml similarity index 100% rename from avr/devices/r05/aqua_r05.xml rename to devices/nodes/aqua_r05.xml diff --git a/avr/devices/r06/aqua_r06.xml b/devices/nodes/aqua_r06.xml similarity index 100% rename from avr/devices/r06/aqua_r06.xml rename to devices/nodes/aqua_r06.xml diff --git a/avr/devices/s03/aqua_s03.xml b/devices/nodes/aqua_s03.xml similarity index 100% rename from avr/devices/s03/aqua_s03.xml rename to devices/nodes/aqua_s03.xml diff --git a/avr/devices/t03/aqua_t03.xml b/devices/nodes/aqua_t03.xml similarity index 100% rename from avr/devices/t03/aqua_t03.xml rename to devices/nodes/aqua_t03.xml diff --git a/avr/devices/t04/aqua_t04.xml b/devices/nodes/aqua_t04.xml similarity index 100% rename from avr/devices/t04/aqua_t04.xml rename to devices/nodes/aqua_t04.xml diff --git a/etc/0BUILD b/etc/0BUILD index a7b57d1..166efa8 100644 --- a/etc/0BUILD +++ b/etc/0BUILD @@ -7,6 +7,8 @@ aqhome-mqttlog.service aqhome-nodes.service aqhome-react.service + + aqhome-apache2.conf diff --git a/etc/aqhome-apache2.conf b/etc/aqhome-apache2.conf new file mode 100644 index 0000000..3727ecc --- /dev/null +++ b/etc/aqhome-apache2.conf @@ -0,0 +1,48 @@ + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + ServerName aqhome.withinet.lan + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/aqhome-cgi/html + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + LogLevel debug + + ErrorLog ${APACHE_LOG_DIR}/aqhome-error.log + CustomLog ${APACHE_LOG_DIR}/aqhome-access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + + Header set Cache-Control "no-cache, no-store, must-revalidate" + Header set Pragma "no-cache" + Header set Expires 0 + + + ScriptAlias "/aqhome" "/usr/local/lib/cgi-bin/aqhome-cgi" + + SetEnv AQHOME_STATIC_FILES /var/www/aqhome-cgi/static + SetEnv AQHOME_RUNTIME_FILES /var/www/aqhome-cgi + SetEnv AQHOME_BASE_URL http://aqhome.withinet.lan/aqhome + AllowOverride None + Options +ExecCGI + SetHandler cgi-script + Require all granted + + + diff --git a/etc/aqhome-data.service b/etc/aqhome-data.service index 2be5421..4c6a908 100644 --- a/etc/aqhome-data.service +++ b/etc/aqhome-data.service @@ -11,6 +11,7 @@ RemainAfterExit=no ExecStart=/usr/local/sbin/aqhome-data --datafolder=/var/lib/aqhome-data -p /var/run/aqhome-data.pid Restart=on-failure RestartSec=5s +LimitNOFILE=16384 [Install] WantedBy=multi-user.target