Compare commits
224 Commits
mp-2025_06
...
mp-2025_10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31e677a4ae | ||
|
|
4fb9e2ecdf | ||
|
|
bb9f86211d | ||
|
|
2f694f983a | ||
|
|
f858b5b3de | ||
|
|
32bf7c0da4 | ||
|
|
aaf460ec6f | ||
|
|
ffc86b3e61 | ||
|
|
89228ed03b | ||
|
|
ced89d9845 | ||
|
|
617c8551dc | ||
|
|
c32be5cd38 | ||
|
|
7c320b210f | ||
|
|
0fa4c6c8b5 | ||
|
|
9caf468b86 | ||
|
|
55ac83820e | ||
|
|
cfa071c6de | ||
|
|
39dba4ccb8 | ||
|
|
9fec57511a | ||
|
|
01aca2d3b7 | ||
|
|
5a16117240 | ||
|
|
d0c8b3b284 | ||
|
|
1aeeed9845 | ||
|
|
624b1648b5 | ||
|
|
1d6bb38d89 | ||
|
|
28cf031b46 | ||
|
|
c9cfcc5dc4 | ||
|
|
dd577be872 | ||
|
|
2a1af6f947 | ||
|
|
15728e27ca | ||
|
|
0095b38c9f | ||
|
|
9a379f12b2 | ||
|
|
023cabbc1b | ||
|
|
a35211e427 | ||
|
|
8629e52749 | ||
|
|
81e9078b80 | ||
|
|
dafe32792a | ||
|
|
3f9e16f038 | ||
|
|
5bd1e06850 | ||
|
|
5040ccc065 | ||
|
|
494e7b3fbc | ||
|
|
8d22d386b4 | ||
|
|
0f712717d8 | ||
|
|
f201ac4bd6 | ||
|
|
408b173ae1 | ||
|
|
12a64b8c91 | ||
|
|
6920117ba1 | ||
|
|
8d188976eb | ||
|
|
9770cd8d6d | ||
|
|
68829f6428 | ||
|
|
cc00f8e64a | ||
|
|
d08d30d297 | ||
|
|
90f0590d18 | ||
|
|
732eb4f53d | ||
|
|
666e7690a6 | ||
|
|
42e477098c | ||
|
|
162d6d9f4e | ||
|
|
13ee628b8d | ||
|
|
124815079a | ||
|
|
c1afb05250 | ||
|
|
5c24750acc | ||
|
|
4d6edf3fb6 | ||
|
|
b13bace79f | ||
|
|
60a3f1f324 | ||
|
|
860310de7f | ||
|
|
65c89fab07 | ||
|
|
8da865928a | ||
|
|
6b39e0bfb1 | ||
|
|
124e471364 | ||
|
|
8178901ffb | ||
|
|
3fd460637a | ||
|
|
5cd308d10c | ||
|
|
a0e18c80dc | ||
|
|
b0ce010dc8 | ||
|
|
8805712aea | ||
|
|
a1d6f80c36 | ||
|
|
3e00ac4dfb | ||
|
|
fb365c7e1d | ||
|
|
d7145198a1 | ||
|
|
9f6adf7a98 | ||
|
|
348c3a8853 | ||
|
|
7f301d271b | ||
|
|
8f2bd23dc5 | ||
|
|
8db57a7875 | ||
|
|
785f479921 | ||
|
|
61f69f45b0 | ||
|
|
90f6ce73e4 | ||
|
|
3bda196b79 | ||
|
|
757f4fca4f | ||
|
|
54b4693b2e | ||
|
|
1c8e9134bf | ||
|
|
1915133093 | ||
|
|
53e076c2ad | ||
|
|
3ea7170473 | ||
|
|
0dc9f0330c | ||
|
|
17a7dddd02 | ||
|
|
a81acf7b19 | ||
|
|
d7e4ee4cca | ||
|
|
5866a55067 | ||
|
|
40282486f6 | ||
|
|
2b2c41867f | ||
|
|
679865f68b | ||
|
|
5b459ef5ac | ||
|
|
9685e45861 | ||
|
|
fbda9cf228 | ||
|
|
552cd5b2ae | ||
|
|
3926b01b13 | ||
|
|
ffaa27ca24 | ||
|
|
9a1c5799aa | ||
|
|
85e66c352d | ||
|
|
d1b67a4819 | ||
|
|
51d55128a9 | ||
|
|
52a5078706 | ||
|
|
2d15091b0c | ||
|
|
81598881d1 | ||
|
|
4a74a9990f | ||
|
|
6c1e8a45ff | ||
|
|
808a7c4258 | ||
|
|
80ca6e0ac5 | ||
|
|
0989543b1b | ||
|
|
36195f88e0 | ||
|
|
3b916facf4 | ||
|
|
9d59bf31e6 | ||
|
|
a256c6261c | ||
|
|
21830321f7 | ||
|
|
eb27d223fb | ||
|
|
33cae3ab26 | ||
|
|
1612065d8a | ||
|
|
eac37b9927 | ||
|
|
b95a4fa872 | ||
|
|
81669a5442 | ||
|
|
3270a71cb0 | ||
|
|
5ae7f821e4 | ||
|
|
224aca5c41 | ||
|
|
9600be78a5 | ||
|
|
246d00a220 | ||
|
|
809439fd26 | ||
|
|
86741a0e50 | ||
|
|
41843cbab9 | ||
|
|
64854506e5 | ||
|
|
463385a296 | ||
|
|
b97fc98bc1 | ||
|
|
9b86aea7ed | ||
|
|
5bfb49d9e1 | ||
|
|
32a0ad5eae | ||
|
|
65593f95ad | ||
|
|
ec3774c7a5 | ||
|
|
4bd462ea59 | ||
|
|
77d3a201f5 | ||
|
|
127525e3ec | ||
|
|
465e750e3c | ||
|
|
6e062d3f60 | ||
|
|
7efaf720cc | ||
|
|
66ac029a69 | ||
|
|
bae188ddee | ||
|
|
87788fa93c | ||
|
|
5013bb8e29 | ||
|
|
08d420a871 | ||
|
|
3a7951be16 | ||
|
|
6a3f6be8a9 | ||
|
|
6c3926c1e4 | ||
|
|
8467408fd8 | ||
|
|
6bb499740d | ||
|
|
fc073696f8 | ||
|
|
102996f69f | ||
|
|
f9d721ac02 | ||
|
|
6bf8f03fbb | ||
|
|
fa404a5fcf | ||
|
|
3592a745d3 | ||
|
|
7c01aa255f | ||
|
|
d9e7d4df81 | ||
|
|
9b1badb310 | ||
|
|
0dc4a3a952 | ||
|
|
32bd3bc2f9 | ||
|
|
3f2ae9dd03 | ||
|
|
7fbc616ce4 | ||
|
|
8c13f9fdf7 | ||
|
|
6c5dc21f6a | ||
|
|
eb1392f3fd | ||
|
|
2b25fed2cd | ||
|
|
66b298d977 | ||
|
|
1091ec1dee | ||
|
|
d0b5f84316 | ||
|
|
ae1e4c3e37 | ||
|
|
78cbbf334e | ||
|
|
c8c12bb892 | ||
|
|
ae1853ba62 | ||
|
|
e8423ae97f | ||
|
|
597504fb08 | ||
|
|
59a0962420 | ||
|
|
323a5b76be | ||
|
|
b7234a6da2 | ||
|
|
4a5ba97b85 | ||
|
|
bdd710fc5c | ||
|
|
535a695c50 | ||
|
|
357ffe4e17 | ||
|
|
349b4a929a | ||
|
|
a06d245345 | ||
|
|
83225c453d | ||
|
|
fa94190345 | ||
|
|
68aa3beab8 | ||
|
|
3cd23d5f60 | ||
|
|
003f53b0b7 | ||
|
|
c1ea4212f2 | ||
|
|
3283a38981 | ||
|
|
3054274da5 | ||
|
|
2d84198e54 | ||
|
|
f3544f5e93 | ||
|
|
04c02b5e33 | ||
|
|
b709b7e624 | ||
|
|
8c397dd6b2 | ||
|
|
6e923ce075 | ||
|
|
245d44c05d | ||
|
|
4f497fc41a | ||
|
|
e32e8e7c13 | ||
|
|
f3020562bf | ||
|
|
fbb710a4e3 | ||
|
|
cbd498150f | ||
|
|
691ee3c71b | ||
|
|
280d5828bf | ||
|
|
6ecc1721b0 | ||
|
|
1824e8ccdf | ||
|
|
0a45e38939 | ||
|
|
81b008af0c |
3
0BUILD
3
0BUILD
@@ -2,7 +2,7 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<project name="aqhome" version="0.0.11" so_current="0" so_age="0" so_revision="11" write_config_h="TRUE">
|
||||
<project name="aqhome" version="0.0.19" so_current="0" so_age="0" so_revision="19" write_config_h="TRUE">
|
||||
<setVar name="package">$(project_name)</setVar>
|
||||
<setVar name="version">
|
||||
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
|
||||
@@ -153,6 +153,7 @@
|
||||
<variables>plugindir gwengui-fox16</variables>
|
||||
</dep>
|
||||
<dep id="aqcgi" name="aqcgi" minversion="0.0.1" required="TRUE" />
|
||||
<dep id="aqdiagram" name="aqdiagram" minversion="0.0.1" required="TRUE" />
|
||||
<!-- <dep id="aqdatabase" name="aqdatabase" minversion="1.99.1" required="TRUE" >
|
||||
<variables>aqdatabase_typemakerdir</variables>
|
||||
</dep>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqcgi_cflags)
|
||||
$(aqdiagram_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
@@ -21,6 +22,8 @@
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
<define name="AQHOME_CGI_WWWDIR" value="$(httpdatadir)/aqhome-cgi" quoted="TRUE" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
<setVar name="tm2flags" >
|
||||
@@ -47,15 +50,16 @@
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
aqhome
|
||||
aqhomecgi
|
||||
aqhcgi_service
|
||||
aqhome
|
||||
</useTargets>
|
||||
|
||||
<libraries>
|
||||
$(gwenhywfar_libs)
|
||||
-lm
|
||||
$(aqcgi_libs)
|
||||
$(aqdiagram_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
@@ -125,6 +129,7 @@
|
||||
$(gwenhywfar_libs)
|
||||
-lm
|
||||
$(aqcgi_libs)
|
||||
$(aqdiagram_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
#include "./service_file.h"
|
||||
#include "aqhome-cgi/modules/mroot.h"
|
||||
#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/devices/mdevices.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
|
||||
#include <aqcgi/cgi.h>
|
||||
#include <aqcgi/request.h>
|
||||
#include <aqdiagram/aqdiagram.h>
|
||||
|
||||
#include <gwenhywfar/gwenhywfar.h>
|
||||
#include <gwenhywfar/nogui.h>
|
||||
@@ -20,22 +25,48 @@
|
||||
|
||||
#define AQHOME_CGI_LOGFILE "/var/www/aqhome-cgi/log/aqhome-cgi.log"
|
||||
|
||||
#define AQHOME_CGI_DEFAULT_STATIC_FILES "0-build/services/static"
|
||||
#define AQHOME_CGI_DEFAULT_RUNTIME_FILES "0-build/services/runtime"
|
||||
#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"
|
||||
|
||||
|
||||
|
||||
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles);
|
||||
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles);
|
||||
AQH_MODULE *_loadModule(AQH_SERVICE *sv, AQCGI_REQUEST *rq, AQH_MODULE *mParent, const char *sModuleName);
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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, const char *sBaseUrl);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GWEN_GUI *gui;
|
||||
AQCGI_REQUEST *rq;
|
||||
const char *sPathStaticFiles;
|
||||
const char *sPathRuntimeFiles;
|
||||
const char *sBaseUrl;
|
||||
|
||||
sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
|
||||
if (!(sPathStaticFiles && *sPathStaticFiles))
|
||||
sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;
|
||||
|
||||
sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
|
||||
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();
|
||||
@@ -45,59 +76,64 @@ 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);
|
||||
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
|
||||
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
|
||||
|
||||
DBG_ERROR(NULL, "Init CGI");
|
||||
AQCGI_Init();
|
||||
|
||||
GWEN_Logger_Close(GWEN_LOGDOMAIN);
|
||||
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
|
||||
|
||||
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);
|
||||
|
||||
rq=AQCGI_ReadRequest();
|
||||
if (rq) {
|
||||
const char *sPathStaticFiles;
|
||||
const char *sPathRuntimeFiles;
|
||||
if (argc>1 && argv[1]) {
|
||||
if (0==strcasecmp(argv[1], "init")) {
|
||||
int rv;
|
||||
|
||||
sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
|
||||
if (!(sPathStaticFiles && *sPathStaticFiles))
|
||||
sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;
|
||||
rv=_init(sPathRuntimeFiles, sBaseUrl);
|
||||
if (rv<0) {
|
||||
fprintf(stderr, "Error on init (%d)\n", rv);
|
||||
return 2;
|
||||
}
|
||||
|
||||
sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
|
||||
if (!(sPathRuntimeFiles && *sPathRuntimeFiles))
|
||||
sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES;
|
||||
|
||||
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "Content-type: text/plain\n\n");
|
||||
fprintf(stdout, "Error: No Request!\n");
|
||||
return 0;
|
||||
}
|
||||
AQCGI_REQUEST *rq;
|
||||
|
||||
AQCGI_Fini();
|
||||
DBG_ERROR(NULL, "Init CGI");
|
||||
AQCGI_Init();
|
||||
rq=AQCGI_ReadRequest();
|
||||
if (rq) {
|
||||
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles, sBaseUrl);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "Content-type: text/plain\n\n");
|
||||
fprintf(stdout, "Error: No Request!\n");
|
||||
}
|
||||
AQCGI_Fini();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
}
|
||||
AQH_Service_free(sv);
|
||||
}
|
||||
@@ -108,10 +144,13 @@ int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles
|
||||
{
|
||||
AQH_MODULE *mRoot;
|
||||
AQH_MODULE *mParent;
|
||||
AQH_SESSION *session;
|
||||
const GWEN_STRINGLIST *sl;
|
||||
|
||||
mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
|
||||
mParent=mRoot;
|
||||
session=AQH_ModService_ReadSession(mRoot, rq);
|
||||
AQH_ModService_CalcSessionModPerms(mRoot, session);
|
||||
|
||||
sl=AQCGI_Request_GetStringlistPath(rq);
|
||||
if (sl) {
|
||||
@@ -129,10 +168,10 @@ int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles
|
||||
AQH_MODULE *m;
|
||||
|
||||
DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
|
||||
m=AQH_ModService_LoadSubModule(mParent, rq, s);
|
||||
if (m==NULL) {
|
||||
m=AQH_ModService_LoadSubModule(mParent, rq, session, s);
|
||||
if (m==NULL) {
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
AQCGI_SendResponseWithStatus(rq, 404, "Not found");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
mParent=m;
|
||||
@@ -141,9 +180,11 @@ int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles
|
||||
int rv;
|
||||
|
||||
/* last, let module handle remaining part */
|
||||
rv=AQH_ModService_HandleRequest(mParent, rq, s);
|
||||
DBG_ERROR(NULL, "Entry: %s (last)", s);
|
||||
rv=AQH_ModService_HandleRequest(mParent, rq, session, s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return rv;
|
||||
}
|
||||
@@ -153,10 +194,12 @@ int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles
|
||||
|
||||
se=seNext;
|
||||
}
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
AQH_Session_free(session);
|
||||
AQH_Module_free(mRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
@@ -177,5 +220,45 @@ void logStart()
|
||||
|
||||
|
||||
|
||||
int _init(const char *sPathRuntimeFiles, const char *sBaseUrl)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
int rv;
|
||||
|
||||
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\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModAdmModules_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"modules\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModAdmUsers_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"users\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_ModDevices_Create(sv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error creating module \"devices\"");
|
||||
AQH_Service_free(sv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
AQH_Service_free(sv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="BUILDING_AQHOME" />
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
@@ -49,13 +49,12 @@
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
mservice.h
|
||||
mdataclient.h
|
||||
mroot.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
mservice_p.h
|
||||
mroot_p.h
|
||||
</headers>
|
||||
|
||||
@@ -63,7 +62,7 @@
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mservice.c
|
||||
mdataclient.c
|
||||
mroot.c
|
||||
</sources>
|
||||
|
||||
@@ -73,9 +72,13 @@
|
||||
|
||||
|
||||
<useTargets>
|
||||
aqhcgi_modcom
|
||||
aqhcgi_mdevices
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
common
|
||||
devices
|
||||
static
|
||||
</subdirs>
|
||||
|
||||
|
||||
86
apps/aqhome-cgi/modules/common/0BUILD
Normal file
86
apps/aqhome-cgi/modules/common/0BUILD
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_modcom" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
mservice.h
|
||||
madmin.h
|
||||
mmodules.h
|
||||
musers.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
mservice_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mservice.c
|
||||
madmin.c
|
||||
mmodules.c
|
||||
musers.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
217
apps/aqhome-cgi/modules/common/madmin.c
Normal file
217
apps/aqhome-cgi/modules/common/madmin.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./madmin.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/common/mmodules.h"
|
||||
#include "aqhome-cgi/modules/common/musers.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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 int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmin_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_ModAdmin_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "admin");
|
||||
AQH_Module_SetDescr(m, "administration 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, "AdminUsers", 0x001, "User Administration");
|
||||
AQH_ModService_AddPermDef(permDefList, "AdminModules", 0x002, "Module Administration");
|
||||
|
||||
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++, "userAdmin", AQH_MODADM_PERMS_ADMINUSERS, "User administrator");
|
||||
AQH_ModService_AddRole(roleList, id++, "moduleAdmin", AQH_MODADM_PERMS_ADMINMODULES, "Module administrator");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
if (strcasecmp(sModuleName, "modules")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/modules", s?s:".");
|
||||
|
||||
AQH_ModAdmModules_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sModuleName, "users")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/modules", s?s:".");
|
||||
|
||||
AQH_ModAdmUsers_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
GWEN_BUFFER *dbuf;
|
||||
int rv=0;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
if (strcasecmp(sLastPathElem, "index.html")==0) {
|
||||
if (AQH_ModService_GetUserPerms(m) & (AQH_MODADM_PERMS_ADMINUSERS | AQH_MODADM_PERMS_ADMINMODULES))
|
||||
rv=_handleRqIndex(m, rq, dbuf);
|
||||
else {
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
}
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
}
|
||||
AQH_ModService_AddFooter(m, "en", dbuf);
|
||||
AQCGI_Request_SetBufferResponseBody(rq, dbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET) {
|
||||
uint32_t userPerms;
|
||||
|
||||
GWEN_Buffer_AppendString(dbuf, "<table>");
|
||||
userPerms=AQH_ModService_GetUserPerms(m);
|
||||
if (userPerms & AQH_MODADM_PERMS_ADMINUSERS)
|
||||
GWEN_Buffer_AppendString(dbuf,
|
||||
"<tr>"
|
||||
"<td><a href=\"users/index.html\" >User administration</a></td>"
|
||||
"<td>Add, remove or modify users</td>"
|
||||
"</tr>\n");
|
||||
if (userPerms & AQH_MODADM_PERMS_ADMINMODULES)
|
||||
GWEN_Buffer_AppendString(dbuf,
|
||||
"<tr>"
|
||||
"<td><a href=\"modules/index.html\" >Module administration</a></td>"
|
||||
"<td>Add, remove or modify modules</td>"
|
||||
"</tr>\n");
|
||||
GWEN_Buffer_AppendString(dbuf, "</table>\n");
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
return 0;
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
31
apps/aqhome-cgi/modules/common/madmin.h
Normal file
31
apps/aqhome-cgi/modules/common/madmin.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/****************************************************************************
|
||||
* 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_MADMIN_H
|
||||
#define AQHOME_CGI_MADMIN_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#define AQH_MODADM_PERMS_ADMINUSERS 0x001
|
||||
#define AQH_MODADM_PERMS_ADMINMODULES 0x002
|
||||
|
||||
|
||||
void AQH_ModAdmin_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmin_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
745
apps/aqhome-cgi/modules/common/mmodules.c
Normal file
745
apps/aqhome-cgi/modules/common/mmodules.c
Normal file
@@ -0,0 +1,745 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mmodules.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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 _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqAddRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _handleRqEditRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static int _getHighestUsedRoleId(const AQH_ROLE_LIST *roleList);
|
||||
|
||||
static void _handleRqDeleteRole(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _writeEditModForm(const AQH_MODULE *currentMod, const char *sModName, GWEN_BUFFER *dbuf);
|
||||
static void _writeRoleListToForm(const AQH_ROLE_LIST *roleList,
|
||||
const char *sModName,
|
||||
const AQH_PERMDEF_LIST *permDefList,
|
||||
GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName);
|
||||
static void _writeEnabledPermissions(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
|
||||
{"index.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESREAD, _handleRqIndex},
|
||||
{"editmodule.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditModGet},
|
||||
{"editmodule.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditModPost},
|
||||
{"addrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqAddRoleGet},
|
||||
{"addrole.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqAddRolePost},
|
||||
{"editrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditRoleGet},
|
||||
{"editrole.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqEditRolePost},
|
||||
{"delrole.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMMODULES_PERMS_MODULESWRITE, _handleRqDeleteRole},
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmModules_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_ModAdmModules_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "modules");
|
||||
AQH_Module_SetDescr(m, "modules administration 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, "ModuleRead", 0x001, "Read modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleWrite", 0x002, "Modify modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleAdd", 0x004, "Add modules");
|
||||
AQH_ModService_AddPermDef(permDefList, "ModuleDel", 0x008, "Remove modules");
|
||||
|
||||
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++, "admin",
|
||||
AQH_MODADMMODULES_PERMS_MODULESREAD |
|
||||
AQH_MODADMMODULES_PERMS_MODULESWRITE |
|
||||
AQH_MODADMMODULES_PERMS_MODULESADD |
|
||||
AQH_MODADMMODULES_PERMS_MODULESDEL,
|
||||
"Administrator Role");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
/* no sub-modules */
|
||||
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 _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slModules;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slModules=AQH_Service_ListModules(sv);
|
||||
if (slModules) {
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
GBAS(dbuf, "<h1>Modules</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Id</th><th>Name</th><th>Description</th><th>Actions</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
se=GWEN_StringList_FirstEntry(slModules);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
currentMod=AQH_Service_LoadModule(sv, sModName);
|
||||
if (currentMod) {
|
||||
const char *s;
|
||||
const char *sName;
|
||||
|
||||
sName=AQH_Module_GetName(currentMod);
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td>%lu</td>", (unsigned long int) AQH_Module_GetId(currentMod));
|
||||
GBAA(dbuf, "<td>%s</td>", sName?sName:"");
|
||||
s=AQH_Module_GetDescr(currentMod);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
if (perms & AQH_MODADMMODULES_PERMS_MODULESWRITE)
|
||||
GBAA(dbuf, "<a href=\"editmodule.html?name=%s\"><img src=\"/pics/edit.png\"></a>", sName?sName:"");
|
||||
GBAA(dbuf, "</td>\n");
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
GWEN_StringList_free(slModules);
|
||||
}
|
||||
if (perms & AQH_MODADMMODULES_PERMS_MODULESADD)
|
||||
GBAS(dbuf, "<hr><a href=\"addmodule.html\">Add Module</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "name", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
_writeEditModForm(currentMod, sModName, dbuf);
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "module", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
const char *sNewModName;
|
||||
const char *sDescr;
|
||||
int rv;
|
||||
uint32_t perms;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
|
||||
permDefList=AQH_Module_GetPermDefList(currentMod);
|
||||
sNewModName=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
sDescr=GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL);
|
||||
perms=AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL);
|
||||
if (sNewModName && *sNewModName)
|
||||
AQH_Module_SetName(currentMod, sNewModName);
|
||||
AQH_Module_SetDescr(currentMod, sDescr);
|
||||
AQH_Module_SetGuestPerms(currentMod, perms);
|
||||
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving module</p>");
|
||||
DBG_ERROR(NULL, "Could not save module \"%s\"", sModName);
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "Module \"%s\" saved", sModName);
|
||||
AQH_Module_free(currentMod);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Could not load module \"%s\"", sModName?sModName:"<no name>");
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
uint32_t guestPerms;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
guestPerms=currentMod?AQH_Module_GetGuestPerms(currentMod):0;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
|
||||
if (currentMod) {
|
||||
if (permDefList) {
|
||||
GBAA(dbuf, "<h2>Add Role for Module %s</h2>\n", sModName?sModName:"");
|
||||
GBAS(dbuf,
|
||||
"<form action=\"addrole.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\"></td>"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\"></td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "<tr><td><label>Permissions:</label></td><td>");
|
||||
AQH_ModService_WritePermsToForm(guestPerms, permDefList, NULL, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"mod\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Add\">\n");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Please add permission definitions first.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
int newId;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
AQH_ROLE_LIST *roleList;
|
||||
int rv;
|
||||
|
||||
/* sample data */
|
||||
DBG_ERROR(NULL, "Handling POST request");
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
/* read role values */
|
||||
newId=(roleList?_getHighestUsedRoleId(roleList):0)+1;
|
||||
sName=dbPost?GWEN_DB_GetCharValue(dbPost, "name", 0, NULL):NULL;
|
||||
sDescr=dbPost?GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL):NULL;
|
||||
perms=(dbPost && permDefList)?AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL):0;
|
||||
|
||||
/* validate */
|
||||
if (!(sName && *sName)) {
|
||||
DBG_ERROR(NULL, "Missing value for \"name\"");
|
||||
GBAS(dbuf, "<p>Missing name.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMod) {
|
||||
AQH_ROLE *role;
|
||||
|
||||
/* set new values */
|
||||
role=AQH_Role_new();
|
||||
AQH_Role_SetId(role, newId);
|
||||
AQH_Role_SetName(role, sName);
|
||||
AQH_Role_SetDescr(role, sDescr);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
/* add role */
|
||||
if (roleList==NULL) {
|
||||
roleList=AQH_Role_List_new();
|
||||
AQH_Module_SetRoleList(currentMod, roleList);
|
||||
}
|
||||
AQH_Role_List_Add(role, roleList);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditRoleGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
int id;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
const AQH_ROLE *role;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
id=dbQuery?GWEN_DB_GetIntValue(dbQuery, "id", 0, 0):0;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, id):NULL;
|
||||
sName=role?AQH_Role_GetName(role):NULL;
|
||||
sDescr=role?AQH_Role_GetDescr(role):NULL;
|
||||
perms=role?AQH_Role_GetPerms(role):0;
|
||||
|
||||
if (role) {
|
||||
GBAA(dbuf, "<h2>Edit Role for Module %s</h2>\n", sModName?sModName:"");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"editrole.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\" value=\"%s\"></td></tr>\n"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\" value=\"%s\"></td></tr>\n",
|
||||
sName, sDescr?sDescr:"");
|
||||
|
||||
GBAS(dbuf, "<tr><td><label>Permissions:</label></td><td>");
|
||||
AQH_ModService_WritePermsToForm(perms, permDefList, NULL, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"mod\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"oldId\" value=\"%d\">\n", id);
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Save\">\n");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditRolePost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sModName;
|
||||
AQH_MODULE *currentMod;
|
||||
int oldId;
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
uint32_t perms;
|
||||
AQH_PERMDEF_LIST *permDefList;
|
||||
AQH_ROLE_LIST *roleList;
|
||||
AQH_ROLE *role;
|
||||
int rv;
|
||||
|
||||
/* sample data */
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "mod", 0, NULL):NULL;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL;
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
/* read role data */
|
||||
oldId=dbPost?GWEN_DB_GetIntValue(dbPost, "oldId", 0, -1):-1;
|
||||
sName=dbPost?GWEN_DB_GetCharValue(dbPost, "name", 0, NULL):NULL;
|
||||
sDescr=dbPost?GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, oldId):NULL;
|
||||
perms=(dbPost && permDefList)?AQH_ModService_ReadPermsFromForm(dbPost, permDefList, NULL):0;
|
||||
/* validate */
|
||||
if (!(sName && *sName)) {
|
||||
DBG_ERROR(NULL, "Missing value for \"name\"");
|
||||
GBAS(dbuf, "<p>Missing name.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
if (role==NULL) {
|
||||
DBG_ERROR(NULL, "Role %d not found", oldId);
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMod) {
|
||||
/* set new values */
|
||||
AQH_Role_SetName(role, sName);
|
||||
AQH_Role_SetDescr(role, sDescr);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqDeleteRole(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sModName;
|
||||
int id;
|
||||
AQH_MODULE *currentMod;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
AQH_ROLE *role;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL;
|
||||
id=dbQuery?GWEN_DB_GetIntValue(dbQuery, "id", 0, 0):0;
|
||||
currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL;
|
||||
if (currentMod) {
|
||||
roleList=currentMod?AQH_Module_GetRoleList(currentMod):NULL;
|
||||
role=roleList?AQH_Role_List_GetById(roleList, id):NULL;
|
||||
if (role) {
|
||||
int rv;
|
||||
|
||||
AQH_Role_List_Del(role);
|
||||
AQH_Role_free(role);
|
||||
|
||||
/* save module */
|
||||
rv=AQH_Service_SaveModule(sv, currentMod);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<p>Error saving module.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
AQH_Module_free(currentMod);
|
||||
return;
|
||||
}
|
||||
|
||||
_setLocationHeaderForMod(rq, "editmodule.html", sModName);
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See Other");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Role not found.</p>\n");
|
||||
GBAA(dbuf, "<p><a href=\"editmodule.html?name=\"%s\"> back to module</p>\n", sModName?sModName:"");
|
||||
}
|
||||
AQH_Module_free(currentMod);
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf, "<p>Error loading module.</p>\n");
|
||||
GBAS(dbuf, "<p><a href=\"index.html\"> back to module list</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName)
|
||||
{
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GBAA(tbuf, "Location: %s?name=%s", page?page:"", sModName?sModName:"");
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getHighestUsedRoleId(const AQH_ROLE_LIST *roleList)
|
||||
{
|
||||
int id=0;
|
||||
|
||||
if (roleList) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
int rid;
|
||||
|
||||
rid=AQH_Role_GetId(role);
|
||||
id=(rid>id)?rid:id;
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeEditModForm(const AQH_MODULE *currentMod, const char *sModName, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sName;
|
||||
const char *sDescr;
|
||||
const AQH_PERMDEF_LIST *permDefList;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
permDefList=AQH_Module_GetPermDefList(currentMod);
|
||||
roleList=AQH_Module_GetRoleList(currentMod);
|
||||
sName=AQH_Module_GetName(currentMod);
|
||||
sDescr=AQH_Module_GetDescr(currentMod);
|
||||
/* write module info */
|
||||
GBAS(dbuf, "<h2>Module Info</h2>\n");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"editmodule.html\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n"
|
||||
"<tr><td><label for=\"name\">Name:</label></td><td><input type=\"text\" name=\"name\" value=\"%s\"></td></tr>\n"
|
||||
"<tr><td><label for=\"descr\">Description:</label></td><td><input type=\"text\" name=\"descr\" value=\"%s\"></td></tr>\n",
|
||||
sName?sName:"", sDescr?sDescr:"");
|
||||
|
||||
if (permDefList) {
|
||||
GBAA(dbuf, "<tr><td><label>Guest Permissions:</label></td>\n<td>");
|
||||
AQH_ModService_WritePermsToForm(AQH_Module_GetGuestPerms(currentMod), permDefList, NULL, dbuf);
|
||||
GBAA(dbuf, "</td></tr>");
|
||||
}
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"module\" value=\"%s\">\n", sModName?sModName:"");
|
||||
GBAS(dbuf, "<input type=\"submit\" value=\"Save\">\n</form>\n\n");
|
||||
|
||||
/* write role list */
|
||||
GBAS(dbuf, "<h2>User Roles</h2>\n");
|
||||
if (roleList)
|
||||
_writeRoleListToForm(roleList, sModName, permDefList, dbuf);
|
||||
else
|
||||
GBAS(dbuf, "<p>none</p>");
|
||||
GBAA(dbuf, "<a href=\"addrole.html?mod=%s\"><img src=\"/pics/plus.png\">Add Role</a>\n", sModName?sModName:"");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeRoleListToForm(const AQH_ROLE_LIST *roleList,
|
||||
const char *sModName,
|
||||
const AQH_PERMDEF_LIST *permDefList,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const AQH_ROLE *role;
|
||||
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead><tr><th>Id</th><th>Name</th><th>Permissions</th><th>Description</th><th>Actions</th></tr>\n</thead>\n"
|
||||
"<tbody>\n");
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
uint8_t id;
|
||||
const char *s;
|
||||
|
||||
GBAS(dbuf, "<tr>");
|
||||
/* id */
|
||||
id=AQH_Role_GetId(role);
|
||||
GBAA(dbuf, "<td>%d</td>", id);
|
||||
/* name */
|
||||
s=AQH_Role_GetName(role);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* permissions */
|
||||
GBAS(dbuf, "<td>");
|
||||
if (permDefList)
|
||||
_writeEnabledPermissions(permDefList, AQH_Role_GetPerms(role), dbuf);
|
||||
GBAS(dbuf, "</td>");
|
||||
/* description */
|
||||
s=AQH_Role_GetDescr(role);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* actions */
|
||||
GBAA(dbuf, "<td>");
|
||||
GBAA(dbuf, "<a href=\"editrole.html?mod=%s&id=%d\"><img src=\"/pics/edit.png\"></a>", sModName?sModName:"", id);
|
||||
GBAA(dbuf, "<a href=\"delrole.html?mod=%s&id=%d\"><img src=\"/pics/minus.png\"></a>", sModName?sModName:"", id);
|
||||
GBAA(dbuf, "</td>");
|
||||
GBAS(dbuf, "</tr>\n");
|
||||
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
|
||||
GBAS(dbuf, "</tbody>\n</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _writeEnabledPermissions(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *s;
|
||||
uint32_t mask;
|
||||
|
||||
s=AQH_PermDef_GetId(permDef);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
if (perms & mask)
|
||||
GBAA(dbuf, "%s ", s?s:"");
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
apps/aqhome-cgi/modules/common/mmodules.h
Normal file
35
apps/aqhome-cgi/modules/common/mmodules.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* 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_MMODULES_H
|
||||
#define AQHOME_CGI_MMODULES_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESREAD 0x001
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESWRITE 0x002
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESADD 0x004
|
||||
#define AQH_MODADMMODULES_PERMS_MODULESDEL 0x008
|
||||
|
||||
|
||||
|
||||
void AQH_ModAdmModules_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmModules_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
684
apps/aqhome-cgi/modules/common/mservice.c
Normal file
684
apps/aqhome-cgi/modules/common/mservice.c
Normal file
@@ -0,0 +1,684 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mservice_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQH_MOD_SERVICE_HEADERFILE "header.html"
|
||||
#define AQH_MOD_SERVICE_FOOTERFILE "footer.html"
|
||||
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE)
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
static void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user);
|
||||
static uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModService_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm);
|
||||
GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData);
|
||||
|
||||
xm->service=sv;
|
||||
xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _freeData(GWEN_UNUSED void *bp, void *p)
|
||||
{
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=(AQH_MOD_SERVICE*) p;
|
||||
free(xm->baseFolder);
|
||||
GWEN_FREE_OBJECT(xm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->service;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->baseFolder;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModService_GetUserPerms(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->userPerms;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->handleRequestFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->loadSubModuleFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetAddHeaderFn(AQH_MODULE *m, AQH_MODSERVICE_ADDHEADER_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->addHeaderFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetAddFooterFn(AQH_MODULE *m, AQH_MODSERVICE_ADDFOOTER_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->addFooterFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
if (xm->addHeaderFn)
|
||||
xm->addHeaderFn(m, lang, dbuf);
|
||||
else {
|
||||
AQH_MODULE *mParent;
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent)
|
||||
AQH_ModService_AddHeader(mParent, lang, dbuf);
|
||||
AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
if (xm->addFooterFn)
|
||||
xm->addFooterFn(m, lang, dbuf);
|
||||
else {
|
||||
AQH_MODULE *mParent;
|
||||
|
||||
AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf);
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent)
|
||||
AQH_ModService_AddFooter(mParent, lang, dbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, dbuf);
|
||||
if (rv<0) {
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->handleRequestFn)
|
||||
return xm->handleRequestFn(m, rq, session, sLastPathElem);
|
||||
}
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->loadSubModuleFn) {
|
||||
AQH_MODULE *mReturn;
|
||||
|
||||
mReturn=xm->loadSubModuleFn(m, rq, session, sModuleName);
|
||||
if (mReturn)
|
||||
AQH_ModService_CalcSessionModPerms(mReturn, session);
|
||||
return mReturn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && filename && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
GWEN_BUFFER *fbuf;
|
||||
int rv;
|
||||
|
||||
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(fbuf, xm->baseFolder);
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en");
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, filename);
|
||||
DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf));
|
||||
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv);
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return rv;
|
||||
}
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)");
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION *AQH_ModService_ReadSession(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *db;
|
||||
const char *s;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
db=AQCGI_Request_GetDbRequestHeader(rq);
|
||||
s=GWEN_DB_GetCharValue(db, "cookies/session", 0, NULL);
|
||||
if (s && *s) {
|
||||
AQH_SESSION *session;
|
||||
|
||||
session=AQH_Service_LoadSession(sv, s);
|
||||
if (session==NULL) {
|
||||
DBG_ERROR(NULL, "Session \"%s\" not found", s);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
const char *sUserName;
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
sUserName=AQH_Session_GetUserAlias(session);
|
||||
if (sUserName && *sUserName) {
|
||||
AQH_USER *user;
|
||||
|
||||
user=AQH_Service_LoadUser(sv, sUserName);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
|
||||
AQH_Session_free(session);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "User is \"%s\"", sUserName);
|
||||
}
|
||||
AQH_Session_SetUser(session, user);
|
||||
}
|
||||
/* renew session cookie */
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(tbuf, "Set-Cookie: session=%s; max-age=86400", AQH_Session_GetUid(session));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
DBG_ERROR(NULL, "Renew session cookie");
|
||||
GWEN_Buffer_free(tbuf);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No session cookie");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_CalcSessionModPerms(AQH_MODULE *m, const AQH_SESSION *session)
|
||||
{
|
||||
const AQH_USER *user;
|
||||
|
||||
user=session?AQH_Session_GetUser(session):NULL;
|
||||
_calcUserModPerms(m, user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
uint32_t perms=0;
|
||||
|
||||
if (user) {
|
||||
if (AQH_User_GetFlags(user) & AQH_USER_FLAGS_ADMIN)
|
||||
perms=0xffffffff;
|
||||
else {
|
||||
const char *sModName;
|
||||
const AQH_MODULE_PERMS_LIST *modPermsList;
|
||||
AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
sModName=AQH_Module_GetName(m);
|
||||
modPermsList=AQH_User_GetModulePermList(user);
|
||||
modPerms=(sModName && modPermsList)?AQH_ModulePerms_List_GetByModuleId(modPermsList, sModName):NULL;
|
||||
if (modPerms)
|
||||
perms=_calcRolePerms(m, modPerms);
|
||||
else
|
||||
perms=AQH_Module_GetGuestPerms(m);
|
||||
}
|
||||
} /* if (user) */
|
||||
else
|
||||
perms=AQH_Module_GetGuestPerms(m);
|
||||
xm->userPerms=perms;
|
||||
}
|
||||
} /* if (m) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms)
|
||||
{
|
||||
uint32_t perms=0;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
roleList=AQH_Module_GetRoleList(m);
|
||||
if (roleList) {
|
||||
int roleArraySize;
|
||||
int i;
|
||||
uint32_t explAddPerms=0;
|
||||
uint32_t explDelPerms=0;
|
||||
|
||||
roleArraySize=AQH_ModulePerms_GetRoleArrayArraySize();
|
||||
for (i=0; i<roleArraySize; i++) {
|
||||
int roleId;
|
||||
|
||||
roleId=AQH_ModulePerms_GetRoleArrayAt(modPerms, i);
|
||||
if (roleId) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_GetById(roleList, roleId);
|
||||
if (role) {
|
||||
perms|=AQH_Role_GetPerms(role);
|
||||
explAddPerms|=AQH_Role_GetExplAddPerms(role);
|
||||
explAddPerms|=AQH_Role_GetExplDelPerms(role);
|
||||
}
|
||||
}
|
||||
} /* for */
|
||||
/* collate permissions */
|
||||
perms|=explAddPerms;
|
||||
perms|=AQH_ModulePerms_GetExplAddPerms(modPerms);
|
||||
perms&=~explDelPerms;
|
||||
perms&=~AQH_ModulePerms_GetExplDelPerms(modPerms);
|
||||
}
|
||||
return perms;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddPermDef(AQH_PERMDEF_LIST *permDefList, const char *id, uint32_t mask, const char *descr)
|
||||
{
|
||||
AQH_PERMDEF *permDef;
|
||||
|
||||
permDef=AQH_PermDef_new();
|
||||
AQH_PermDef_SetId(permDef, id);
|
||||
AQH_PermDef_SetMask(permDef, mask);
|
||||
AQH_PermDef_SetDescr(permDef, descr);
|
||||
AQH_PermDef_List_Add(permDef, permDefList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_AddRole(AQH_ROLE_LIST *roleList, int id, const char *name, uint32_t perms, const char *descr)
|
||||
{
|
||||
AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_new();
|
||||
AQH_Role_SetId(role, id);
|
||||
AQH_Role_SetName(role, name);
|
||||
AQH_Role_SetPerms(role, perms);
|
||||
AQH_Role_SetDescr(role, descr);
|
||||
AQH_Role_List_Add(role, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_HandleRequestWithTable(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
const char *page,
|
||||
const AQH_MODSERVICE_HANDLER_ENTRY *e)
|
||||
{
|
||||
uint32_t perms;
|
||||
GWEN_BUFFER *dbuf;
|
||||
int i;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
DBG_ERROR(NULL, "Perms=%08x", perms);
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
for (i=0; ; i++) {
|
||||
if (e[i].page==NULL) {
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
break;
|
||||
}
|
||||
if ((AQCGI_Request_GetRequestMethod(rq)==e[i].httpMethod) &&
|
||||
(strcasecmp(page, e[i].page)==0)) {
|
||||
/* preset result */
|
||||
AQCGI_Request_SetResponseCode(rq, 200);
|
||||
AQCGI_Request_SetResponseText(rq, "Ok");
|
||||
if ((perms & e[i].perms)==e[i].perms)
|
||||
(e[i].handlerFn)(m, rq, session, dbuf);
|
||||
else {
|
||||
GWEN_Buffer_AppendString(dbuf, "<h1>Error</h1><p>No permissions for this request.</p>");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (AQCGI_Request_GetFlags(rq) & AQCGI_FLAGS_HAS_CONTENT_HEADER)
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_WritePermsToForm(uint32_t perms, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_PermDef_GetId(permDef);
|
||||
if (s && *s) {
|
||||
uint32_t mask;
|
||||
|
||||
GBAS(tbuf, s);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
if (perms & mask)
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\" checked>", GWEN_Buffer_GetStart(tbuf));
|
||||
else
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\">", s?s:"");
|
||||
GBAA(dbuf, "<label for=\"%s\">%s</label>", GWEN_Buffer_GetStart(tbuf), s?s:"");
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_ModService_ReadPermsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
if (permDefList) {
|
||||
const AQH_PERMDEF *permDef;
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
permDef=AQH_PermDef_List_First(permDefList);
|
||||
while(permDef) {
|
||||
const char *id;
|
||||
|
||||
id=AQH_PermDef_GetId(permDef);
|
||||
if (id && *id) {
|
||||
uint32_t mask;
|
||||
const char *s;
|
||||
|
||||
GBAS(tbuf, id);
|
||||
mask=AQH_PermDef_GetMask(permDef);
|
||||
s=GWEN_DB_GetCharValue(dbPost, GWEN_Buffer_GetStart(tbuf), 0, NULL);
|
||||
if (s && *s)
|
||||
result|=mask;
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
permDef=AQH_PermDef_List_Next(permDef);
|
||||
}
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE_LIST *AQH_ModService_LoadRawModules(AQH_MODULE *m)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slModuleNames;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slModuleNames=AQH_Service_ListModules(sv);
|
||||
if (slModuleNames) {
|
||||
AQH_MODULE_LIST *modList;
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
modList=AQH_Module_List_new();
|
||||
se=GWEN_StringList_FirstEntry(slModuleNames);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_MODULE *currentMod;
|
||||
|
||||
currentMod=AQH_Service_LoadModule(sv, sModName);
|
||||
if (currentMod)
|
||||
AQH_Module_List_Add(currentMod, modList);
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GWEN_StringList_free(slModuleNames);
|
||||
if (AQH_Module_List_GetCount(modList))
|
||||
return modList;
|
||||
AQH_Module_List_free(modList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER_LIST *AQH_ModService_LoadRawUsers(AQH_MODULE *m)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_STRINGLIST *slUserNames;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
slUserNames=AQH_Service_ListUsers(sv);
|
||||
if (slUserNames) {
|
||||
AQH_USER_LIST *userList;
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
userList=AQH_User_List_new();
|
||||
se=GWEN_StringList_FirstEntry(slUserNames);
|
||||
while(se) {
|
||||
const char *sModName;
|
||||
|
||||
sModName=GWEN_StringListEntry_Data(se);
|
||||
if (sModName && *sModName) {
|
||||
AQH_USER *u;
|
||||
|
||||
u=AQH_Service_LoadUser(sv, sModName);
|
||||
if (u)
|
||||
AQH_User_List_Add(u, userList);
|
||||
}
|
||||
se=GWEN_StringListEntry_Next(se);
|
||||
}
|
||||
GWEN_StringList_free(slUserNames);
|
||||
if (AQH_User_List_GetCount(userList))
|
||||
return userList;
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
85
apps/aqhome-cgi/modules/common/mservice.h
Normal file
85
apps/aqhome-cgi/modules/common/mservice.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
* 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_MSERVICE_H
|
||||
#define AQHOME_CGI_MSERVICE_H
|
||||
|
||||
#include <aqhome-cgi/service/module.h>
|
||||
#include <aqhome-cgi/service/service.h>
|
||||
#include <aqhome-cgi/service/session.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#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);
|
||||
typedef void (*AQH_MODSERVICE_ADDFOOTER_FN)(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
typedef struct AQH_MODSERVICE_HANDLER_ENTRY AQH_MODSERVICE_HANDLER_ENTRY;
|
||||
struct AQH_MODSERVICE_HANDLER_ENTRY {
|
||||
const char *page;
|
||||
int httpMethod;
|
||||
uint32_t perms;
|
||||
void (*handlerFn)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m);
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m);
|
||||
|
||||
uint32_t AQH_ModService_GetUserPerms(const AQH_MODULE *m);
|
||||
|
||||
void AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
void AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName);
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem);
|
||||
|
||||
AQH_SESSION *AQH_ModService_ReadSession(AQH_MODULE *m, AQCGI_REQUEST *rq);
|
||||
void AQH_ModService_CalcSessionModPerms(AQH_MODULE *m, const AQH_SESSION *session);
|
||||
|
||||
void AQH_ModService_HandleRequestWithTable(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
const char *page,
|
||||
const AQH_MODSERVICE_HANDLER_ENTRY *e);
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename, GWEN_BUFFER *dbuf);
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf);
|
||||
|
||||
void AQH_ModService_AddPermDef(AQH_PERMDEF_LIST *permDefList, const char *id, uint32_t mask, const char *descr);
|
||||
void AQH_ModService_AddRole(AQH_ROLE_LIST *roleList, int id, const char *name, uint32_t perms, const char *descr);
|
||||
|
||||
|
||||
void AQH_ModService_WritePermsToForm(uint32_t perms, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix, GWEN_BUFFER *dbuf);
|
||||
uint32_t AQH_ModService_ReadPermsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList, const char *sPrefix);
|
||||
|
||||
AQH_MODULE_LIST *AQH_ModService_LoadRawModules(AQH_MODULE *m);
|
||||
AQH_USER_LIST *AQH_ModService_LoadRawUsers(AQH_MODULE *m);
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn);
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn);
|
||||
|
||||
void AQH_ModService_SetAddHeaderFn(AQH_MODULE *m, AQH_MODSERVICE_ADDHEADER_FN fn);
|
||||
void AQH_ModService_SetAddFooterFn(AQH_MODULE *m, AQH_MODSERVICE_ADDFOOTER_FN fn);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,16 +9,19 @@
|
||||
#ifndef AQHOME_CGI_MSERVICE_P_H
|
||||
#define AQHOME_CGI_MSERVICE_P_H
|
||||
|
||||
#include "aqhome-cgi/modules/mservice.h"
|
||||
#include "aqhome-cgi/modules/common/mservice.h"
|
||||
|
||||
|
||||
typedef struct AQH_MOD_SERVICE AQH_MOD_SERVICE;
|
||||
struct AQH_MOD_SERVICE {
|
||||
AQH_SERVICE *service;
|
||||
char *baseFolder;
|
||||
uint32_t userPerms;
|
||||
|
||||
AQH_MODSERVICE_HANDLEREQUEST_FN handleRequestFn;
|
||||
AQH_MODSERVICE_LOADSUBMODULE_FN loadSubModuleFn;
|
||||
AQH_MODSERVICE_ADDHEADER_FN addHeaderFn;
|
||||
AQH_MODSERVICE_ADDFOOTER_FN addFooterFn;
|
||||
};
|
||||
|
||||
|
||||
640
apps/aqhome-cgi/modules/common/musers.c
Normal file
640
apps/aqhome-cgi/modules/common/musers.c
Normal file
@@ -0,0 +1,640 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./musers.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define GBAS GWEN_Buffer_AppendString
|
||||
#define GBAA GWEN_Buffer_AppendArgs
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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 _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqEditUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
static void _handleRqAddUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf);
|
||||
|
||||
static int _getHighestUserId(const AQH_USER_LIST *userList);
|
||||
static int _modulePermsHasRole(const AQH_MODULE_PERMS *modPerms, uint8_t rid);
|
||||
|
||||
static void _writeEditUserForm(AQH_MODULE *m,
|
||||
const AQH_USER *u,
|
||||
const char *sAlias,
|
||||
const char *sUrl,
|
||||
const char *sSubmitText,
|
||||
GWEN_BUFFER *dbuf);
|
||||
static void _writeUserModRolesToForm(const AQH_ROLE_LIST *roles, const AQH_MODULE_PERMS *perms, const char *sModName, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _readAllModRolesForUserFromForm(AQH_MODULE *m, GWEN_DB_NODE *dbPost, AQH_USER *u);
|
||||
static void _readModRolesFromForm(GWEN_DB_NODE *dbPost,
|
||||
const AQH_ROLE_LIST *roleList,
|
||||
const char *sPrefix,
|
||||
AQH_MODULE_PERMS *modPerms);
|
||||
|
||||
static void _addLabelAndInputToFormTableH(const char *title, const char *name, const char *value, const char *xxtra, GWEN_BUFFER *dbuf);
|
||||
static void _addUserStateLabelAndSelectionToFormTableH(const char *sTitle, const char *sName, int st, GWEN_BUFFER *dbuf);
|
||||
|
||||
static void _setLocationHeaderForMod(AQCGI_REQUEST *rq, const char *page, const char *sModName);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODSERVICE_HANDLER_ENTRY _requestTable[]={
|
||||
{"index.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSREAD, _handleRqIndex},
|
||||
{"edituser.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqEditUserGet},
|
||||
{"edituser.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqEditUserPost},
|
||||
{"adduser.html", AQCGI_REQUEST_METHOD_GET, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqAddUserGet},
|
||||
{"adduser.html", AQCGI_REQUEST_METHOD_POST, AQH_MODADMUSERS_PERMS_USERSWRITE, _handleRqAddUserPost},
|
||||
{NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModAdmUsers_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_ModAdmUsers_Create(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
m=AQH_Module_new();
|
||||
AQH_Module_SetName(m, "users");
|
||||
AQH_Module_SetDescr(m, "user administration 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, "UserRead", 0x001, "Read users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserWrite", 0x002, "Modify users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserAdd", 0x004, "Add users");
|
||||
AQH_ModService_AddPermDef(permDefList, "UserDel", 0x008, "Remove users");
|
||||
|
||||
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++, "admin",
|
||||
AQH_MODADMUSERS_PERMS_USERSREAD |
|
||||
AQH_MODADMUSERS_PERMS_USERSWRITE |
|
||||
AQH_MODADMUSERS_PERMS_USERSADD |
|
||||
AQH_MODADMUSERS_PERMS_USERSDEL,
|
||||
"Administrator Role");
|
||||
AQH_Module_SetRoleList(m, roleList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
/* no sub-modules */
|
||||
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 _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_USER_LIST *userList;
|
||||
uint32_t perms;
|
||||
|
||||
perms=AQH_ModService_GetUserPerms(m);
|
||||
userList=AQH_ModService_LoadRawUsers(m);
|
||||
|
||||
GBAS(dbuf, "<h1>Users</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Id</th><th>Alias</th><th>Name</th><th>Status</th><th>Email</th><th>Notes</th><th>Actions</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
if (userList) {
|
||||
const AQH_USER *u;
|
||||
|
||||
AQH_User_List_SortByAlias(userList, 1);
|
||||
u=AQH_User_List_First(userList);
|
||||
while(u) {
|
||||
const char *sUserAlias;
|
||||
|
||||
sUserAlias=AQH_User_GetAlias(u);
|
||||
if (sUserAlias && *sUserAlias) {
|
||||
uint32_t id;
|
||||
const char *s;
|
||||
const char *sAlias;
|
||||
|
||||
id=AQH_User_GetId(u);
|
||||
sAlias=AQH_User_GetAlias(u);
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td>%lu</td>", (unsigned long int) id);
|
||||
GBAA(dbuf, "<td>%s</td>", sAlias?sAlias:"");
|
||||
s=AQH_User_GetName(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_UserState_toString(AQH_User_GetState(u));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_User_GetEmail(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
s=AQH_User_GetNotes(u);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
if (perms & AQH_MODADMUSERS_PERMS_USERSWRITE) {
|
||||
DBG_ERROR(NULL, "User=%s", sAlias?sAlias:"");
|
||||
GBAS(dbuf, "<a href=\"edituser.html?alias=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sAlias?sAlias:"", dbuf);
|
||||
GBAS(dbuf, "\"><img src=\"/pics/edit.png\"></a>");
|
||||
}
|
||||
GBAA(dbuf, "</td>\n");
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
}
|
||||
u=AQH_User_List_Next(u);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
if (perms & AQH_MODADMUSERS_PERMS_USERSADD)
|
||||
GBAS(dbuf, "<hr><a href=\"adduser.html\">Add User</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbQuery;
|
||||
const char *sAlias;
|
||||
AQH_USER *user;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbQuery=AQCGI_Request_GetDbQuery(rq);
|
||||
sAlias=dbQuery?GWEN_DB_GetCharValue(dbQuery, "alias", 0, NULL):NULL;
|
||||
user=(sAlias && *sAlias)?AQH_Service_LoadUser(sv, sAlias):NULL;
|
||||
if (user) {
|
||||
_writeEditUserForm(m, user, sAlias, "edituser.html", "Save", dbuf);
|
||||
AQH_User_free(user);
|
||||
}
|
||||
else {
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqEditUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sAlias;
|
||||
AQH_USER *u;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sAlias=dbPost?GWEN_DB_GetCharValue(dbPost, "alias", 0, NULL):NULL;
|
||||
u=(sAlias && *sAlias)?AQH_Service_LoadUser(sv, sAlias):NULL;
|
||||
if (u) {
|
||||
const char *s;
|
||||
int state;
|
||||
int rv;
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
AQH_User_SetName(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "email", 0, NULL);
|
||||
AQH_User_SetEmail(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "notes", 0, NULL);
|
||||
AQH_User_SetNotes(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "status", 0, NULL);
|
||||
state=(s && *s)?AQH_UserState_fromString(s):AQH_UserState_Unknown;
|
||||
if (state!=AQH_UserState_Unknown)
|
||||
AQH_User_SetState(u, state);
|
||||
|
||||
_readAllModRolesForUserFromForm(m, dbPost, u);
|
||||
|
||||
rv=AQH_Service_SaveUser(sv, u);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving user</p>");
|
||||
DBG_ERROR(NULL, "Could not save user \"%s\"", sAlias);
|
||||
AQH_User_free(u);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "User \"%s\" saved", sAlias);
|
||||
AQH_User_free(u);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Could not load user \"%s\"", sAlias?sAlias:"<no name>");
|
||||
GBAS(dbuf, "<p>Error loading user.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddUserGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
DBG_ERROR(NULL, "AddUser");
|
||||
_writeEditUserForm(m, NULL, NULL, "adduser.html", "Add", dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRqAddUserPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
GWEN_DB_NODE *dbPost;
|
||||
const char *sAlias;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
sAlias=dbPost?GWEN_DB_GetCharValue(dbPost, "alias", 0, NULL):NULL;
|
||||
// TODO: check alias validity
|
||||
if (sAlias) {
|
||||
AQH_USER *u;
|
||||
const char *s;
|
||||
int state;
|
||||
int rv;
|
||||
uint32_t userId;
|
||||
AQH_USER_LIST *userList;
|
||||
|
||||
u=AQH_User_new();
|
||||
userList=AQH_ModService_LoadRawUsers(m);
|
||||
userId=_getHighestUserId(userList)+1;
|
||||
AQH_User_SetId(u, userId);
|
||||
AQH_User_SetAlias(u, sAlias);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL);
|
||||
AQH_User_SetName(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "email", 0, NULL);
|
||||
AQH_User_SetEmail(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "notes", 0, NULL);
|
||||
AQH_User_SetNotes(u, s);
|
||||
s=GWEN_DB_GetCharValue(dbPost, "status", 0, NULL);
|
||||
state=(s && *s)?AQH_UserState_fromString(s):AQH_UserState_Unknown;
|
||||
if (state!=AQH_UserState_Unknown)
|
||||
AQH_User_SetState(u, state);
|
||||
|
||||
rv=AQH_Service_AddUser(sv, u);
|
||||
if (rv<0) {
|
||||
GBAS(dbuf, "<h2>Error</h2><p>Error saving user</p>");
|
||||
DBG_ERROR(NULL, "Could not save user \"%s\" (%d)", sAlias, rv);
|
||||
AQH_User_free(u);
|
||||
AQH_User_List_free(userList);
|
||||
return;
|
||||
}
|
||||
DBG_ERROR(NULL, "User \"%s\" saved", sAlias);
|
||||
AQH_User_free(u);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
AQH_User_List_free(userList);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing alias");
|
||||
GBAS(dbuf, "<p>Missing alias.</p>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getHighestUserId(const AQH_USER_LIST *userList)
|
||||
{
|
||||
int id=0;
|
||||
|
||||
if (userList) {
|
||||
const AQH_USER *user;
|
||||
|
||||
user=AQH_User_List_First(userList);
|
||||
while(user) {
|
||||
int uid;
|
||||
|
||||
uid=AQH_User_GetId(user);
|
||||
id=(uid>id)?uid:id;
|
||||
user=AQH_User_List_Next(user);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _modulePermsHasRole(const AQH_MODULE_PERMS *modPerms, uint8_t rid)
|
||||
{
|
||||
if (modPerms) {
|
||||
int arraySize;
|
||||
int i;
|
||||
|
||||
arraySize=AQH_ModulePerms_GetRoleArrayArraySize();
|
||||
for(i=0; i<arraySize; i++) {
|
||||
if (AQH_ModulePerms_GetRoleArrayAt(modPerms, i)==rid)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _writeEditUserForm(AQH_MODULE *m,
|
||||
const AQH_USER *u,
|
||||
const char *sAlias,
|
||||
const char *sUrl,
|
||||
const char *sSubmitText,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_MODULE_LIST *moduleList;
|
||||
|
||||
/* write user info */
|
||||
GBAS(dbuf, "<h2>User Info</h2>\n");
|
||||
GBAA(dbuf,
|
||||
"<form action=\"%s\" method=\"post\">\n"
|
||||
"<table class=\"formtable\">\n",
|
||||
sUrl?sUrl:"");
|
||||
_addLabelAndInputToFormTableH("Alias", "alias", sAlias, "required", dbuf);
|
||||
_addLabelAndInputToFormTableH("Name", "name", u?AQH_User_GetName(u):NULL, NULL, dbuf);
|
||||
_addLabelAndInputToFormTableH("Email", "email", u?AQH_User_GetEmail(u):NULL, NULL, dbuf);
|
||||
_addLabelAndInputToFormTableH("Notes", "notes", u?AQH_User_GetNotes(u):NULL, NULL, dbuf);
|
||||
_addUserStateLabelAndSelectionToFormTableH("Status", "status", u?AQH_User_GetState(u):AQH_UserState_Unknown, dbuf);
|
||||
|
||||
GBAS(dbuf, "</table>\n");
|
||||
|
||||
/* module permissions */
|
||||
GBAS(dbuf, "<h2>Module Roles</h2>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr><th>Module</th><th>Roles</th></tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
moduleList=AQH_ModService_LoadRawModules(m);
|
||||
if (moduleList) {
|
||||
const AQH_MODULE_PERMS_LIST *modPermsList;
|
||||
const AQH_MODULE *currentMod;
|
||||
|
||||
modPermsList=u?AQH_User_GetModulePermList(u):NULL;
|
||||
currentMod=AQH_Module_List_First(moduleList);
|
||||
while(currentMod) {
|
||||
const char *sModName;
|
||||
const AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
sModName=AQH_Module_GetName(currentMod);
|
||||
GBAA(dbuf, "<tr><td>%s</td><td>", sModName);
|
||||
|
||||
modPerms=modPermsList?AQH_ModulePerms_List_GetByModuleId(modPermsList, sModName):NULL;
|
||||
_writeUserModRolesToForm(AQH_Module_GetRoleList(currentMod), modPerms, sModName, dbuf);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
GBAS(dbuf, "<td>");
|
||||
|
||||
currentMod=AQH_Module_List_Next(currentMod);
|
||||
} /* while */
|
||||
AQH_Module_List_free(moduleList);
|
||||
}
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
|
||||
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"alias\" value=\"%s\">\n", sAlias?sAlias:"");
|
||||
GBAA(dbuf, "<input type=\"submit\" value=\"%s\">\n</form>\n\n", sSubmitText?sSubmitText:"Save");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _readAllModRolesForUserFromForm(AQH_MODULE *m, GWEN_DB_NODE *dbPost, AQH_USER *u)
|
||||
{
|
||||
AQH_MODULE_LIST *moduleList;
|
||||
|
||||
moduleList=AQH_ModService_LoadRawModules(m);
|
||||
if (moduleList) {
|
||||
AQH_MODULE_PERMS_LIST *permsList;
|
||||
const AQH_MODULE *module;
|
||||
|
||||
permsList=AQH_User_GetModulePermList(u);
|
||||
if (permsList==NULL) {
|
||||
DBG_ERROR(NULL, "Creating module perms list for user");
|
||||
permsList=AQH_ModulePerms_List_new();
|
||||
AQH_User_SetModulePermList(u, permsList);
|
||||
}
|
||||
|
||||
module=AQH_Module_List_First(moduleList);
|
||||
while(module) {
|
||||
const char *sModName;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
sModName=AQH_Module_GetName(module);
|
||||
roleList=AQH_Module_GetRoleList(module);
|
||||
if (sModName && *sModName && roleList) {
|
||||
AQH_MODULE_PERMS *modPerms;
|
||||
|
||||
modPerms=AQH_ModulePerms_List_GetByModuleId(permsList, sModName);
|
||||
if (modPerms==NULL) {
|
||||
modPerms=AQH_ModulePerms_new();
|
||||
AQH_ModulePerms_SetModuleId(modPerms, sModName);
|
||||
AQH_ModulePerms_List_Add(modPerms, permsList);
|
||||
}
|
||||
_readModRolesFromForm(dbPost, roleList, sModName, modPerms);
|
||||
}
|
||||
module=AQH_Module_List_Next(module);
|
||||
}
|
||||
|
||||
AQH_Module_List_free(moduleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeUserModRolesToForm(const AQH_ROLE_LIST *roleList, const AQH_MODULE_PERMS *modPerms, const char *sModName, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (roleList) {
|
||||
const AQH_ROLE *role;
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
const char *sRoleName;
|
||||
uint8_t roleId;
|
||||
|
||||
roleId=AQH_Role_GetId(role);
|
||||
sRoleName=AQH_Role_GetName(role);
|
||||
if (sRoleName && *sRoleName) {
|
||||
int isChecked;
|
||||
|
||||
isChecked=(modPerms && _modulePermsHasRole(modPerms, roleId));
|
||||
if (sModName && *sModName) {
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s:%s\" %s>", sModName, sRoleName, isChecked?"checked":"");
|
||||
GBAA(dbuf, "<label for=\"%s:%s\">%s</label>", sModName, sRoleName, sRoleName);
|
||||
}
|
||||
else {
|
||||
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\" %s>", sRoleName, isChecked?"checked":"");
|
||||
GBAA(dbuf, "<label for=\"%s\">%s</label>", sRoleName, sRoleName);
|
||||
}
|
||||
}
|
||||
role=AQH_Role_List_Next(role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _readModRolesFromForm(GWEN_DB_NODE *dbPost,
|
||||
const AQH_ROLE_LIST *roleList,
|
||||
const char *sPrefix,
|
||||
AQH_MODULE_PERMS *modPerms)
|
||||
{
|
||||
AQH_ModulePerms_PresetRoleArray(modPerms, 0);
|
||||
if (roleList) {
|
||||
GWEN_BUFFER *tbuf;
|
||||
uint32_t pos;
|
||||
const AQH_ROLE *role;
|
||||
int nextRolePos=0;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (sPrefix && *sPrefix)
|
||||
GBAA(tbuf, "%s:", sPrefix);
|
||||
pos=GWEN_Buffer_GetPos(tbuf);
|
||||
|
||||
role=AQH_Role_List_First(roleList);
|
||||
while(role) {
|
||||
const char *roleName;
|
||||
|
||||
roleName=AQH_Role_GetName(role);
|
||||
if (roleName && *roleName) {
|
||||
const char *s;
|
||||
|
||||
GBAS(tbuf, roleName);
|
||||
s=GWEN_DB_GetCharValue(dbPost, GWEN_Buffer_GetStart(tbuf), 0, NULL);
|
||||
if (s && *s) {
|
||||
if (nextRolePos<AQH_ModulePerms_GetRoleArrayArraySize())
|
||||
AQH_ModulePerms_SetRoleArrayAt(modPerms, nextRolePos++, AQH_Role_GetId(role));
|
||||
}
|
||||
GWEN_Buffer_Crop(tbuf, 0, pos);
|
||||
}
|
||||
|
||||
role=AQH_Role_List_Next(role);
|
||||
} /* while */
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void _addUserStateLabelAndSelectionToFormTableH(const char *sTitle, const char *sName, int st, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
int i;
|
||||
|
||||
GBAA(dbuf, "<tr><td><label for=\"%s\">%s:</label></td>", sName?sName:"", sTitle?sTitle:"");
|
||||
GBAA(dbuf, "<td><select name=\"%s\">", sName?sName:"");
|
||||
for(i=AQH_UserState_Unknown; i<=AQH_UserState_Active; i++) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_UserState_toString(i);
|
||||
GBAA(dbuf, "<option value=\"%s\" %s>%s</option>", s, (i==st)?"selected":"", s);
|
||||
}
|
||||
GBAS(dbuf, "</select></td></tr>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addLabelAndInputToFormTableH(const char *sTitle, const char *sName, const char *sValue, const char *sExtra, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td><label for=\"%s:\">%s</label></td>", sName?sName:"", sTitle?sTitle:"");
|
||||
GBAA(dbuf, "<td><input type=\"text\" name=\"%s\"", sName?sName:"");
|
||||
if (sValue && *sValue)
|
||||
GBAA(dbuf, " value=\"%s\"", sValue);
|
||||
if (sExtra && *sExtra)
|
||||
GBAA(dbuf, " %s", sExtra);
|
||||
GBAS(dbuf, "></td>");
|
||||
GBAS(dbuf, "</tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
35
apps/aqhome-cgi/modules/common/musers.h
Normal file
35
apps/aqhome-cgi/modules/common/musers.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/****************************************************************************
|
||||
* 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_MUSERS_H
|
||||
#define AQHOME_CGI_MUSERS_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MODADMUSERS_PERMS_USERSREAD 0x001
|
||||
#define AQH_MODADMUSERS_PERMS_USERSWRITE 0x002
|
||||
#define AQH_MODADMUSERS_PERMS_USERSADD 0x004
|
||||
#define AQH_MODADMUSERS_PERMS_USERSDEL 0x008
|
||||
|
||||
|
||||
|
||||
void AQH_ModAdmUsers_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
int AQH_ModAdmUsers_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
99
apps/aqhome-cgi/modules/devices/0BUILD
Normal file
99
apps/aqhome-cgi/modules/devices/0BUILD
Normal file
@@ -0,0 +1,99 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_mdevices" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqcgi_cflags)
|
||||
$(aqdiagram_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
-I$(topsrcdir)/apps
|
||||
-I$(topbuilddir)/apps
|
||||
-I$(builddir)
|
||||
-I$(srcdir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags-INACTIVE" >
|
||||
--api=AQHOME_API
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/typefiles" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_sources" >
|
||||
</setVar>
|
||||
|
||||
<setVar name="local/built_headers_pub">
|
||||
</setVar>
|
||||
|
||||
|
||||
<setVar name="local/built_headers_priv" >
|
||||
</setVar>
|
||||
|
||||
|
||||
<headers dist="false" install="$(pkgincludedir)/service" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/service" >
|
||||
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
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(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
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
395
apps/aqhome-cgi/modules/devices/mdevices.c
Normal file
395
apps/aqhome-cgi/modules/devices/mdevices.c
Normal file
@@ -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 <config.h>
|
||||
#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 <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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, "<input type=\"color\" name=\"%s\" value=\"refresh\"/>", sValueName);
|
||||
break;
|
||||
case AQH_ValueModality_OnOff:
|
||||
GBAA(dbuf,
|
||||
"<select name=\"%s\">"
|
||||
"<option value=\"unchanged\">unchanged</option>"
|
||||
"<option value=\"off\">off</option>"
|
||||
"<option value=\"on\">on</option>"
|
||||
"</select>",
|
||||
sValueName);
|
||||
break;
|
||||
case AQH_ValueModality_OnOffAuto:
|
||||
GBAA(dbuf,
|
||||
"<select name=\"%s\">"
|
||||
"<option value=\"unchanged\">unchanged</option>"
|
||||
"<option value=\"off\">off</option>"
|
||||
"<option value=\"on\">on</option>"
|
||||
"<option value=\"auto\">auto</option>"
|
||||
"</select>",
|
||||
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, "<input type=\"text\" name=\"%s\" value=\"#%08x\"/>", sValueName, (uint32_t) (u.f));
|
||||
#else
|
||||
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"#%08x\"/>#%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, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
break;
|
||||
case AQH_ValueModality_OnOffAuto:
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"auto\" %s>auto</option>", (intVal==2)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
break;
|
||||
default:
|
||||
// GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"%.2f\"/>", 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
55
apps/aqhome-cgi/modules/devices/mdevices.h
Normal file
55
apps/aqhome-cgi/modules/devices/mdevices.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
* 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_MODULES_DEVICES_H
|
||||
#define AQHOME_CGI_MODULES_DEVICES_H
|
||||
|
||||
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEREAD 0x001
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEWRITE 0x002
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEADD 0x004
|
||||
#define AQH_MODDEVICES_PERMS_DEVICEDEL 0x008
|
||||
|
||||
#define AQH_MODDEVICES_PERMS_VALUEREAD 0x010
|
||||
#define AQH_MODDEVICES_PERMS_VALUEWRITE 0x020
|
||||
#define AQH_MODDEVICES_PERMS_VALUEADD 0x040
|
||||
#define AQH_MODDEVICES_PERMS_VALUEDEL 0x080
|
||||
#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);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
131
apps/aqhome-cgi/modules/devices/mdevices_device.c
Normal file
131
apps/aqhome-cgi/modules/devices/mdevices_device.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_device.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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:"<empty>");
|
||||
|
||||
GBAA(dbuf,"<h1>Device %s</h1>\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,"<form action=\"device.html\" method=\"post\">\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
|
||||
|
||||
GBAS(dbuf,"<table>\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,"</table>\n");
|
||||
GBAS(dbuf,"<br>\n");
|
||||
|
||||
GBAS(dbuf,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addFieldToForm(const char *sFieldTitle, const char *sFieldName, const char *sFieldContent, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAS(dbuf, "<tr>");
|
||||
GBAA(dbuf, "<td><label for=\"%s\">%s</label></td>", sFieldName, sFieldTitle);
|
||||
GBAA(dbuf, "<td><input type=\"text\" name=\"%s\" value=\"%s\"/></td>", sFieldName, sFieldContent?sFieldContent:"");
|
||||
GBAS(dbuf, "</tr>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_device.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_device.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
135
apps/aqhome-cgi/modules/devices/mdevices_index.c
Normal file
135
apps/aqhome-cgi/modules/devices/mdevices_index.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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, "<p>No devices.</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
GBAS(dbuf, "<h1>Devices</h1>\n");
|
||||
GBAS(dbuf,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>\n"
|
||||
"<tr>"
|
||||
"<th>Name For System</th>"
|
||||
"<th>Name For GUI</th>"
|
||||
"<th>Room</th>"
|
||||
"<th>Location</th>"
|
||||
"<th>Description</th>"
|
||||
"<th>Actions</th>"
|
||||
"</tr>\n"
|
||||
"</thead>\n"
|
||||
"<tbody>\n");
|
||||
|
||||
device=AQH_Device_List_First(deviceList);
|
||||
while(device) {
|
||||
const char *s;
|
||||
const char *sDevice;
|
||||
|
||||
GBAA(dbuf, "<tr>");
|
||||
/* name for system */
|
||||
sDevice=AQH_Device_GetNameForSystem(device);
|
||||
GBAA(dbuf,"<td>%s</td>", sDevice?sDevice:"");
|
||||
/* nameForGui */
|
||||
s=AQH_Device_GetNameForGui(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* room */
|
||||
s=AQH_Device_GetRoomName(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* location */
|
||||
s=AQH_Device_GetLocation(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
/* description */
|
||||
s=AQH_Device_GetDescription(device);
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAS(dbuf, "<td>");
|
||||
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, "</td>");
|
||||
|
||||
GBAA(dbuf, "</tr>");
|
||||
device=AQH_Device_List_Next(device);
|
||||
}
|
||||
|
||||
GBAS(dbuf,
|
||||
"</tbody>\n"
|
||||
"</table>\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,"<a href=\"%s?device=", page);
|
||||
GWEN_Text_EscapeToBufferTolerant(sDevice, dbuf);
|
||||
GBAS(dbuf,"\">");
|
||||
GBAA(dbuf,"<img src=\"%s\" alt=\"%s\" title=\"%s\" />", imgName, action, action);
|
||||
GBAS(dbuf,"</a>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_index.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_index.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
129
apps/aqhome-cgi/modules/devices/mdevices_init.c
Normal file
129
apps/aqhome-cgi/modules/devices/mdevices_init.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_init.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_init.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_init.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
int AQH_ModDevices_Create(AQH_SERVICE *sv);
|
||||
|
||||
|
||||
#endif
|
||||
194
apps/aqhome-cgi/modules/devices/mdevices_setdata.c
Normal file
194
apps/aqhome-cgi/modules/devices/mdevices_setdata.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_setdata.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_setdata.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_setdata.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunSetData(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
105
apps/aqhome-cgi/modules/devices/mdevices_setdevice.c
Normal file
105
apps/aqhome-cgi/modules/devices/mdevices_setdevice.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_setdevice.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_setdevice.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_setdevice.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunSetDevice(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
245
apps/aqhome-cgi/modules/devices/mdevices_value.c
Normal file
245
apps/aqhome-cgi/modules/devices/mdevices_value.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_value.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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:"<empty>", sValueName?sValueName:"<empty>");
|
||||
|
||||
GBAA(dbuf,"<h1>Value %s/%s</h1>\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, "<table>\n");
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=4h\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=1d\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "&period=1w\"/>");
|
||||
GBAS(dbuf, "</td></tr>");
|
||||
|
||||
GBAS(dbuf, "</table>");
|
||||
}
|
||||
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,"<form action=\"setdata.html\" method=\"post\">\n");
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"device\" value=\"%s\">\n", sDeviceName);
|
||||
GBAA(dbuf, "<input type=\"hidden\" name=\"value\" value=\"%s\">\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,"<input type=\"submit\" name=\"action\" value=\"Send\"/>");
|
||||
GBAS(dbuf, "</form>\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeRgbwToForm(const char *sValueName, uint32_t color, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
#if 1
|
||||
GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"#%08x\"/>", sValueName, color);
|
||||
#else
|
||||
GBAA(dbuf, "<input type=\"color\" name=\"%s\" value=\"#%08x\"/>#%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, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeOnOffAutoToForm(const char *sValueName, int intVal, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GBAA(dbuf, "<select name=\"%s\">" "<option value=\"unchanged\" >unchanged</option>", sValueName);
|
||||
GBAA(dbuf, "<option value=\"off\" %s>off</option>", (intVal==0)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"on\" %s>on</option>", (intVal==1)?"selected":"");
|
||||
GBAA(dbuf, "<option value=\"auto\" %s>auto</option>", (intVal==2)?"selected":"");
|
||||
GBAS(dbuf, "</select>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_value.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_value.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
175
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c
Normal file
175
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_valuesgraph.h"
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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,"<h1>Value %s/%s</h1>\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,"<h1>Values for Device %s</h1>\n", sDeviceName);
|
||||
_writeValueListToTable(sDeviceName, valueList, dbuf);
|
||||
GBAS(dbuf, "\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf,"<p>No values.</p>\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, "<table>\n");
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "4h", dbuf, 0);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1d", dbuf, 0);
|
||||
GBAS(dbuf, "</td></tr><tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1w", dbuf, 0);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "12m", dbuf, 0);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueListToTable(const char *sDeviceName, const AQH_VALUE_LIST *valueList, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const AQH_VALUE *value;
|
||||
|
||||
GBAS(dbuf, "<table>\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, "</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *sValueName;
|
||||
|
||||
/* name */
|
||||
sValueName=AQH_Value_GetName(value);
|
||||
|
||||
GBAS(dbuf, "<tr><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1d", dbuf, 1);
|
||||
GBAS(dbuf, "</td><td>");
|
||||
_addGraphLink(sDeviceName, sValueName, "1w", dbuf, 1);
|
||||
GBAS(dbuf, "</td></tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _addGraphLink(const char *sDeviceName, const char *sValueName, const char *sPeriod, GWEN_BUFFER *dbuf, int withLink)
|
||||
{
|
||||
if (withLink) {
|
||||
GBAS(dbuf, "<a href=\"vgraph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAS(dbuf, "\">");
|
||||
}
|
||||
|
||||
GBAS(dbuf, "<img src=\"graph.html?device=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sDeviceName, dbuf);
|
||||
GBAS(dbuf, "&value=");
|
||||
GWEN_Text_EscapeToBufferTolerant(sValueName, dbuf);
|
||||
GBAA(dbuf, "&period=%s\"", sPeriod);
|
||||
GBAA(dbuf, " alt=\"%s\" width=\"%d\" height=\"%d\"", sValueName, AQH_MODDEVICES_GRAPH_WIDTH, AQH_MODDEVICES_GRAPH_HEIGHT);
|
||||
GBAS(dbuf, "/>");
|
||||
|
||||
if (withLink) {
|
||||
GBAS(dbuf, "</a>");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_valuesgraph.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValuesAsGraph(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
145
apps/aqhome-cgi/modules/devices/mdevices_valuestable.c
Normal file
145
apps/aqhome-cgi/modules/devices/mdevices_valuestable.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_valuestable.h"
|
||||
#include "./mdevices_index.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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,"<h1>Values for Device %s</h1>\n", sDeviceName);
|
||||
_writeValueListToTable(sDeviceName, valueList, perms, dbuf);
|
||||
GBAS(dbuf, "\n");
|
||||
}
|
||||
else {
|
||||
GBAS(dbuf,"<p>No values.</p>\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,
|
||||
"<table class=\"datatable\">\n"
|
||||
"<thead>"
|
||||
"<tr>"
|
||||
"<th>Name</th>"
|
||||
"<th>Type</th>"
|
||||
"<th>Modality</th>"
|
||||
#if 0
|
||||
"<th>Driver</th>"
|
||||
"<th>Device</th>"
|
||||
"<th>Name for System</th>"
|
||||
#endif
|
||||
"</tr>"
|
||||
"</thead>\n"
|
||||
"<tbody>\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,
|
||||
"</tbody>\n"
|
||||
"</table>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeValueToTable(const char *sDeviceName, const AQH_VALUE *value, uint32_t perms, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
GBAS(dbuf, "<tr>");
|
||||
|
||||
/* name for system */
|
||||
s=AQH_Value_GetName(value);
|
||||
if (perms & AQH_MODDEVICES_PERMS_VALUEREAD) {
|
||||
uint32_t pos;
|
||||
|
||||
pos=GWEN_Buffer_GetPos(dbuf);
|
||||
GBAS(dbuf,"<td><a href=\"value.html?device=");
|
||||
GWEN_Text_EscapeToBuffer(sDeviceName, dbuf);
|
||||
GBAS(dbuf,"&value=");
|
||||
GWEN_Text_EscapeToBuffer(s, dbuf);
|
||||
GBAA(dbuf,"\">%s</a></td>", s);
|
||||
}
|
||||
else
|
||||
GBAA(dbuf,"<td>%s</td>", s?s:"");
|
||||
|
||||
s=AQH_ValueType_toString(AQH_Value_GetValueType(value));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
s=AQH_ValueModality_toString(AQH_Value_GetModality(value));
|
||||
GBAA(dbuf, "<td>%s</td>", s?s:"");
|
||||
|
||||
GBAA(dbuf, "</tr>\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_valuestable.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_valuestable.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunValuesAsTable(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
384
apps/aqhome-cgi/modules/devices/mdevices_vgraph.c
Normal file
384
apps/aqhome-cgi/modules/devices/mdevices_vgraph.c
Normal file
@@ -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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdevices_vgraph.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/mdataclient.h"
|
||||
|
||||
#include <aqdiagram/graph/timegraph.h>
|
||||
#include <aqdiagram/graph/w_graph.h>
|
||||
#include <aqdiagram/draw/context_cairo.h>
|
||||
//#include <aqdiagram/data/date.h>
|
||||
//#include <aqdiagram/data/floatingavg.h>
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* 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:"<empty>", sValueName?sValueName:"<empty>");
|
||||
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:"<empty>", sValueName?sValueName:"<empty>",
|
||||
sPeriod?sPeriod:"<empty>");
|
||||
|
||||
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; i<numValues; i++) {
|
||||
AQDG_GRAPH_DATAPAIR *dp;
|
||||
double timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
|
||||
timestamp=(double)(*(dataPoints++));
|
||||
u.i=*(dataPoints++);
|
||||
dp=AQDG_Graph_DataPair_new();
|
||||
AQDG_Graph_DataPair_SetValueX(dp, timestamp);
|
||||
AQDG_Graph_DataPair_SetValueY(dp, u.f);
|
||||
AQDG_Graph_DataPair_List_Add(dp, dpList);
|
||||
}
|
||||
AQDG_Graph_DataPair_List_SortByValueX(dpList, 1);
|
||||
return dpList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const MY_GRAPH_PARAMS *_getParamsByName(const char *s)
|
||||
{
|
||||
const MY_GRAPH_PARAMS *p;
|
||||
|
||||
p=_graphParams;
|
||||
while(p->name) {
|
||||
if (strcasecmp(p->name, s)==0)
|
||||
return p;
|
||||
p++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/devices/mdevices_vgraph.h
Normal file
27
apps/aqhome-cgi/modules/devices/mdevices_vgraph.h
Normal file
@@ -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 <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
void AQH_ModDevices_RunGraphValue(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
#endif
|
||||
BIN
apps/aqhome-cgi/modules/html/pics/cancel.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/cancel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/aqhome-cgi/modules/html/pics/edit.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/edit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 912 B |
BIN
apps/aqhome-cgi/modules/html/pics/graph.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/graph.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/aqhome-cgi/modules/html/pics/minus.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/minus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 B |
BIN
apps/aqhome-cgi/modules/html/pics/ok.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/ok.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1013 B |
BIN
apps/aqhome-cgi/modules/html/pics/plus.png
Normal file
BIN
apps/aqhome-cgi/modules/html/pics/plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 834 B |
63
apps/aqhome-cgi/modules/html/style.css
Normal file
63
apps/aqhome-cgi/modules/html/style.css
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
102
apps/aqhome-cgi/modules/mdataclient.c
Normal file
102
apps/aqhome-cgi/modules/mdataclient.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mdataclient.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AQH_ModDataClient_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModDataClient_HandleRequest(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_MODDATACLIENT_RUN_FN runFn,
|
||||
GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_EVENT_LOOP *eventLoop;
|
||||
AQH_DATACLIENT *dc;
|
||||
int rv;
|
||||
|
||||
rv=AQH_Init();
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
eventLoop=AQH_EventLoop_new();
|
||||
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
|
||||
rv=AQH_DataClient_ReadConfigFile(dc);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error connecting (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (runFn)
|
||||
runFn(m, rq, session, dc, dbuf);
|
||||
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
|
||||
AQH_Fini();
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
apps/aqhome-cgi/modules/mdataclient.h
Normal file
37
apps/aqhome-cgi/modules/mdataclient.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* 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_MDATACLIENT_H
|
||||
#define AQHOME_CGI_MDATACLIENT_H
|
||||
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
typedef void (*AQH_MODDATACLIENT_RUN_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, AQH_DATACLIENT *dc, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
void AQH_ModDataClient_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder);
|
||||
void AQH_ModDataClient_HandleRequest(AQH_MODULE *m,
|
||||
AQCGI_REQUEST *rq,
|
||||
AQH_SESSION *session,
|
||||
AQH_MODDATACLIENT_RUN_FN runFn,
|
||||
GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "./mroot_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
#include "aqhome-cgi/modules/devices/mdevices.h"
|
||||
#include "aqhome-cgi/modules/common/madmin.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
@@ -35,11 +37,12 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
|
||||
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
|
||||
static int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq);
|
||||
static int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq);
|
||||
static AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq);
|
||||
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 int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
static AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -51,7 +54,8 @@ AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
|
||||
m=AQH_ModService_new(sv, baseFolder);
|
||||
m=AQH_Module_new();
|
||||
AQH_ModService_Extend(m, sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
|
||||
@@ -60,69 +64,132 @@ AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder)
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
if (strcasecmp(sModuleName, "devices")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/devices", s?s:".");
|
||||
|
||||
AQH_ModDevices_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
else if (strcasecmp(sModuleName, "admin")==0) {
|
||||
AQH_MODULE *mSub;
|
||||
|
||||
mSub=AQH_Service_LoadModule(sv, sModuleName);
|
||||
if (mSub) {
|
||||
const char *s;
|
||||
GWEN_BUFFER *nbuf;
|
||||
|
||||
nbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
s=AQH_ModService_GetBaseFolder(m);
|
||||
GWEN_Buffer_AppendArgs(nbuf, "%s/devices", s?s:".");
|
||||
|
||||
AQH_ModAdmin_Extend(mSub, AQH_ModService_GetService(m), GWEN_Buffer_GetStart(nbuf));
|
||||
AQH_Module_Tree2_AddChild(m, mSub);
|
||||
GWEN_Buffer_free(nbuf);
|
||||
return mSub;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem)
|
||||
{
|
||||
GWEN_BUFFER *dbuf;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQH_ModService_AddHeader(m, "en", dbuf);
|
||||
|
||||
if (strcasecmp(sLastPathElem, "login")==0)
|
||||
return _handleRqLogin(m, rq);
|
||||
_handleRqLogin(m, rq, dbuf);
|
||||
else if (strcasecmp(sLastPathElem, "signup")==0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
AQCGI_Request_SetResponseCode(rq, 501);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Implemented");
|
||||
}
|
||||
else if (strcasecmp(sLastPathElem, "confirm")==0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
AQCGI_Request_SetResponseCode(rq, 501);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Implemented");
|
||||
}
|
||||
else if (strcasecmp(sLastPathElem, "index.html")==0)
|
||||
_handleRqIndex(m, rq, dbuf);
|
||||
else {
|
||||
AQCGI_SendResponseWithStatus(rq, 404, "Not Found");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
AQCGI_Request_SetResponseCode(rq, 404);
|
||||
AQCGI_Request_SetResponseText(rq, "Not Found");
|
||||
}
|
||||
|
||||
AQH_ModService_AddFooter(m, "en", dbuf);
|
||||
AQCGI_Request_SetBufferResponseBody(rq, dbuf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
|
||||
return AQCGI_SendResponse(rq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
|
||||
return AQH_ModService_RespondWithFile(m, rq, "en", "index.html", dbuf);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
|
||||
rv=AQH_ModService_RespondWithFile(m, rq, "en", "login.html");
|
||||
AQH_ModService_RespondWithFile(m, rq, "en", "login.html", dbuf);
|
||||
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST)
|
||||
rv=_handleRqLoginPost(m, rq);
|
||||
_handleRqLoginPost(m, rq, dbuf);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
|
||||
AQCGI_SendResponseWithStatus(rq, 405, "Method No Allowed");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
AQCGI_Request_SetResponseCode(rq, 405);
|
||||
AQCGI_Request_SetResponseText(rq, "Method Not Allowed");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
AQH_USER *user;
|
||||
AQH_SESSION *session;
|
||||
GWEN_BUFFER *dbuf;
|
||||
GWEN_BUFFER *tbuf;
|
||||
GWEN_TIMESTAMP *ts;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Handling request");
|
||||
sv=AQH_ModService_GetService(m);
|
||||
user=_getAndCheckUser(m, rq);
|
||||
user=_getAndCheckUser(m, rq, dbuf);
|
||||
if (user==NULL) {
|
||||
DBG_INFO(NULL, "here");
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
@@ -132,37 +199,42 @@ int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
rv=AQH_Service_SaveUser(sv, user);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error saving user \"%s\"", AQH_User_GetAlias(user));
|
||||
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
AQH_User_free(user);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* generate session */
|
||||
DBG_ERROR(NULL, "Generating session");
|
||||
dbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
AQCGI_GenerateSessionId(dbuf);
|
||||
tbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
AQCGI_GenerateSessionId(tbuf);
|
||||
session=AQH_Session_new();
|
||||
AQH_Session_SetTimestampCreation(session, ts);
|
||||
AQH_Session_SetTimestampLastAccess(session, ts);
|
||||
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
AQH_Session_SetUserAlias(session, AQH_User_GetAlias(user));
|
||||
rv=AQH_Service_AddSession(sv, session);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error adding session for user \"%s\"", AQH_User_GetAlias(user));
|
||||
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
|
||||
DBG_ERROR(NULL, "Error adding session for user \"%s\" (%d)", AQH_User_GetAlias(user), rv);
|
||||
AQCGI_Request_SetResponseCode(rq, 500);
|
||||
AQCGI_Request_SetResponseText(rq, "Internal Error");
|
||||
AQH_Session_free(session);
|
||||
AQH_User_free(user);
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
/* add Set-Cookie header */
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(dbuf, "Set-Cookie: session=%s; max-age=3600", AQH_Session_GetUid(session));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(dbuf));
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(tbuf, "Set-Cookie: session=%s; max-age=86400", AQH_Session_GetUid(session));
|
||||
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf));
|
||||
GWEN_Buffer_free(tbuf);
|
||||
|
||||
/* finish */
|
||||
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html");
|
||||
AQCGI_Request_SetResponseCode(rq, 303);
|
||||
AQCGI_Request_SetResponseText(rq, "See other");
|
||||
AQH_Session_free(session);
|
||||
AQH_User_free(user);
|
||||
|
||||
@@ -171,7 +243,7 @@ int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
|
||||
|
||||
|
||||
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
GWEN_DB_NODE *dbPost;
|
||||
|
||||
@@ -189,7 +261,8 @@ AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
sPasswd=GWEN_DB_GetCharValue(dbPost, "password", 0, NULL);
|
||||
if (!(sUserName && *sUserName && sPasswd && *sPasswd)) {
|
||||
DBG_ERROR(NULL, "Either user name or password missing");
|
||||
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
|
||||
AQCGI_Request_SetResponseCode(rq, 400);
|
||||
AQCGI_Request_SetResponseText(rq, "Bad Request");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -197,14 +270,16 @@ AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
user=AQH_Service_LoadUser(sv, sUserName);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Loaded user \"%s\"", sUserName);
|
||||
|
||||
if (AQH_User_GetState(user)!=AQH_UserState_Active) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not active", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
@@ -212,16 +287,19 @@ AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
hashedPaswd=AQH_User_GetHashedPassword(user);
|
||||
if (!(hashedPaswd && *hashedPaswd)) {
|
||||
DBG_ERROR(NULL, "User \"%s\" has no hashed password", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQCGI_HashMd256ToBuffer(sPasswd, buf);
|
||||
DBG_ERROR(NULL, "Password: [%s]", sPasswd); // TODO: Remove!!!
|
||||
DBG_ERROR(NULL, "Hashed password: [%s]", GWEN_Buffer_GetStart(buf));
|
||||
if (strcasecmp(GWEN_Buffer_GetStart(buf), hashedPaswd)!=0) {
|
||||
DBG_ERROR(NULL, "Bad password for user \"%s\"", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
|
||||
AQCGI_Request_SetResponseCode(rq, 403);
|
||||
AQCGI_Request_SetResponseText(rq, "Forbidden");
|
||||
GWEN_Buffer_free(buf);
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
@@ -234,6 +312,8 @@ AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
else {
|
||||
DBG_ERROR(NULL, "No POST data");
|
||||
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
|
||||
AQCGI_Request_SetResponseCode(rq, 400);
|
||||
AQCGI_Request_SetResponseText(rq, "Bad Request");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef AQHOME_CGI_MROOT_H
|
||||
#define AQHOME_CGI_MROOT_H
|
||||
|
||||
#include <aqhome-cgi/modules/mservice.h>
|
||||
#include <aqhome-cgi/modules/common/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
|
||||
@@ -1,291 +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 <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "./mservice_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQH_MOD_SERVICE_HEADERFILE "header.html"
|
||||
#define AQH_MOD_SERVICE_FOOTERFILE "footer.html"
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE)
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
m=AQH_Module_new();
|
||||
GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm);
|
||||
GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData);
|
||||
|
||||
xm->service=sv;
|
||||
xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _freeData(GWEN_UNUSED void *bp, void *p)
|
||||
{
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=(AQH_MOD_SERVICE*) p;
|
||||
free(xm->baseFolder);
|
||||
GWEN_FREE_OBJECT(xm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->service;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
return xm->baseFolder;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->handleRequestFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
xm->loadSubModuleFn=fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MODULE *mParent;
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent) {
|
||||
int rv;
|
||||
|
||||
rv=AQH_ModService_AddHeader(mParent, lang, dbuf);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf);
|
||||
}
|
||||
DBG_ERROR(NULL, "Argument missing");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && dbuf) {
|
||||
AQH_MODULE *mParent;
|
||||
int rv;
|
||||
|
||||
rv=AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
mParent=AQH_Module_Tree2_GetParent(m);
|
||||
if (mParent) {
|
||||
int rv;
|
||||
|
||||
rv=AQH_ModService_AddFooter(mParent, lang, dbuf);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Argument missing");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename)
|
||||
{
|
||||
GWEN_BUFFER *buf;
|
||||
int rv;
|
||||
|
||||
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
rv=AQH_ModService_AddHeader(m, lang, buf);
|
||||
if (rv<0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
|
||||
GWEN_Buffer_free(buf);
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, buf);
|
||||
if (rv<0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
|
||||
GWEN_Buffer_free(buf);
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
rv=AQH_ModService_AddFooter(m, lang, buf);
|
||||
if (rv<0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
|
||||
GWEN_Buffer_free(buf);
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
AQCGI_Request_SetBufferResponseBody(rq, buf);
|
||||
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
|
||||
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->handleRequestFn)
|
||||
return xm->handleRequestFn(m, rq, sLastPathElem);
|
||||
}
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
|
||||
{
|
||||
if (m) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm && xm->loadSubModuleFn)
|
||||
return xm->loadSubModuleFn(m, rq, sModuleName);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf)
|
||||
{
|
||||
if (m && filename && dbuf) {
|
||||
AQH_MOD_SERVICE *xm;
|
||||
|
||||
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
|
||||
if (xm) {
|
||||
GWEN_BUFFER *fbuf;
|
||||
int rv;
|
||||
|
||||
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(fbuf, xm->baseFolder);
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en");
|
||||
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Buffer_AppendString(fbuf, filename);
|
||||
DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf));
|
||||
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv);
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return rv;
|
||||
}
|
||||
GWEN_Buffer_free(fbuf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)");
|
||||
return GWEN_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,46 +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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQHOME_CGI_MSERVICE_H
|
||||
#define AQHOME_CGI_MSERVICE_H
|
||||
|
||||
#include <aqhome-cgi/service/module.h>
|
||||
#include <aqhome-cgi/service/service.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
typedef int (*AQH_MODSERVICE_HANDLEREQUEST_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
|
||||
typedef AQH_MODULE* (*AQH_MODSERVICE_LOADSUBMODULE_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m);
|
||||
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m);
|
||||
|
||||
|
||||
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
|
||||
|
||||
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
|
||||
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
|
||||
|
||||
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename);
|
||||
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf);
|
||||
|
||||
|
||||
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn);
|
||||
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
header.html
|
||||
footer.html
|
||||
login.html
|
||||
index.html
|
||||
</data>
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,17 @@
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="martin" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
|
||||
<link rel="stylesheet" href="/style.css" >
|
||||
<title>AqHome</title>
|
||||
</head>
|
||||
|
||||
<ul class="mainmenu" >
|
||||
<li><a href="/aqbt/devices/index.html">Devices</a></li>
|
||||
<li><a href="/aqbt/admin/index.html">Admin</a></li>
|
||||
<li><a href="#news">News</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li style="float:right"><a href="/aqbt/login">Login</a></li>
|
||||
</ul>
|
||||
|
||||
<body>
|
||||
|
||||
|
||||
6
apps/aqhome-cgi/modules/static/en/index.html
Normal file
6
apps/aqhome-cgi/modules/static/en/index.html
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
<h1> AqHome Main Page </h1>
|
||||
|
||||
<p>Nothing to see for now</p>
|
||||
|
||||
63
apps/aqhome-cgi/modules/static/style.css
Normal file
63
apps/aqhome-cgi/modules/static/style.css
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="BUILDING_AQHOME" />
|
||||
<define name="not_BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember</flags>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="flags" type="uint32_t" maxlen="4">
|
||||
@@ -60,7 +60,7 @@
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember</flags>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="descr" type="char_ptr" maxlen="256">
|
||||
|
||||
@@ -31,21 +31,21 @@
|
||||
|
||||
<members>
|
||||
|
||||
<member name="moduleId" type="uint32_t" maxlen="4">
|
||||
<member name="moduleId" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember</flags>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="exclAddPerms" type="uint32_t" maxlen="4">
|
||||
<member name="explAddPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
<member name="exclDelPerms" type="uint32_t" maxlen="4">
|
||||
<member name="explDelPerms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
@@ -59,14 +59,6 @@
|
||||
<flags></flags>
|
||||
</member>
|
||||
|
||||
|
||||
<member name="perms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>volatile</flags>
|
||||
</member>
|
||||
|
||||
</members>
|
||||
|
||||
</type>
|
||||
|
||||
@@ -43,6 +43,13 @@
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="descr" type="char_ptr" maxlen="256">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
</member>
|
||||
|
||||
<member name="perms" type="uint32_t" maxlen="4">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
</lang>
|
||||
|
||||
<defines>
|
||||
<define id="AQH_USER_FLAGS" prefix="AQH_USER_FLAGS_">
|
||||
<item name="ADMIN" value="0x00000001" />
|
||||
</define>
|
||||
|
||||
<define id="AQH_USER_RTFLAGS" prefix="AQH_USER_RTFLAGS_">
|
||||
<item name="MODIFIED" value="0x00000001" />
|
||||
<item name="PERMSCALC" value="0x00000002" />
|
||||
@@ -69,7 +73,7 @@
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>with_getbymember</flags>
|
||||
<flags>with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="flags" type="uint32_t" maxlen="4">
|
||||
@@ -83,21 +87,21 @@
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags></flags>
|
||||
<flags>sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="name" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="alias" type="char_ptr" maxlen="16">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own with_getbymember</flags>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="hashedPassword" type="char_ptr" maxlen="128">
|
||||
@@ -111,7 +115,7 @@
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>own with_getbymember sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="notes" type="char_ptr" maxlen="256">
|
||||
@@ -125,14 +129,14 @@
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="timestampLastLogin" type="gwen_timestamp" maxlen="8">
|
||||
<default>NULL</default>
|
||||
<preset>NULL</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>own sortbymember</flags>
|
||||
</member>
|
||||
|
||||
<member name="modulePermList" type="AQH_MODULE_PERMS_LIST">
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -213,6 +211,9 @@ int _addUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
GWEN_DB_Group_free(db);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing alias");
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -138,10 +138,8 @@ int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
{
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
|
||||
valueId=AQH_Value_GetId(value);
|
||||
if (num==0 || num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES)
|
||||
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES;
|
||||
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, num);
|
||||
if (tablePtr) {
|
||||
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
|
||||
@@ -163,8 +161,6 @@ int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
|
||||
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
|
||||
valueId=AQH_Value_GetId(value);
|
||||
tablePtr=AQH_Storage_GetLastNDataPoints(storage, valueId, num);
|
||||
if (tablePtr) {
|
||||
@@ -187,8 +183,6 @@ int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
|
||||
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
|
||||
valueId=AQH_Value_GetId(value);
|
||||
tablePtr=AQH_Storage_GetFirstNDataPoints(storage, valueId, num);
|
||||
if (tablePtr) {
|
||||
@@ -210,14 +204,28 @@ void _sendDataPointsResponse(AQH_OBJECT *ep,
|
||||
{
|
||||
int numTableEntries;
|
||||
int numDataPoints;
|
||||
AQH_MESSAGE *outMsg;
|
||||
|
||||
numTableEntries=(int)(tablePtr[0]);
|
||||
numDataPoints=numTableEntries/2;
|
||||
outMsg=AQH_IpcdMessageMultiData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
|
||||
AQH_Endpoint_GetNextMessageId(ep), refMsgId,
|
||||
value, &(tablePtr[1]), numDataPoints);
|
||||
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
||||
tablePtr++;
|
||||
|
||||
while(numDataPoints) {
|
||||
AQH_MESSAGE *outMsg;
|
||||
int toSend;
|
||||
uint32_t flags=0;
|
||||
|
||||
toSend=numDataPoints;
|
||||
if (toSend>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
|
||||
toSend=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
|
||||
numDataPoints-=toSend;
|
||||
if (numDataPoints==0)
|
||||
flags|=AQH_MSGDATA_MULTIDATA_FLAGS_LASTMSG;
|
||||
outMsg=AQH_IpcdMessageMultiData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
|
||||
AQH_Endpoint_GetNextMessageId(ep), refMsgId, flags,
|
||||
value, tablePtr, toSend);
|
||||
tablePtr+=(toSend*2);
|
||||
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#include "aqhome/ipc2/endpoint.h"
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getdevices.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_devices.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +40,10 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
static AQH_DEVICE_LIST *_getMatchingDeviceList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList);
|
||||
static int _deviceMatches(const AQH_DEVICE *dev, const char *deviceName);
|
||||
static void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t refMsgId);
|
||||
static void _sendDeviceListMsg(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
|
||||
|
||||
|
||||
@@ -47,63 +52,114 @@ static void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeDataServer_HandleGetDevices(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, GWEN_UNUSED const GWEN_TAG16_LIST *tagList)
|
||||
void AqHomeDataServer_HandleGetDevices(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList)
|
||||
{
|
||||
AQHOME_SERVER *xo;
|
||||
|
||||
xo=AqHomeDataServer_GetServerData(o);
|
||||
if (xo) {
|
||||
const AQH_DEVICE_LIST *origDeviceList;
|
||||
AQH_DEVICE_LIST *deviceList;
|
||||
uint32_t refMsgId;
|
||||
|
||||
refMsgId=AQH_IpcMessage_GetMsgId(msg);
|
||||
|
||||
DBG_INFO(NULL, "HandleGetDevices");
|
||||
origDeviceList=AQH_Storage_GetDeviceList(xo->storage);
|
||||
if (origDeviceList) {
|
||||
DBG_INFO(NULL, "Have a list of %d devices", AQH_Device_List_GetCount(origDeviceList));
|
||||
if (AQH_Device_List_GetCount(origDeviceList)<AQHOMEDATA_DEVICESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending all entries in one message");
|
||||
_sendDeviceList(ep, origDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
|
||||
}
|
||||
else {
|
||||
AQH_DEVICE_LIST *tmpDeviceList;
|
||||
const AQH_DEVICE *v;
|
||||
|
||||
DBG_INFO(NULL, "Sending entries in multiple messages");
|
||||
tmpDeviceList=AQH_Device_List_new();
|
||||
v=AQH_Device_List_First(origDeviceList);
|
||||
while(v) {
|
||||
const AQH_DEVICE *next;
|
||||
AQH_DEVICE *copyOfDevice;
|
||||
|
||||
next=AQH_Device_List_Next(v);
|
||||
copyOfDevice=AQH_Device_dup(v);
|
||||
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceList(ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
|
||||
AQH_Device_List_Clear(tmpDeviceList);
|
||||
}
|
||||
v=next;
|
||||
}
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceList(ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); /* send remaining */
|
||||
}
|
||||
AQH_Device_List_free(tmpDeviceList);
|
||||
}
|
||||
deviceList=_getMatchingDeviceList(xo, tagList);
|
||||
if (deviceList) {
|
||||
_sendDeviceList(ep, deviceList, refMsgId);
|
||||
AQH_Device_List_free(deviceList);
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
_sendDeviceList(ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
|
||||
_sendDeviceListMsg(ep, NULL, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
AQH_DEVICE_LIST *_getMatchingDeviceList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList)
|
||||
{
|
||||
const AQH_DEVICE_LIST *origDeviceList;
|
||||
AQH_DEVICE_LIST *tmpDeviceList=NULL;
|
||||
char *deviceName;
|
||||
|
||||
deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDEVICES_TAGS_DEVICENAME, NULL):NULL;
|
||||
|
||||
origDeviceList=AQH_Storage_GetDeviceList(xo->storage);
|
||||
if (origDeviceList) {
|
||||
const AQH_DEVICE *dev;
|
||||
|
||||
tmpDeviceList=AQH_Device_List_new();
|
||||
dev=AQH_Device_List_First(origDeviceList);
|
||||
while(dev) {
|
||||
if (_deviceMatches(dev, deviceName)) {
|
||||
AQH_DEVICE *copyOfDevice;
|
||||
|
||||
copyOfDevice=AQH_Device_dup(dev);
|
||||
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
|
||||
}
|
||||
dev=AQH_Device_List_Next(dev);
|
||||
}
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)<1) {
|
||||
AQH_Device_List_free(tmpDeviceList);
|
||||
tmpDeviceList=NULL;
|
||||
}
|
||||
}
|
||||
free(deviceName);
|
||||
|
||||
return tmpDeviceList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _deviceMatches(const AQH_DEVICE *dev, const char *deviceName)
|
||||
{
|
||||
if (deviceName && *deviceName) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Device_GetNameForSystem(dev);
|
||||
if (s && *s && GWEN_Text_ComparePattern(s, deviceName, 0)==-1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDeviceList(AQH_OBJECT *ep, const AQH_DEVICE_LIST *deviceList, uint32_t refMsgId)
|
||||
{
|
||||
AQH_DEVICE_LIST *tmpDeviceList;
|
||||
const AQH_DEVICE *dev;
|
||||
|
||||
DBG_INFO(NULL, "Sending entries in multiple messages");
|
||||
tmpDeviceList=AQH_Device_List_new();
|
||||
dev=AQH_Device_List_First(deviceList);
|
||||
while(dev) {
|
||||
const AQH_DEVICE *next;
|
||||
AQH_DEVICE *copyOfDevice;
|
||||
|
||||
next=AQH_Device_List_Next(dev);
|
||||
copyOfDevice=AQH_Device_dup(dev);
|
||||
AQH_Device_List_Add(copyOfDevice, tmpDeviceList);
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)>=AQHOMEDATA_DEVICESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceListMsg(ep, tmpDeviceList, next?0:AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId);
|
||||
AQH_Device_List_Clear(tmpDeviceList);
|
||||
}
|
||||
dev=next;
|
||||
}
|
||||
if (AQH_Device_List_GetCount(tmpDeviceList)) {
|
||||
DBG_INFO(NULL, "Sending %d devices", AQH_Device_List_GetCount(tmpDeviceList));
|
||||
_sendDeviceListMsg(ep, tmpDeviceList, AQH_MSGDATA_DEVICES_FLAGS_LASTMSG, refMsgId); /* send remaining */
|
||||
}
|
||||
AQH_Device_List_free(tmpDeviceList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDeviceListMsg(AQH_OBJECT *ep, const AQH_DEVICE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
{
|
||||
AQH_MESSAGE *msg;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -152,7 +152,7 @@ void _sendDataChangedMsgToAllClients(AQHOME_SERVER *xo, AQH_OBJECT *epSrc, const
|
||||
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Sending update msg to endpoint");
|
||||
msg=AQH_IpcdMessageMultiData_new(AQH_MSGTYPE_IPC_DATA_DATACHANGED,
|
||||
AQH_Endpoint_GetNextMessageId(ep), 0,
|
||||
AQH_Endpoint_GetNextMessageId(ep), 0, 0,
|
||||
v, dataPoints, numValues);
|
||||
AQH_Endpoint_AddMsgOut(ep, msg);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@ static int _handleNewClient(AQH_OBJECT *o, AQH_OBJECT *clientEndpoint);
|
||||
static int _handleClientDown(AQH_OBJECT *o, AQH_OBJECT *clientEndpoint);
|
||||
static void _handleMsgsFromClient(AQH_OBJECT *o, AQHOME_SERVER *xo, AQH_OBJECT *ep);
|
||||
static void _handleMsgFromClient(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg);
|
||||
static void _createValue(AQHOME_SERVER *xo, AQH_OBJECT *epDriver, const char *deviceName, const AQH_VALUE *valueTemplate);
|
||||
static void _updateValue(AQHOME_SERVER *xo, AQH_VALUE *v, const char *deviceName, const AQH_VALUE *valueTemplate);
|
||||
static AQH_DEVICE *_getOrCreateDeviceForDriver(AQHOME_SERVER *xo, AQH_OBJECT *epDriver, const char *deviceName);
|
||||
static int _createPidFile(const char *pidFilename);
|
||||
static int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs);
|
||||
@@ -652,32 +654,16 @@ AQH_VALUE *AqHomeDataServer_GetOrCreateValueForDriverWithTemplate(AQH_OBJECT *o,
|
||||
|
||||
v=AQH_Storage_GetValueByNameForSystem(xo->storage, GWEN_Buffer_GetStart(buf));
|
||||
if (v==NULL) {
|
||||
if (AQH_Endpoint_GetPermissions(epDriver) & AQH_ENDPOINT_PERMS_ADDVALUE) {
|
||||
AQH_DEVICE *device;
|
||||
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Creating value \"%s\"", GWEN_Buffer_GetStart(buf));
|
||||
device=(deviceName && *deviceName)?_getOrCreateDeviceForDriver(xo, epDriver, deviceName):NULL;
|
||||
|
||||
v=AQH_Value_new();
|
||||
AQH_Value_SetDriver(v, serviceName);
|
||||
AQH_Value_SetName(v, AQH_Value_GetName(valueTemplate));
|
||||
AQH_Value_SetNameForSystem(v, GWEN_Buffer_GetStart(buf));
|
||||
AQH_Value_SetValueUnits(v, AQH_Value_GetValueUnits(valueTemplate));
|
||||
AQH_Value_SetValueType(v, AQH_Value_GetValueType(valueTemplate));
|
||||
AQH_Value_SetModality(v, AQH_Value_GetModality(valueTemplate));
|
||||
AQH_Value_SetTimestampCreation(v, (uint64_t) time(NULL));
|
||||
if (device) {
|
||||
AQH_Value_SetDeviceNameForSystem(v, AQH_Device_GetNameForSystem(device));
|
||||
AQH_Value_SetDeviceName(v, AQH_Device_GetName(device));
|
||||
}
|
||||
AQH_Storage_AddValue(xo->storage, v);
|
||||
}
|
||||
if (AQH_Endpoint_GetPermissions(epDriver) & AQH_ENDPOINT_PERMS_ADDVALUE)
|
||||
_createValue(xo, epDriver, GWEN_Buffer_GetStart(buf), valueTemplate);
|
||||
else {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No permissions to create value \"%s\"", GWEN_Buffer_GetStart(buf));
|
||||
GWEN_Buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
_updateValue(xo, v, GWEN_Buffer_GetStart(buf), valueTemplate);
|
||||
GWEN_Buffer_free(buf);
|
||||
return v;
|
||||
}
|
||||
@@ -686,6 +672,75 @@ AQH_VALUE *AqHomeDataServer_GetOrCreateValueForDriverWithTemplate(AQH_OBJECT *o,
|
||||
|
||||
|
||||
|
||||
void _createValue(AQHOME_SERVER *xo, AQH_OBJECT *epDriver, const char *deviceName, const AQH_VALUE *valueTemplate)
|
||||
{
|
||||
AQH_DEVICE *device;
|
||||
const char *serviceName;
|
||||
AQH_VALUE *v;
|
||||
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Creating value \"%s\"", deviceName);
|
||||
serviceName=AQH_Endpoint_GetServiceName(epDriver);
|
||||
device=(deviceName && *deviceName)?_getOrCreateDeviceForDriver(xo, epDriver, deviceName):NULL;
|
||||
|
||||
v=AQH_Value_new();
|
||||
AQH_Value_SetDriver(v, serviceName);
|
||||
AQH_Value_SetName(v, AQH_Value_GetName(valueTemplate));
|
||||
AQH_Value_SetNameForSystem(v, deviceName);
|
||||
AQH_Value_SetValueUnits(v, AQH_Value_GetValueUnits(valueTemplate));
|
||||
AQH_Value_SetValueType(v, AQH_Value_GetValueType(valueTemplate));
|
||||
AQH_Value_SetModality(v, AQH_Value_GetModality(valueTemplate));
|
||||
AQH_Value_SetTimestampCreation(v, (uint64_t) time(NULL));
|
||||
if (device) {
|
||||
AQH_Value_SetDeviceNameForSystem(v, AQH_Device_GetNameForSystem(device));
|
||||
AQH_Value_SetDeviceName(v, AQH_Device_GetName(device));
|
||||
}
|
||||
AQH_Storage_AddValue(xo->storage, v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _updateValue(AQHOME_SERVER *xo, AQH_VALUE *value, const char *deviceName, const AQH_VALUE *valueTemplate)
|
||||
{
|
||||
int chg=0;
|
||||
const char *s1;
|
||||
const char *s2;
|
||||
int i1;
|
||||
int i2;
|
||||
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Updating value \"%s\"", deviceName);
|
||||
s1=AQH_Value_GetValueUnits(valueTemplate);
|
||||
s2=AQH_Value_GetValueUnits(value);
|
||||
if (s1 && *s1) {
|
||||
if (!(s2 && *s2) || (strcasecmp(s1, s2)!=0)) {
|
||||
AQH_Value_SetValueUnits(value, s1);
|
||||
chg=1;
|
||||
}
|
||||
}
|
||||
|
||||
i1=AQH_Value_GetValueType(valueTemplate);
|
||||
i2=AQH_Value_GetValueType(value);
|
||||
if (i1!=AQH_ValueDataType_Unknown) {
|
||||
if (i1!=i2) {
|
||||
AQH_Value_SetValueType(value, i1);
|
||||
chg=1;
|
||||
}
|
||||
}
|
||||
|
||||
i1=AQH_Value_GetModality(valueTemplate);
|
||||
i2=AQH_Value_GetModality(value);
|
||||
if (i1!=AQH_ValueModality_Unknown) {
|
||||
if (i1!=i2) {
|
||||
AQH_Value_SetModality(value, i1);
|
||||
chg=1;
|
||||
}
|
||||
}
|
||||
|
||||
if (chg)
|
||||
AQH_Storage_AddRuntimeFlags(xo->storage, AQH_STORAGE_RTFLAGS_MODIFIED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_DEVICE *_getOrCreateDeviceForDriver(AQHOME_SERVER *xo, AQH_OBJECT *epDriver, const char *deviceName)
|
||||
{
|
||||
const char *serviceName;
|
||||
|
||||
@@ -218,7 +218,7 @@ void _sendMessage(AQH_MQTTLOG_SERVER *xo, const AQHMQTT_DEVICE *device, const AQ
|
||||
AQH_MESSAGE *pubMsg;
|
||||
|
||||
pubMsg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA,
|
||||
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
|
||||
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0, 0,
|
||||
msgValue, now, f);
|
||||
DBG_INFO(AQH_LOGDOMAIN, "BROKER UPDATE_DATA %s/%s: %f",
|
||||
deviceName?deviceName:"<no device name>",
|
||||
|
||||
@@ -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:"<empty>");
|
||||
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:"<empty>");
|
||||
#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;
|
||||
|
||||
@@ -32,18 +32,18 @@
|
||||
|
||||
<members>
|
||||
|
||||
<member name="aqhValue" type="char_ptr" maxlen="128">
|
||||
<member name="aqhValue" type="int" maxlen="8">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>with_getByMember</flags>
|
||||
</member>
|
||||
|
||||
<member name="driverValue" type="char_ptr" maxlen="128">
|
||||
<default>0</default>
|
||||
<preset>0</preset>
|
||||
<access>public</access>
|
||||
<flags>own</flags>
|
||||
<flags>own with_getByMember</flags>
|
||||
</member>
|
||||
|
||||
|
||||
|
||||
@@ -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 <translations> element");
|
||||
DBG_ERROR(NULL, "No <translations> 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 <translation> element");
|
||||
DBG_ERROR(NULL, "Error reading <translation> 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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ void AQH_NodeServer_HandleForward(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSA
|
||||
AQH_Message_SetData(nodeMsg, ptr, len);
|
||||
AQH_Message_SetUsedSize(nodeMsg, len);
|
||||
AQH_Endpoint_AddMsgOut(xo->ttyEndpoint, nodeMsg);
|
||||
AQH_NodeServer_WriteTtyMsgToLogFile(o, nodeMsg, "sending");
|
||||
DBG_ERROR(NULL, "Forwarding node message %d to node", AQH_NodeMessage_GetMsgType(nodeMsg));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -54,7 +54,7 @@ void AQH_NodeServer_HandleGetNodes(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESS
|
||||
AQH_Endpoint_GetNextMessageId(ep), AQH_IpcMessage_GetMsgId(msg),
|
||||
niNext?0:AQH_MSGNODE_GETDEVICES_RSP_FLAGS_LASTMSG, ni);
|
||||
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
||||
DBG_ERROR(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
|
||||
DBG_DEBUG(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
|
||||
ni=niNext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -274,6 +266,7 @@ AQH_MSG_REQUEST *_mkSubRequest_SetData(AQH_OBJECT *o, AQH_NODE_SERVER *xo,
|
||||
AQH_MsgRequest_SetTimestamps(rq, R_SETDATA_SUBREQUEST_EXPIRE_SECS);
|
||||
|
||||
msgOut=AQH_ValueMessage_new(destAddr, xo->nodeAddress, AQH_MSG_TYPE_VALUE_SET, msgId, valueId, dataVal, dataDenom);
|
||||
AQH_NodeServer_WriteTtyMsgToLogFile(o, msgOut, "sending");
|
||||
AQH_Endpoint_AddMsgOut(xo->ttyEndpoint, msgOut);
|
||||
|
||||
return rq;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <aqhome/msg/node/m_value.h>
|
||||
#include <aqhome/msg/node/m_recvstats.h>
|
||||
#include <aqhome/msg/node/m_sendstats.h>
|
||||
#include <aqhome/msg/node/m_memstats.h>
|
||||
#include <aqhome/data/value.h>
|
||||
|
||||
#include <gwenhywfar/args.h>
|
||||
@@ -122,7 +123,9 @@ static void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH
|
||||
static void _forwardValueMessageToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||
static void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||
static void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||
static void _forwardDataFromMemStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||
static void _forwardTtyMsgToClients(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||
static void _publishIntWithIdx(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int idx, int vModality, const char *vUnits, int v);
|
||||
static void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v);
|
||||
static void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, double v);
|
||||
static void _setDeviceName(AQH_VALUE *value, uint32_t uid);
|
||||
@@ -827,9 +830,11 @@ void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAG
|
||||
|
||||
code=AQH_NodeMessage_GetMsgType(msg);
|
||||
switch(code) {
|
||||
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
|
||||
case AQH_MSG_TYPE_COMSENDSTATS: _forwardDataFromSendStatsMsgToBroker(xo, msg); break;
|
||||
case AQH_MSG_TYPE_COMRECVSTATS: _forwardDataFromRecvStatsMsgToBroker(xo, msg); break;
|
||||
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
|
||||
case AQH_MSG_TYPE_COMSENDSTATS: _forwardDataFromSendStatsMsgToBroker(xo, msg); break;
|
||||
case AQH_MSG_TYPE_COMRECVSTATS: _forwardDataFromRecvStatsMsgToBroker(xo, msg); break;
|
||||
case AQH_MSG_TYPE_MEMSTATS: _forwardDataFromMemStatsMsgToBroker(xo, msg); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -898,24 +903,21 @@ void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
|
||||
packetsOutInt=AQH_SendStatsMessage_GetPacketsOut(msg);
|
||||
if (packetsOutInt) {
|
||||
uint32_t uid;
|
||||
double packetsOut;
|
||||
double collisions;
|
||||
double busy;
|
||||
double collisionsPercentage=0.0;
|
||||
double busyPercentage=0.0;
|
||||
int devNum;
|
||||
|
||||
uid=AQH_SendStatsMessage_GetUid(msg);
|
||||
packetsOut=/*(double)*/ packetsOutInt;
|
||||
collisions=/*(double)*/ AQH_SendStatsMessage_GetCollisions(msg);
|
||||
busy=/*(double)*/ AQH_SendStatsMessage_GetBusyErrors(msg);
|
||||
devNum=AQH_SendStatsMessage_GetInterface(msg);
|
||||
|
||||
collisionsPercentage=collisions*100.0/packetsOut;
|
||||
busyPercentage=busy*100.0/packetsOut;
|
||||
|
||||
_publishInt( xo, uid, "net/packetsOut", 0, NULL, packetsOutInt);
|
||||
_publishInt( xo, uid, "net/collisions", 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
||||
_publishDouble(xo, uid, "net/collisionsPercent", 0, "%", collisionsPercentage);
|
||||
_publishDouble(xo, uid, "net/busyPercent", 0, "%", busyPercentage);
|
||||
if (devNum==0) {
|
||||
_publishInt(xo, uid, "net/packetsOut", AQH_ValueModality_Stats, NULL, packetsOutInt);
|
||||
_publishInt(xo, uid, "net/collisions", AQH_ValueModality_Stats, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
||||
_publishInt(xo, uid, "net/busy", AQH_ValueModality_Stats, NULL, (int) AQH_SendStatsMessage_GetBusyErrors(msg));
|
||||
}
|
||||
else {
|
||||
_publishIntWithIdx(xo, uid, "net/packetsOut", devNum, AQH_ValueModality_Stats, NULL, packetsOutInt);
|
||||
_publishIntWithIdx(xo, uid, "net/collisions", devNum, AQH_ValueModality_Stats, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
||||
_publishIntWithIdx(xo, uid, "net/busy", devNum, AQH_ValueModality_Stats, NULL, (int) AQH_SendStatsMessage_GetBusyErrors(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,30 +930,57 @@ void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
|
||||
packetsInInt=AQH_RecvStatsMessage_GetPacketsIn(msg);
|
||||
if (packetsInInt) {
|
||||
uint32_t uid;
|
||||
double packetsIn;
|
||||
double crcErrors;
|
||||
double ioErrors;
|
||||
double crcErrorsPercentage=0.0;
|
||||
double ioErrorsPercentage=0.0;
|
||||
int devNum;
|
||||
int m=AQH_ValueModality_Stats;
|
||||
|
||||
uid=AQH_SendStatsMessage_GetUid(msg);
|
||||
packetsIn=/*(double)*/ packetsInInt;
|
||||
crcErrors=/*(double)*/AQH_RecvStatsMessage_GetCrcErrors(msg);
|
||||
ioErrors=/*(double)*/AQH_RecvStatsMessage_GetIoErrors(msg);
|
||||
uid=AQH_RecvStatsMessage_GetUid(msg);
|
||||
devNum=AQH_RecvStatsMessage_GetInterface(msg);
|
||||
|
||||
crcErrorsPercentage=crcErrors*100.0/packetsIn;
|
||||
ioErrorsPercentage=ioErrors*100.0/packetsIn;
|
||||
|
||||
_publishInt( xo, uid, "net/packetsIn", 0, NULL, packetsInInt);
|
||||
_publishInt( xo, uid, "net/crcerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
||||
_publishInt( xo, uid, "net/ioerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
||||
_publishDouble(xo, uid, "net/crcerrorsPercent", 0, "%", crcErrorsPercentage);
|
||||
_publishDouble(xo, uid, "net/ioerrorsPercent", 0, "%", ioErrorsPercentage);
|
||||
if (devNum==0) {
|
||||
_publishInt(xo, uid, "net/packetsIn", m, NULL, packetsInInt);
|
||||
_publishInt(xo, uid, "net/crcErrors", m, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
||||
_publishInt(xo, uid, "net/ioErrors", m, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
||||
_publishInt(xo, uid, "net/nobufferErrors", m, NULL, (int) AQH_RecvStatsMessage_GetNoBufferErrors(msg));
|
||||
_publishInt(xo, uid, "net/msgSizeErrors", m, NULL, (int) AQH_RecvStatsMessage_GetMsgSizeErrors(msg));
|
||||
_publishInt(xo, uid, "net/missed", m, NULL, (int) AQH_RecvStatsMessage_GetMissed(msg));
|
||||
}
|
||||
else {
|
||||
_publishIntWithIdx(xo, uid, "net/packetsIn", devNum, m, NULL, packetsInInt);
|
||||
_publishIntWithIdx(xo, uid, "net/crcErrors", devNum, m, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
||||
_publishIntWithIdx(xo, uid, "net/ioErrors", devNum, m, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
||||
_publishIntWithIdx(xo, uid, "net/nobufferErrors", devNum, m, NULL, (int) AQH_RecvStatsMessage_GetNoBufferErrors(msg));
|
||||
_publishIntWithIdx(xo, uid, "net/msgSizeErrors", devNum, m, NULL, (int) AQH_RecvStatsMessage_GetMsgSizeErrors(msg));
|
||||
_publishIntWithIdx(xo, uid, "net/missed", devNum, m, NULL, (int) AQH_RecvStatsMessage_GetMissed(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _forwardDataFromMemStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg)
|
||||
{
|
||||
uint32_t uid;
|
||||
|
||||
uid=AQH_MemStatsMessage_GetUid(msg);
|
||||
|
||||
_publishInt( xo, uid, "mem/buffersUsed", AQH_ValueModality_Stats, NULL, AQH_MemStatsMessage_GetBuffersUsed(msg));
|
||||
_publishInt( xo, uid, "mem/maxBuffersUsed", AQH_ValueModality_Stats, NULL, AQH_MemStatsMessage_GetMaxBuffersUsed(msg));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _publishIntWithIdx(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int idx, int vModality, const char *vUnits, int v)
|
||||
{
|
||||
GWEN_BUFFER *tbuf;
|
||||
|
||||
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendArgs(tbuf, "%s%d", vPath, idx);
|
||||
_publishInt(xo, uid, GWEN_Buffer_GetStart(tbuf), vModality, vUnits, v);
|
||||
GWEN_Buffer_free(tbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v)
|
||||
{
|
||||
_publishDouble(xo, uid, vPath, vModality, vUnits, /*(double)*/ v);
|
||||
@@ -980,7 +1009,7 @@ void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vM
|
||||
AQH_MESSAGE *pubMsg;
|
||||
|
||||
pubMsg=AQH_IpcdMessageMultiData_new(AQH_MSGTYPE_IPC_DATA_UPDATEDATA,
|
||||
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0,
|
||||
AQH_Endpoint_GetNextMessageId(xo->brokerEndpoint), 0, 0,
|
||||
value, arrayToSend, 1);
|
||||
if (pubMsg) {
|
||||
DBG_INFO(AQH_LOGDOMAIN,
|
||||
@@ -1017,6 +1046,30 @@ void _setDeviceName(AQH_VALUE *value, uint32_t uid)
|
||||
|
||||
|
||||
|
||||
void AQH_NodeServer_WriteTtyMsgToLogFile(AQH_OBJECT *o, const AQH_MESSAGE *msg, const char *txt)
|
||||
{
|
||||
if (o && msg) {
|
||||
AQH_NODE_SERVER *xo;
|
||||
|
||||
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_NODE_SERVER, o);
|
||||
if (xo && xo->logFile) {
|
||||
GWEN_BUFFER *dbuf;
|
||||
GWEN_TIME *ti;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
ti=GWEN_CurrentTime();
|
||||
GWEN_Time_toString(ti, "YYYY-MM-DD hh:mm:ss ", dbuf);
|
||||
GWEN_Time_free(ti);
|
||||
ti=NULL;
|
||||
AQH_NodeMessage_DumpSpecificToBuffer(msg, dbuf, txt?txt:"");
|
||||
_writeToLogFile(xo->logFile, GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeTtyMsgToLogFile(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg)
|
||||
{
|
||||
if (xo->logFile) {
|
||||
|
||||
@@ -86,6 +86,7 @@ AQH_MSG_REQUEST *AQH_NodeServer_GetRequestTree(const AQH_OBJECT *o);
|
||||
void AQH_NodeServer_AddRequestToTree(AQH_OBJECT *o, AQH_MSG_REQUEST *rq);
|
||||
void AQH_NodeServer_CleanupRequests(AQH_OBJECT *o);
|
||||
|
||||
void AQH_NodeServer_WriteTtyMsgToLogFile(AQH_OBJECT *o, const AQH_MESSAGE *msg, const char *txt);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,15 +26,6 @@
|
||||
|
||||
<unit id="and1" type="and" />
|
||||
|
||||
<unit id="zeroPosNegString1" type="zeroPosNegString">
|
||||
<params>
|
||||
<param name="valueIfNegative">OFF</param>
|
||||
<param name="valueIfZero">OFF</param>
|
||||
<param name="valueIfPositive">ON</param>
|
||||
</params>
|
||||
</unit>
|
||||
|
||||
|
||||
<unit id="valueSetOutPlug1" type="valueSet">
|
||||
<params>
|
||||
<param name="valueName">mqtt/109C2F/power</param>
|
||||
@@ -49,7 +40,6 @@
|
||||
<link sourceUnit=".timer" sourcePort="output" targetUnit="suntime1" targetPort="timer" />
|
||||
<link sourceUnit="suntime1" sourcePort="output" targetUnit="and1" targetPort="input" />
|
||||
<link sourceUnit="delayedOff1" sourcePort="output" targetUnit="and1" targetPort="input" />
|
||||
<link sourceUnit="and1" sourcePort="output" targetUnit="zeroPosNegString1" targetPort="input" />
|
||||
<link sourceUnit="zeroPosNegString1" sourcePort="output" targetUnit="valueSetOutPlug1" targetPort="input" />
|
||||
<link sourceUnit="and1" sourcePort="output" targetUnit="valueSetOutPlug1" targetPort="input" />
|
||||
</links>
|
||||
</network>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</inputPorts>
|
||||
|
||||
<outputPorts>
|
||||
<outputPort name="output" dataType="string" />
|
||||
<outputPort name="output" dataType="double" />
|
||||
</outputPorts>
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqdiagram_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
</includes>
|
||||
@@ -54,6 +55,7 @@
|
||||
|
||||
<libraries>
|
||||
$(gwenhywfar_libs)
|
||||
$(aqdiagram_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
setdata.h
|
||||
moddevice.h
|
||||
watch.h
|
||||
devicestate.h
|
||||
imgperioddata.h
|
||||
</headers>
|
||||
|
||||
<sources>
|
||||
@@ -58,6 +60,8 @@
|
||||
setdata.c
|
||||
moddevice.c
|
||||
watch.c
|
||||
devicestate.c
|
||||
imgperioddata.c
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
|
||||
@@ -197,7 +197,7 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
|
||||
AQH_Value_SetValueUnits(v, valueUnits);
|
||||
AQH_Value_SetDeviceName(v, deviceName);
|
||||
|
||||
msg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, msgId, 0, v, timestampToSend, dataToSend);
|
||||
msg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, msgId, 0, 0, v, timestampToSend, dataToSend);
|
||||
AQH_Value_free(v);
|
||||
GWEN_JsonElement_free(jRoot);
|
||||
return msg;
|
||||
|
||||
264
apps/aqhome-tool/data/devicestate.c
Normal file
264
apps/aqhome-tool/data/devicestate.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "./devicestate.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getdata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
|
||||
|
||||
#include <gwenhywfar/args.h>
|
||||
#include <gwenhywfar/i18n.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define I18S(msg) msg
|
||||
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
|
||||
|
||||
#define A_ARG GWEN_ARGS_FLAGS_HAS_ARGUMENT
|
||||
#define A_END (GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST)
|
||||
#define A_CHAR GWEN_ArgsType_Char
|
||||
#define A_INT GWEN_ArgsType_Int
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _runCommand(AQH_DATACLIENT *dc);
|
||||
static void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device);
|
||||
static void _handleValue(AQH_DATACLIENT *dc, const AQH_VALUE *value);
|
||||
static void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues);
|
||||
static void _printSingleDataPoint(uint64_t timestamp, double data);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
|
||||
{
|
||||
AQH_EVENT_LOOP *eventLoop;
|
||||
AQH_DATACLIENT *dc;
|
||||
int rv;
|
||||
const GWEN_ARGS args[]= {
|
||||
/* flags type name min max s long short_descr, long_descr */
|
||||
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "t", "tcpaddress", I18S("TCP address to connect to [127.0.0.1]"), NULL},
|
||||
{ A_ARG, A_INT, "brokerPort", 0, 1, "P", "tcpport", I18S("Specify the TCP port to listen on"), NULL},
|
||||
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL},
|
||||
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL},
|
||||
{ A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL},
|
||||
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
|
||||
{ A_ARG, A_CHAR, "device", 1, 1, "d", "device", I18S("device name"), NULL},
|
||||
{ A_ARG, A_CHAR, "valueName", 0, 1, "N", "valuename", I18S("Value name for device(e.g. LIGHT)"), NULL},
|
||||
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
|
||||
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
|
||||
};
|
||||
|
||||
eventLoop=AQH_EventLoop_new();
|
||||
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
|
||||
|
||||
rv=AQH_DataClient_ReadLocalArgs(dc, dbGlobalArgs, args, argc, argv);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error connecting (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv=_runCommand(dc);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error running (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _runCommand(AQH_DATACLIENT *dc)
|
||||
{
|
||||
GWEN_DB_NODE *dbLocalArgs;
|
||||
const char *deviceName;
|
||||
AQH_DEVICE_LIST *deviceList;
|
||||
AQH_DEVICE *device;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
deviceName=GWEN_DB_GetCharValue(dbLocalArgs, "device", 0, "*");
|
||||
|
||||
deviceList=AQH_DataClient_GetDevices(dc, deviceName);
|
||||
if (deviceList==NULL) {
|
||||
DBG_ERROR(NULL, "Error getting devices");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
device=AQH_Device_List_First(deviceList);
|
||||
while(device) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Device_GetNameForSystem(device);
|
||||
if (s && *s && -1!=GWEN_Text_ComparePattern(s, deviceName, 0)) {
|
||||
_handleDevice(dc, device);
|
||||
}
|
||||
|
||||
device=AQH_Device_List_Next(device);
|
||||
}
|
||||
|
||||
AQH_Device_List_free(deviceList);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device)
|
||||
{
|
||||
AQH_VALUE_LIST *valueList;
|
||||
const char *devName;
|
||||
const char *roomName;
|
||||
const char *location;
|
||||
const char *descr;
|
||||
|
||||
devName=AQH_Device_GetNameForSystem(device);
|
||||
roomName=AQH_Device_GetRoomName(device);
|
||||
location=AQH_Device_GetLocation(device);
|
||||
descr=AQH_Device_GetDescription(device);
|
||||
|
||||
fprintf(stdout, "%s (room: %s, loc: %s, descr: %s)\n",
|
||||
devName,
|
||||
roomName?roomName:"--",
|
||||
location?location:"--",
|
||||
descr?descr:"--");
|
||||
valueList=AQH_DataClient_GetValues(dc, devName, 0);
|
||||
if (valueList) {
|
||||
const AQH_VALUE *value;
|
||||
|
||||
value=AQH_Value_List_First(valueList);
|
||||
while(value) {
|
||||
if (AQH_Value_GetValueType(value)==AQH_ValueType_Sensor)
|
||||
_handleValue(dc, value);
|
||||
value=AQH_Value_List_Next(value);
|
||||
}
|
||||
}
|
||||
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleValue(AQH_DATACLIENT *dc, const AQH_VALUE *value)
|
||||
{
|
||||
GWEN_DB_NODE *dbLocalArgs;
|
||||
const char *wantedValueName;
|
||||
const char *valueName;
|
||||
int numDataPoints;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
numDataPoints=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 5);
|
||||
wantedValueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, "*");
|
||||
|
||||
valueName=AQH_Value_GetName(value);
|
||||
if (valueName &&
|
||||
-1==GWEN_Text_ComparePattern(valueName, "stats_*", 0) &&
|
||||
-1!=GWEN_Text_ComparePattern(valueName, wantedValueName, 0)) {
|
||||
const char *valueNameForSystem;
|
||||
uint64_t *dataPoints;
|
||||
uint64_t recvdNum;
|
||||
|
||||
valueNameForSystem=AQH_Value_GetNameForSystem(value);
|
||||
fprintf(stdout, " %s: ", valueName?valueName:"<empty>");
|
||||
|
||||
dataPoints=malloc(numDataPoints*sizeof(uint64_t)*2);
|
||||
|
||||
recvdNum=AQH_DataClient_GetLastData(dc, valueNameForSystem, dataPoints, numDataPoints);
|
||||
if (recvdNum>0)
|
||||
_printDataPoints(dataPoints, recvdNum);
|
||||
|
||||
free(dataPoints);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for(i=0; i<numValues; i++) {
|
||||
uint64_t timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
|
||||
if (i)
|
||||
fprintf(stdout, " | ");
|
||||
timestamp=*(dataPoints++);
|
||||
u.i=*(dataPoints++);
|
||||
|
||||
_printSingleDataPoint(timestamp, u.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _printSingleDataPoint(uint64_t timestamp, double data)
|
||||
{
|
||||
GWEN_TIMESTAMP *ts;
|
||||
|
||||
ts=GWEN_Timestamp_fromLocalTime((time_t) timestamp);
|
||||
if (ts)
|
||||
fprintf(stdout, "%lf (%04d/%02d/%02d-%02d:%02d:%02d)",
|
||||
data,
|
||||
GWEN_Timestamp_GetYear(ts),
|
||||
GWEN_Timestamp_GetMonth(ts),
|
||||
GWEN_Timestamp_GetDay(ts),
|
||||
GWEN_Timestamp_GetHour(ts),
|
||||
GWEN_Timestamp_GetMinute(ts),
|
||||
GWEN_Timestamp_GetSecond(ts));
|
||||
else
|
||||
fprintf(stdout, "%lf", data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-tool/data/devicestate.h
Normal file
21
apps/aqhome-tool/data/devicestate.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/****************************************************************************
|
||||
* 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_TOOL_DEVICESTATE_H
|
||||
#define AQHOME_TOOL_DEVICESTATE_H
|
||||
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
|
||||
|
||||
|
||||
int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
299
apps/aqhome-tool/data/imgperioddata.c
Normal file
299
apps/aqhome-tool/data/imgperioddata.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/****************************************************************************
|
||||
* 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 <config.h>
|
||||
#endif
|
||||
|
||||
#include "./imgperioddata.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#include "aqhome/dataclient/client.h"
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getdata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
#include <aqdiagram/graph/timegraph.h>
|
||||
#include <aqdiagram/graph/w_graph.h>
|
||||
#include <aqdiagram/draw/context_cairo.h>
|
||||
#include <aqdiagram/data/date.h>
|
||||
#include <aqdiagram/data/floatingavg.h>
|
||||
|
||||
#include <gwenhywfar/args.h>
|
||||
#include <gwenhywfar/i18n.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define I18S(msg) msg
|
||||
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
|
||||
|
||||
#define A_ARG GWEN_ARGS_FLAGS_HAS_ARGUMENT
|
||||
#define A_END (GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST)
|
||||
#define A_CHAR GWEN_ArgsType_Char
|
||||
#define A_INT GWEN_ArgsType_Int
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int _createGraph(AQH_DATACLIENT *dc);
|
||||
|
||||
static AQDG_GRAPH_DATAPAIR_LIST *_createDataPairListFromDataPoints(const uint64_t *dataPoints, uint64_t numValues);
|
||||
static AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName,
|
||||
uint64_t num, uint64_t tsBegin, uint64_t tsEnd);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Tool_ImgPeriodData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
|
||||
{
|
||||
AQH_EVENT_LOOP *eventLoop;
|
||||
AQH_DATACLIENT *dc;
|
||||
int rv;
|
||||
const GWEN_ARGS args[]= {
|
||||
/* flags type name min max s long short_descr, long_descr */
|
||||
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "t", "tcpaddress", I18S("TCP address to connect to [127.0.0.1]"), NULL},
|
||||
{ A_ARG, A_INT, "brokerPort", 0, 1, "P", "tcpport", I18S("Specify the TCP port to listen on"), NULL},
|
||||
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL},
|
||||
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL},
|
||||
{ A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL},
|
||||
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
|
||||
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
|
||||
{ A_ARG, A_CHAR, "tsBegin", 0, 1, "tb", "tsbegin", I18S("Timestamp range begin"), NULL},
|
||||
{ A_ARG, A_CHAR, "tsEnd", 0, 1, "te", "tsend", I18S("Timestamp range end"), NULL},
|
||||
{ A_ARG, A_CHAR, "imgFile", 1, 1, "F", NULL, I18S("Image path"), NULL},
|
||||
{ A_ARG, A_INT, "imgWidth", 0, 1, "W", NULL, I18S("Image width"), NULL},
|
||||
{ A_ARG, A_INT, "imgHeight", 0, 1, "H", NULL, I18S("Image height"), NULL},
|
||||
{ A_ARG, A_CHAR, "upperLimit", 0, 1, "U", NULL, I18S("Upper limit for y axis"), NULL},
|
||||
{ A_ARG, A_CHAR, "lowerLimit", 0, 1, "L", NULL, I18S("Lower limit for y axis"), NULL},
|
||||
{ A_ARG, A_INT, "precision", 0, 1, "yp", NULL, I18S("Y axis Data Precision (default: 2)"), NULL},
|
||||
{ A_ARG, A_CHAR, "graphTitle", 0, 1, "gt", NULL, I18S("Graph title"), NULL},
|
||||
{ A_ARG, A_CHAR, "curveSpec", 1, 64, "G", NULL, I18S("Curve specification"), NULL},
|
||||
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
|
||||
};
|
||||
|
||||
eventLoop=AQH_EventLoop_new();
|
||||
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
|
||||
|
||||
rv=AQH_DataClient_ReadLocalArgs(dc, dbGlobalArgs, args, argc, argv);
|
||||
if (rv!=0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error connecting (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
rv=_createGraph(dc);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error running (%d)", rv);
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 2;
|
||||
}
|
||||
|
||||
AQH_DataClient_free(dc);
|
||||
AQH_EventLoop_free(eventLoop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _createGraph(AQH_DATACLIENT *dc)
|
||||
{
|
||||
GWEN_DB_NODE *dbLocalArgs;
|
||||
int numDataPoints;
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
const char *imgFile;
|
||||
int imgWidth;
|
||||
int imgHeight;
|
||||
int precision;
|
||||
const char *s;
|
||||
uint32_t tickFlags=0;
|
||||
double upperLimit;
|
||||
double lowerLimit;
|
||||
const char *graphTitle;
|
||||
AQDG_GRAPH *g;
|
||||
AQDG_DRAW_CONTEXT *drawContext;
|
||||
AQDG_OBJECT *graphObject;
|
||||
int i;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
numDataPoints=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 10000); /* remove later */
|
||||
imgFile=GWEN_DB_GetCharValue(dbLocalArgs, "imgFile", 0, NULL);
|
||||
imgWidth=GWEN_DB_GetIntValue(dbLocalArgs, "imgWidth", 0, 800);
|
||||
imgHeight=GWEN_DB_GetIntValue(dbLocalArgs, "imgHeight", 0, 600);
|
||||
precision=GWEN_DB_GetIntValue(dbLocalArgs, "precision", 0, 2);
|
||||
graphTitle=GWEN_DB_GetCharValue(dbLocalArgs, "graphTitle", 0, NULL);
|
||||
|
||||
tsBegin=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbLocalArgs, "tsBegin", 0, NULL));
|
||||
if (tsBegin==(uint64_t) (-1)) {
|
||||
DBG_ERROR(NULL, "Bad begin timestamp");
|
||||
return 1;
|
||||
}
|
||||
tsEnd=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbLocalArgs, "tsEnd", 0, NULL));
|
||||
if (tsEnd==(uint64_t) (-1)) {
|
||||
DBG_ERROR(NULL, "Bad end timestamp");
|
||||
return 1;
|
||||
}
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbLocalArgs, "upperLimit", 0, NULL);
|
||||
if (s && *s) {
|
||||
if (1==sscanf(s, "%lf", &upperLimit))
|
||||
tickFlags|=AQDG_TIMEGRAPH_SETUPTICKS_FLAGS_MAXY;
|
||||
else {
|
||||
fprintf(stderr, "Invalid upperLimit (%s)\n", s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
s=GWEN_DB_GetCharValue(dbLocalArgs, "lowerLimit", 0, NULL);
|
||||
if (s && *s) {
|
||||
if (1==sscanf(s, "%lf", &lowerLimit))
|
||||
tickFlags|=AQDG_TIMEGRAPH_SETUPTICKS_FLAGS_MINY;
|
||||
else {
|
||||
fprintf(stderr, "Invalid lowerLimit (%s)\n", s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
g=AQDG_TimeGraph_new(graphTitle?graphTitle:NULL, NULL, "Value", NULL, precision);
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
const char *curveSpec;
|
||||
|
||||
curveSpec=GWEN_DB_GetCharValue(dbLocalArgs, "curveSpec", i, NULL);
|
||||
if (curveSpec) {
|
||||
GWEN_STRINGLIST *sl;
|
||||
char delim[2];
|
||||
|
||||
delim[0]=curveSpec[0];
|
||||
delim[1]=0;
|
||||
sl=GWEN_StringList_fromString2(curveSpec+1, delim, 0, GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
|
||||
if (sl) {
|
||||
const char *sValue;
|
||||
const char *sLabel;
|
||||
const char *sModifier;
|
||||
|
||||
sValue=GWEN_StringList_StringAt(sl, 0);
|
||||
sLabel=GWEN_StringList_StringAt(sl, 1);
|
||||
sModifier=GWEN_StringList_StringAt(sl, 2);
|
||||
DBG_DEBUG(NULL, "Value: %s, Label: %s, Modifier: %s", sValue?sValue:"", sLabel?sLabel:"", sModifier?sModifier:"");
|
||||
|
||||
if (sValue && *sValue) {
|
||||
AQDG_GRAPH_DATAPAIR_LIST *dpList;
|
||||
|
||||
DBG_DEBUG(NULL, "Requesting data for %s", sValue);
|
||||
dpList=_requestDataPairList(dc, sValue, numDataPoints, tsBegin, tsEnd);
|
||||
if (dpList)
|
||||
AQDG_TimeGraph_ModifyDataAndAddCurve(g, sLabel?sLabel:sValue, sModifier, dpList);
|
||||
}
|
||||
GWEN_StringList_free(sl);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
AQDG_TimeGraph_SetupTicks(g, tickFlags, lowerLimit, upperLimit);
|
||||
|
||||
drawContext=AQDG_Draw_ContextCairo_Png_new(imgFile, 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQDG_GRAPH_DATAPAIR_LIST *_requestDataPairList(AQH_DATACLIENT *dc, const char *valueName,
|
||||
uint64_t num, uint64_t tsBegin, uint64_t tsEnd)
|
||||
{
|
||||
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 {
|
||||
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; i<numValues; i++) {
|
||||
AQDG_GRAPH_DATAPAIR *dp;
|
||||
double timestamp;
|
||||
union {double f; uint64_t i;} u;
|
||||
|
||||
timestamp=(double)(*(dataPoints++));
|
||||
u.i=*(dataPoints++);
|
||||
dp=AQDG_Graph_DataPair_new();
|
||||
AQDG_Graph_DataPair_SetValueX(dp, timestamp);
|
||||
AQDG_Graph_DataPair_SetValueY(dp, u.f);
|
||||
AQDG_Graph_DataPair_List_Add(dp, dpList);
|
||||
}
|
||||
AQDG_Graph_DataPair_List_SortByValueX(dpList, 1);
|
||||
return dpList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-tool/data/imgperioddata.h
Normal file
21
apps/aqhome-tool/data/imgperioddata.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/****************************************************************************
|
||||
* 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_TOOL_IMGPERIODDATA_H
|
||||
#define AQHOME_TOOL_IMGPERIODDATA_H
|
||||
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
|
||||
|
||||
|
||||
int AQH_Tool_ImgPeriodData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "./data/setdata.h"
|
||||
#include "./data/moddevice.h"
|
||||
#include "./data/watch.h"
|
||||
#include "./data/devicestate.h"
|
||||
#include "./data/imgperioddata.h"
|
||||
|
||||
#include <aqhome/api.h>
|
||||
#include <aqhome/aqhome.h>
|
||||
@@ -101,6 +103,8 @@ int main(int argc, char **argv)
|
||||
GWEN_FE_DAH("setdata", AQH_Tool_SetData, I18N("Set data for a value on the data server (e.g. a switch or thermostat)")),
|
||||
GWEN_FE_DAH("moddevice", AQH_Tool_ModDevice, I18N("Modify a device on the data server")),
|
||||
GWEN_FE_DAH("watch", AQH_Tool_Watch, I18N("Watch and print changes of values on the data server")),
|
||||
GWEN_FE_DAH("devicestate", AQH_Tool_DeviceState, I18N("Show state of devices")),
|
||||
GWEN_FE_DAH("imgperioddata", AQH_Tool_ImgPeriodData, I18N("Create diagram of datapoints from a date range")),
|
||||
GWEN_FE_END(),
|
||||
};
|
||||
const GWEN_FUNCS *func;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#define FLASH_TOOL_MAX_REPEAT 16
|
||||
#define FLASH_TOOL_DEFAULT_TIMEOUTINSECS 5
|
||||
#define FLASH_TOOL_WAITFORFLASHREADY_INSECS 30
|
||||
#define FLASH_TOOL_WAITFORFLASHRESPONSE_SECS 2
|
||||
#define FLASH_TOOL_WAITFORFLASHRESPONSE_SECS 1
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -384,11 +384,31 @@ uint64_t Utils_GetTimeStampFromString(const char *s)
|
||||
case 'm': x*=60; break;
|
||||
case 'h': x*=(60*60); break;
|
||||
case 'd': x*=(60*60*24); break;
|
||||
case 'w': x*=(60*60*24*7); break;
|
||||
case 'M': x*=(60*60*24*30); break;
|
||||
case 'y': x*=(60*60*24*365); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return (now-x);
|
||||
}
|
||||
if (*s=='@') {
|
||||
int y, m, d, H, M, S;
|
||||
|
||||
if (6==sscanf(s+1, "%d/%d/%d-%d:%d:%d", &y, &m, &d, &H, &M, &S)) {
|
||||
GWEN_TIMESTAMP *ts;
|
||||
uint64_t x=0;
|
||||
|
||||
ts=GWEN_Timestamp_new(y, m, d, H, M, S);
|
||||
x=GWEN_Timestamp_toTimeT(ts);
|
||||
GWEN_Timestamp_free(ts);
|
||||
return x;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Invalid timespec [%s], expected: @YYYY/MM/DD-HH:MM:SS", s);
|
||||
return (uint64_t) (-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned long int x;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
#export AQHOME_LOGLEVEL=info
|
||||
export AQHOME_LOGLEVEL=info
|
||||
export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
|
||||
|
||||
# 0-build/apps/aqhome-storage/aqhome-storage $*
|
||||
|
||||
@@ -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);
|
||||
@@ -269,6 +273,10 @@ int AQH_ValueModality_fromString(const char *s)
|
||||
return AQH_ValueModality_Stats;
|
||||
else if (strcasecmp(s, "light")==0)
|
||||
return AQH_ValueModality_Light;
|
||||
else if (strcasecmp(s, "onOff")==0)
|
||||
return AQH_ValueModality_OnOff;
|
||||
else if (strcasecmp(s, "onOffAuto")==0)
|
||||
return AQH_ValueModality_OnOffAuto;
|
||||
}
|
||||
return AQH_ValueModality_Unknown;
|
||||
}
|
||||
@@ -288,6 +296,8 @@ const char *AQH_ValueModality_toString(int i)
|
||||
case AQH_ValueModality_TVOC: return "tvoc";
|
||||
case AQH_ValueModality_Stats: return "stats";
|
||||
case AQH_ValueModality_Light: return "light";
|
||||
case AQH_ValueModality_OnOff: return "onOff";
|
||||
case AQH_ValueModality_OnOffAuto: return "onOffAuto";
|
||||
case AQH_ValueModality_Unknown:
|
||||
default: return "unknown";
|
||||
}
|
||||
@@ -463,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) {
|
||||
|
||||
@@ -46,7 +46,9 @@ enum {
|
||||
AQH_ValueModality_Co2,
|
||||
AQH_ValueModality_TVOC,
|
||||
AQH_ValueModality_Stats,
|
||||
AQH_ValueModality_Light
|
||||
AQH_ValueModality_Light,
|
||||
AQH_ValueModality_OnOff,
|
||||
AQH_ValueModality_OnOffAuto
|
||||
};
|
||||
|
||||
|
||||
@@ -82,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
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
|
||||
#define AQH_STORAGE_DATAPOINTS_STEPS 128
|
||||
|
||||
#define AQH_STORAGE_MAXOPENFILES 128
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -410,7 +410,7 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
|
||||
return NULL;
|
||||
}
|
||||
numEntries=AQH_DataFile_GetNumberOfEntries(df);
|
||||
if (maxDataPointsRequested>numEntries)
|
||||
if (maxDataPointsRequested>numEntries || maxDataPointsRequested==0)
|
||||
maxDataPointsRequested=numEntries;
|
||||
arrayLen=(maxDataPointsRequested*2)+1;
|
||||
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
|
||||
@@ -435,7 +435,8 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
|
||||
|
||||
if ((fromTime==0 || ts>=fromTime) && (toTime==0 || ts<=toTime)) {
|
||||
if ((arrayPos+1)>arrayLen) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached (%d, numEntries=%d)",
|
||||
(int) arrayLen, (int) numEntries);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -650,6 +651,16 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error opening/creating datafile for valueId \"%lu\"", (unsigned long int) valueId);
|
||||
return NULL;
|
||||
}
|
||||
if (AQH_DataFile_List_GetCount(sto->dataFileList)>=AQH_STORAGE_MAXOPENFILES) {
|
||||
AQH_DATAFILE *dfLast;
|
||||
|
||||
dfLast=AQH_DataFile_List_Last(sto->dataFileList);
|
||||
if (dfLast) {
|
||||
AQH_DataFile_Close(dfLast);
|
||||
AQH_DataFile_List_Del(dfLast);
|
||||
AQH_DataFile_free(dfLast);
|
||||
}
|
||||
}
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Adding datafile for valueId \"%lu\" to list", (unsigned long int) valueId);
|
||||
AQH_DataFile_List_Add(df, sto->dataFileList);
|
||||
}
|
||||
@@ -661,8 +672,17 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
|
||||
|
||||
AQH_DATAFILE *_findDataFileByValueId(const AQH_STORAGE *sto, uint64_t valueId)
|
||||
{
|
||||
if (sto && sto->dataFileList)
|
||||
return AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
|
||||
if (sto && sto->dataFileList) {
|
||||
AQH_DATAFILE *df;
|
||||
|
||||
df=AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
|
||||
if (df) {
|
||||
/* move to front of list */
|
||||
AQH_DataFile_List_Del(df);
|
||||
AQH_DataFile_List_Insert(df, sto->dataFileList);
|
||||
return df;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_devices.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_values.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getdevices.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getdata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_setdata.h"
|
||||
@@ -113,6 +114,21 @@ int AQH_DataClient_ReadLocalArgs(AQH_DATACLIENT *dc,
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_ReadConfigFile(AQH_DATACLIENT *dc)
|
||||
{
|
||||
GWEN_DB_NODE *dbConfig;
|
||||
|
||||
dbConfig=AQH_LoadConfigFile();
|
||||
if (dbConfig) {
|
||||
GWEN_DB_Group_free(dc->dbLocalArgs);
|
||||
dc->dbLocalArgs=dbConfig;
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_DB_NODE *AQH_DataClient_GetDbLocalArgs(const AQH_DATACLIENT *dc)
|
||||
{
|
||||
return dc?dc->dbLocalArgs:NULL;
|
||||
@@ -173,7 +189,7 @@ void AQH_DataClient_SetTimeout(AQH_DATACLIENT *dc, int i)
|
||||
|
||||
|
||||
|
||||
AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc)
|
||||
AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc, const char *deviceName)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
@@ -183,7 +199,7 @@ AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc)
|
||||
|
||||
fullDeviceList=AQH_Device_List_new();
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcMessage_new(dc->protoId, dc->protoVer, AQH_MSGTYPE_IPC_DATA_GETDEVICES_REQ, msgId, 0, 0, NULL);
|
||||
msgOut=AQH_IpcdMessageGetDevices_new(AQH_MSGTYPE_IPC_DATA_GETDEVICES_REQ, msgId, 0, deviceName);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
|
||||
@@ -327,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;
|
||||
@@ -352,7 +368,25 @@ int AQH_DataClient_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t t
|
||||
uint32_t msgId;
|
||||
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, msgId, 0, v, timeStamp, dataPoint);
|
||||
msgOut=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, msgId, 0, 0, v, timeStamp, dataPoint);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
return _handleResult(dc, msgId);
|
||||
}
|
||||
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
@@ -445,7 +479,9 @@ uint64_t _handleDataResponses(AQH_DATACLIENT *dc, uint64_t *dataPtr, uint64_t ma
|
||||
if (code==AQH_MSGTYPE_IPC_DATA_GETDATA_RSP) {
|
||||
const uint64_t *recvDataPtr;
|
||||
uint64_t recvNumberOfPoints;
|
||||
uint32_t flags;
|
||||
|
||||
flags=AQH_IpcdMessageMultiData_GetFlags(tagList);
|
||||
AQH_IpcdMessageMultiData_ReadDatapoints(tagList, &recvDataPtr, &recvNumberOfPoints);
|
||||
if (recvNumberOfPoints) {
|
||||
uint64_t i;
|
||||
@@ -462,12 +498,14 @@ uint64_t _handleDataResponses(AQH_DATACLIENT *dc, uint64_t *dataPtr, uint64_t ma
|
||||
}
|
||||
}
|
||||
}
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
break;
|
||||
if (flags & AQH_MSGDATA_MULTIDATA_FLAGS_LASTMSG) {
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (code==AQH_MSGTYPE_IPC_DATA_RESULT) {
|
||||
DBG_ERROR(NULL, "Server Error: %d", AQH_IpcMessageResult_GetResult(tagList));
|
||||
DBG_INFO(NULL, "Server Error: %d", AQH_IpcMessageResult_GetResult(tagList));
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
return 0;
|
||||
@@ -538,7 +576,7 @@ int AQH_DataClient_ConnectWithArgs(AQH_DATACLIENT *dc, uint32_t flags)
|
||||
|
||||
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "brokerPort", 0, -1);
|
||||
if (brokerPort<0)
|
||||
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "ConfigFile/brokerPort", 0, 45456);
|
||||
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "ConfigFile/brokerPort", 0, 1899);
|
||||
|
||||
userId=GWEN_DB_GetCharValue(dc->dbLocalArgs, "userId", 0, NULL);
|
||||
passwd=GWEN_DB_GetCharValue(dc->dbLocalArgs, "password", 0, NULL);
|
||||
|
||||
@@ -34,7 +34,7 @@ AQHOME_API int AQH_DataClient_Connect(AQH_DATACLIENT *dc,
|
||||
AQHOME_API int AQH_DataClient_Disconnect(AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
AQHOME_API AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc);
|
||||
AQHOME_API AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc, const char *deviceName);
|
||||
AQHOME_API AQH_VALUE_LIST *AQH_DataClient_GetValues(AQH_DATACLIENT *dc, const char *deviceName, int modality);
|
||||
|
||||
AQHOME_API uint64_t AQH_DataClient_GetFirstData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum);
|
||||
@@ -43,13 +43,16 @@ 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,
|
||||
GWEN_DB_NODE *dbGlobalArgs, const GWEN_ARGS *argDescrs,
|
||||
int argc, char **argv);
|
||||
AQHOME_API int AQH_DataClient_ReadConfigFile(AQH_DATACLIENT *dc);
|
||||
|
||||
AQHOME_API int AQH_DataClient_ConnectWithArgs(AQH_DATACLIENT *dc, uint32_t flags);
|
||||
AQHOME_API GWEN_DB_NODE *AQH_DataClient_GetDbLocalArgs(const AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user