Compare commits
75 Commits
1.0.2-alph
...
mp-2025_06
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
439e787d37 | ||
|
|
d242d63c2e | ||
|
|
86982d0000 | ||
|
|
f549ef5d27 | ||
|
|
fe2eaafb7b | ||
|
|
caf149fe8b | ||
|
|
c540135705 | ||
|
|
734c237666 | ||
|
|
85d445ec61 | ||
|
|
b059f4a56e | ||
|
|
b56ab22117 | ||
|
|
5bda393b10 | ||
|
|
4ad508eca6 | ||
|
|
7f856dacf6 | ||
|
|
b6ba56a564 | ||
|
|
f930b846c2 | ||
|
|
fc5394a5c9 | ||
|
|
725ff96425 | ||
|
|
bfd0cd77a9 | ||
|
|
548a7634b7 | ||
|
|
3e4637e174 | ||
|
|
20b7c3f50d | ||
|
|
9206341032 | ||
|
|
6383d18e0e | ||
|
|
cfc7dc6320 | ||
|
|
72acef3aaf | ||
|
|
850975a85b | ||
|
|
68ee246216 | ||
|
|
2ba802bb06 | ||
|
|
688129cf08 | ||
|
|
81721ab7eb | ||
|
|
bf50871208 | ||
|
|
cbf88e05fe | ||
|
|
a808450fa2 | ||
|
|
033b7cd4db | ||
|
|
cd6a918533 | ||
|
|
63ebcbadc9 | ||
|
|
b2802a37aa | ||
|
|
1e95b317bf | ||
|
|
78fec171f9 | ||
|
|
8bfaabcf27 | ||
|
|
2b08847cf7 | ||
|
|
9ea722607f | ||
|
|
409155f0d0 | ||
|
|
026a943648 | ||
|
|
aeb6df5685 | ||
|
|
06886e0094 | ||
|
|
b498a445b2 | ||
|
|
876e9ac7b9 | ||
|
|
a89b875872 | ||
|
|
0ce70e48b1 | ||
|
|
bf583a1aa5 | ||
|
|
1533f82ec4 | ||
|
|
8a43bc252f | ||
|
|
ffcc5c0d9f | ||
|
|
c51043d72a | ||
|
|
2cb534df85 | ||
|
|
4f30623f2d | ||
|
|
b9ac7c65fa | ||
|
|
cef487fb3a | ||
|
|
284539fd52 | ||
|
|
08a1313ba5 | ||
|
|
7349014bd6 | ||
|
|
12cfe2ff4b | ||
|
|
ae1892f196 | ||
|
|
dbad237826 | ||
|
|
56e222a97e | ||
|
|
888792a201 | ||
|
|
41867ed01a | ||
|
|
b82e0d02df | ||
|
|
cd1fce313e | ||
|
|
5153bd2f69 | ||
|
|
d4ad6844e3 | ||
|
|
4f610c68a2 | ||
|
|
3582659018 |
5
0BUILD
5
0BUILD
@@ -2,7 +2,7 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<project name="aqhome" version="0.0.10" so_current="0" so_age="0" so_revision="10" write_config_h="TRUE">
|
||||
<project name="aqhome" version="0.0.11" so_current="0" so_age="0" so_revision="11" write_config_h="TRUE">
|
||||
<setVar name="package">$(project_name)</setVar>
|
||||
<setVar name="version">
|
||||
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
|
||||
@@ -51,6 +51,8 @@
|
||||
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
|
||||
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
|
||||
|
||||
<setVar name="httpdatadir">/var/www</setVar>
|
||||
|
||||
<option id="enable_testcode" type="string">
|
||||
<default>TRUE</default>
|
||||
<choices>TRUE FALSE</choices>
|
||||
@@ -126,6 +128,7 @@
|
||||
</option>
|
||||
|
||||
|
||||
|
||||
<checkheaders>
|
||||
signal.h
|
||||
sys/stat.h
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<gwbuild>
|
||||
|
||||
|
||||
<target type="Program" name="aqhome-cgi" install="$(sbindir)" >
|
||||
<target type="Program" name="aqhome-cgi" install="$(libdir)/cgi-bin" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
@@ -55,6 +55,7 @@
|
||||
<libraries>
|
||||
$(gwenhywfar_libs)
|
||||
-lm
|
||||
$(aqcgi_libs)
|
||||
</libraries>
|
||||
|
||||
<subdirs>
|
||||
@@ -117,6 +118,7 @@
|
||||
<useTargets>
|
||||
aqhome
|
||||
aqhcgi_service
|
||||
aqhcgi_modules
|
||||
</useTargets>
|
||||
|
||||
<libraries>
|
||||
@@ -127,6 +129,7 @@
|
||||
|
||||
<subdirs>
|
||||
service
|
||||
modules
|
||||
</subdirs>
|
||||
|
||||
|
||||
|
||||
23
apps/aqhome-cgi/README
Normal file
23
apps/aqhome-cgi/README
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
Modules:
|
||||
- login
|
||||
- signup
|
||||
- main
|
||||
- devices
|
||||
- list
|
||||
- show?name="nodes/12345678"
|
||||
- add
|
||||
- edit
|
||||
- delete
|
||||
- values
|
||||
- rooms
|
||||
|
||||
- users
|
||||
- list
|
||||
- show?alias="admin"
|
||||
- add
|
||||
- edit
|
||||
- delete
|
||||
|
||||
- dashboards
|
||||
@@ -1,11 +1,181 @@
|
||||
|
||||
|
||||
#include "./service_file.h"
|
||||
#include "aqhome-cgi/modules/mroot.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
|
||||
#include <aqcgi/cgi.h>
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/gwenhywfar.h>
|
||||
#include <gwenhywfar/nogui.h>
|
||||
#include <gwenhywfar/logger.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
|
||||
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);
|
||||
static void logStart(void);
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GWEN_GUI *gui;
|
||||
AQCGI_REQUEST *rq;
|
||||
|
||||
GWEN_Init();
|
||||
gui=GWEN_NoGui_new();
|
||||
GWEN_Gui_SetGui(gui);
|
||||
|
||||
logStart();
|
||||
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(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(NULL, GWEN_LoggerLevel_Debug);
|
||||
|
||||
rq=AQCGI_ReadRequest();
|
||||
if (rq) {
|
||||
const char *sPathStaticFiles;
|
||||
const char *sPathRuntimeFiles;
|
||||
|
||||
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;
|
||||
|
||||
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles);
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "Content-type: text/plain\n\n");
|
||||
fprintf(stdout, "Error: No Request!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
AQCGI_Fini();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
int rv;
|
||||
|
||||
sv=AQH_ServiceFiles_new(sPathRuntimeFiles);
|
||||
|
||||
rv=_handlePath(sv, rq, sPathStaticFiles);
|
||||
if (rv<0) {
|
||||
}
|
||||
AQH_Service_free(sv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles)
|
||||
{
|
||||
AQH_MODULE *mRoot;
|
||||
AQH_MODULE *mParent;
|
||||
const GWEN_STRINGLIST *sl;
|
||||
|
||||
mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
|
||||
mParent=mRoot;
|
||||
|
||||
sl=AQCGI_Request_GetStringlistPath(rq);
|
||||
if (sl) {
|
||||
GWEN_STRINGLISTENTRY *se;
|
||||
|
||||
se=GWEN_StringList_FirstEntry(sl);
|
||||
while(se) {
|
||||
GWEN_STRINGLISTENTRY *seNext;
|
||||
const char *s;
|
||||
|
||||
seNext=GWEN_StringListEntry_Next(se);
|
||||
s=GWEN_StringListEntry_Data(se);
|
||||
if (s && *s) {
|
||||
if (seNext) {
|
||||
AQH_MODULE *m;
|
||||
|
||||
DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
|
||||
m=AQH_ModService_LoadSubModule(mParent, rq, s);
|
||||
if (m==NULL) {
|
||||
AQH_Module_free(mRoot);
|
||||
AQCGI_SendResponseWithStatus(rq, 404, "Not found");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
mParent=m;
|
||||
}
|
||||
else {
|
||||
int rv;
|
||||
|
||||
/* last, let module handle remaining part */
|
||||
rv=AQH_ModService_HandleRequest(mParent, rq, s);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQH_Module_free(mRoot);
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
se=seNext;
|
||||
}
|
||||
AQH_Module_free(mRoot);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
AQH_Module_free(mRoot);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void logStart()
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f=fopen(AQHOME_CGI_LOGFILE, "a+");
|
||||
if (f!=NULL) {
|
||||
fprintf(f, "Started.\n");
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
84
apps/aqhome-cgi/modules/0BUILD
Normal file
84
apps/aqhome-cgi/modules/0BUILD
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhcgi_modules" >
|
||||
|
||||
<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="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
|
||||
mroot.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
mservice_p.h
|
||||
mroot_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
mservice.c
|
||||
mroot.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
static
|
||||
</subdirs>
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
246
apps/aqhome-cgi/modules/mroot.c
Normal file
246
apps/aqhome-cgi/modules/mroot.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
* 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 "./mroot_p.h"
|
||||
|
||||
#include "aqhome-cgi/service/module.h"
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* defs and enums
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* global vars
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder)
|
||||
{
|
||||
AQH_MODULE *m;
|
||||
|
||||
m=AQH_ModService_new(sv, baseFolder);
|
||||
AQH_ModService_SetHandleRequestFn(m, _handleRequest);
|
||||
AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
|
||||
{
|
||||
if (strcasecmp(sLastPathElem, "login")==0)
|
||||
return _handleRqLogin(m, rq);
|
||||
else if (strcasecmp(sLastPathElem, "signup")==0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (strcasecmp(sLastPathElem, "confirm")==0) {
|
||||
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
else {
|
||||
AQCGI_SendResponseWithStatus(rq, 404, "Not Found");
|
||||
return GWEN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
|
||||
rv=AQH_ModService_RespondWithFile(m, rq, "en", "login.html");
|
||||
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST)
|
||||
rv=_handleRqLoginPost(m, rq);
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
{
|
||||
AQH_SERVICE *sv;
|
||||
AQH_USER *user;
|
||||
AQH_SESSION *session;
|
||||
GWEN_BUFFER *dbuf;
|
||||
GWEN_TIMESTAMP *ts;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Handling request");
|
||||
sv=AQH_ModService_GetService(m);
|
||||
user=_getAndCheckUser(m, rq);
|
||||
if (user==NULL) {
|
||||
DBG_INFO(NULL, "here");
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
ts=GWEN_Timestamp_NowInLocalTime();
|
||||
AQH_User_SetTimestampLastLogin(user, ts);
|
||||
DBG_ERROR(NULL, "Saving user");
|
||||
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");
|
||||
AQH_User_free(user);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* generate session */
|
||||
DBG_ERROR(NULL, "Generating session");
|
||||
dbuf=GWEN_Buffer_new(0, 64, 0, 1);
|
||||
AQCGI_GenerateSessionId(dbuf);
|
||||
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_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");
|
||||
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));
|
||||
|
||||
/* finish */
|
||||
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
|
||||
AQH_Session_free(session);
|
||||
AQH_User_free(user);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
|
||||
{
|
||||
GWEN_DB_NODE *dbPost;
|
||||
|
||||
dbPost=AQCGI_Request_GetDbPostBody(rq);
|
||||
if (dbPost) {
|
||||
AQH_SERVICE *sv;
|
||||
const char *sUserName;
|
||||
const char *sPasswd;
|
||||
AQH_USER *user;
|
||||
const char *hashedPaswd;
|
||||
GWEN_BUFFER *buf;
|
||||
|
||||
sv=AQH_ModService_GetService(m);
|
||||
sUserName=GWEN_DB_GetCharValue(dbPost, "userid", 0, NULL);
|
||||
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");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Loading user \"%s\" (%p)", sUserName, sv);
|
||||
user=AQH_Service_LoadUser(sv, sUserName);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "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");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashedPaswd=AQH_User_GetHashedPassword(user);
|
||||
if (!(hashedPaswd && *hashedPaswd)) {
|
||||
DBG_ERROR(NULL, "User \"%s\" has no hashed password", sUserName);
|
||||
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
AQCGI_HashMd256ToBuffer(sPasswd, buf);
|
||||
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");
|
||||
GWEN_Buffer_free(buf);
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(buf);
|
||||
|
||||
DBG_ERROR(NULL, "User \"%s\" accepted", sUserName);
|
||||
return user;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "No POST data");
|
||||
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
27
apps/aqhome-cgi/modules/mroot.h
Normal file
27
apps/aqhome-cgi/modules/mroot.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_MROOT_H
|
||||
#define AQHOME_CGI_MROOT_H
|
||||
|
||||
#include <aqhome-cgi/modules/mservice.h>
|
||||
|
||||
#include <aqcgi/request.h>
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_new(AQH_SERVICE *sv, const char *baseFolder);
|
||||
|
||||
AQH_MODULE *AQH_ModRoot_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
|
||||
int AQH_ModRoot_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
18
apps/aqhome-cgi/modules/mroot_p.h
Normal file
18
apps/aqhome-cgi/modules/mroot_p.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/****************************************************************************
|
||||
* 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_MROOT_P_H
|
||||
#define AQHOME_CGI_MROOT_P_H
|
||||
|
||||
#include "aqhome-cgi/modules/mroot.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
291
apps/aqhome-cgi/modules/mservice.c
Normal file
291
apps/aqhome-cgi/modules/mservice.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/****************************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
46
apps/aqhome-cgi/modules/mservice.h
Normal file
46
apps/aqhome-cgi/modules/mservice.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* 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
|
||||
|
||||
27
apps/aqhome-cgi/modules/mservice_p.h
Normal file
27
apps/aqhome-cgi/modules/mservice_p.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_MSERVICE_P_H
|
||||
#define AQHOME_CGI_MSERVICE_P_H
|
||||
|
||||
#include "aqhome-cgi/modules/mservice.h"
|
||||
|
||||
|
||||
typedef struct AQH_MOD_SERVICE AQH_MOD_SERVICE;
|
||||
struct AQH_MOD_SERVICE {
|
||||
AQH_SERVICE *service;
|
||||
char *baseFolder;
|
||||
|
||||
AQH_MODSERVICE_HANDLEREQUEST_FN handleRequestFn;
|
||||
AQH_MODSERVICE_LOADSUBMODULE_FN loadSubModuleFn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
7
apps/aqhome-cgi/modules/static/0BUILD
Normal file
7
apps/aqhome-cgi/modules/static/0BUILD
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
<subdirs>
|
||||
en
|
||||
</subdirs>
|
||||
</gwbuild>
|
||||
13
apps/aqhome-cgi/modules/static/en/0BUILD
Normal file
13
apps/aqhome-cgi/modules/static/en/0BUILD
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<data dist="true" install="$(httpdatadir)/aqhome-cgi/static/en">
|
||||
header.html
|
||||
footer.html
|
||||
login.html
|
||||
</data>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
4
apps/aqhome-cgi/modules/static/en/footer.html
Normal file
4
apps/aqhome-cgi/modules/static/en/footer.html
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
17
apps/aqhome-cgi/modules/static/en/header.html
Normal file
17
apps/aqhome-cgi/modules/static/en/header.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- copyright (c) 2025 by martin@libchipcard.de -->
|
||||
<meta name="generator" content="FTE 1.1" />
|
||||
<meta name="revised" content="martin,2025-06-12" />
|
||||
<meta name="keywords" content="" />
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="martin" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>AqHome</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
25
apps/aqhome-cgi/modules/static/en/login.html
Normal file
25
apps/aqhome-cgi/modules/static/en/login.html
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
<div class="main">
|
||||
<h1>AqHome</h1>
|
||||
<h3>Enter your login credentials</h3>
|
||||
|
||||
<form action="login" method="post">
|
||||
<label for="userid">Username:</label>
|
||||
<input type="text" id="userid" name="userid" placeholder="Enter your Username" required>
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" placeholder="Enter your Password" required>
|
||||
|
||||
<div class="wrap">
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p>Not registered?
|
||||
<a href="signup" style="text-decoration: none;">
|
||||
Create an account
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -54,6 +54,10 @@
|
||||
<descr>Waiting for approval by admin</descr>
|
||||
</item>
|
||||
|
||||
<item name="active">
|
||||
<descr>User active</descr>
|
||||
</item>
|
||||
|
||||
</enum>
|
||||
|
||||
</enums>
|
||||
|
||||
@@ -70,6 +70,8 @@ static int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *s
|
||||
static int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
|
||||
static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName);
|
||||
|
||||
//static void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -169,6 +171,9 @@ int _saveUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
//_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||
|
||||
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
@@ -414,6 +419,7 @@ GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv)
|
||||
|
||||
GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
|
||||
{
|
||||
DBG_ERROR(NULL, "Lock and load group %s/%s", groupName, subGroupName);
|
||||
if (sv && groupName && subGroupName) {
|
||||
AQH_SERVICE_FILE *xs;
|
||||
|
||||
@@ -422,17 +428,20 @@ GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const cha
|
||||
GWEN_DB_NODE *db=NULL;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
return NULL;
|
||||
}
|
||||
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
@@ -442,6 +451,9 @@ GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const cha
|
||||
return db;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Missing argument");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -454,25 +466,26 @@ int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGrou
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
GWEN_DB_NODE *db=NULL;
|
||||
int rv;
|
||||
|
||||
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -491,7 +504,6 @@ int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroup
|
||||
|
||||
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||
if (xs) {
|
||||
GWEN_DB_NODE *db=NULL;
|
||||
int rv;
|
||||
|
||||
rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName);
|
||||
@@ -515,7 +527,6 @@ int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroup
|
||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -577,3 +588,24 @@ GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db)
|
||||
{
|
||||
if (db) {
|
||||
GWEN_BUFFER *dbuf;
|
||||
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_DB_WriteToBuffer(db, dbuf, GWEN_DB_FLAGS_DEFAULT);
|
||||
DBG_ERROR(NULL, "Group %s/%s:\n%s", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>",
|
||||
GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Group %s/%s empty", groupName?groupName:"<empty>", subGroupName?subGroupName:"<empty>");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "aqhome-cgi/service/service.h"
|
||||
|
||||
|
||||
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -33,8 +33,8 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 1024
|
||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 512
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -44,13 +44,15 @@
|
||||
|
||||
static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value,
|
||||
int mode,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
|
||||
static int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||
uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
|
||||
static int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
|
||||
static void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||
uint32_t refMsgId);
|
||||
static void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint32_t refMsgId);
|
||||
|
||||
|
||||
|
||||
@@ -79,16 +81,18 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
uint64_t numRequested;
|
||||
int mode;
|
||||
|
||||
tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
|
||||
tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0);
|
||||
numRequested=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_NUM, 0);
|
||||
mode=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, AQH_MSGDATA_GETDATA_MODE_FIRST);
|
||||
|
||||
value=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName);
|
||||
if (value) {
|
||||
int resultCode;
|
||||
|
||||
resultCode=_getAndSendDataPoints(xo->storage, ep, value, tsBegin, tsEnd, numRequested, refMsgId);
|
||||
resultCode=_getAndSendDataPoints(xo->storage, ep, value, mode, tsBegin, tsEnd, numRequested, refMsgId);
|
||||
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
|
||||
}
|
||||
else {
|
||||
@@ -114,30 +118,31 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
|
||||
|
||||
int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value,
|
||||
int mode,
|
||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
if (num==0)
|
||||
return _getAndSendDataPointsNoNum(storage, ep, value, tsBegin, tsEnd, refMsgId);
|
||||
else if (num==1) {
|
||||
_getAndSendLastDatapoint(storage, ep, value, refMsgId);
|
||||
return AQH_MSGDATA_RESULT_SUCCESS;
|
||||
switch(mode) {
|
||||
case AQH_MSGDATA_GETDATA_MODE_FIRST: return _getAndSendDataPointsFirst(storage, ep, value, num, refMsgId);
|
||||
case AQH_MSGDATA_GETDATA_MODE_PERIOD: return _getAndSendDataPointsPeriod(storage, ep, value, tsBegin, tsEnd, num, refMsgId);
|
||||
default:
|
||||
case AQH_MSGDATA_GETDATA_MODE_LAST: return _getAndSendDataPointsLast(storage, ep, value, num, refMsgId);
|
||||
}
|
||||
else
|
||||
return _getAndSendDataPointsWithNum(storage, ep, value, num, refMsgId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
|
||||
uint32_t refMsgId)
|
||||
int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
|
||||
valueId=AQH_Value_GetId(value);
|
||||
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
|
||||
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);
|
||||
free(tablePtr);
|
||||
@@ -151,9 +156,9 @@ int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
uint64_t valueId;
|
||||
uint64_t *tablePtr;
|
||||
@@ -175,6 +180,30 @@ int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
|
||||
|
||||
|
||||
int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint64_t num,
|
||||
uint32_t refMsgId)
|
||||
{
|
||||
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) {
|
||||
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
|
||||
free(tablePtr);
|
||||
return AQH_MSGDATA_RESULT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
|
||||
return AQH_MSGDATA_RESULT_ERROR_NODATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendDataPointsResponse(AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||
uint32_t refMsgId)
|
||||
@@ -193,36 +222,3 @@ void _sendDataPointsResponse(AQH_OBJECT *ep,
|
||||
|
||||
|
||||
|
||||
void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||
const AQH_VALUE *value, uint32_t refMsgId)
|
||||
{
|
||||
int rv;
|
||||
uint64_t timestamp=0;
|
||||
double data=0.0;
|
||||
|
||||
rv=AQH_Storage_GetLastDataPoint(storage, AQH_Value_GetId(value), ×tamp, &data);
|
||||
if (rv<0) {
|
||||
int resultCode;
|
||||
|
||||
switch(rv) {
|
||||
case GWEN_ERROR_INVALID: resultCode=AQH_MSGDATA_RESULT_ERROR_INVALID; break;
|
||||
case GWEN_ERROR_NO_DATA: resultCode=AQH_MSGDATA_RESULT_ERROR_NODATA; break;
|
||||
default: resultCode=AQH_MSGDATA_RESULT_ERROR_GENERIC; break;
|
||||
}
|
||||
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
|
||||
}
|
||||
else {
|
||||
AQH_MESSAGE *outMsg;
|
||||
|
||||
outMsg=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_GETDATA_RSP,
|
||||
AQH_Endpoint_GetNextMessageId(ep), refMsgId,
|
||||
value, timestamp, data);
|
||||
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,13 +13,16 @@
|
||||
|
||||
#include "./s_getvalues.h"
|
||||
#include "./server_p.h"
|
||||
#include "aqhome/aqhome.h"
|
||||
#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_getvalues.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_values.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
||||
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
@@ -38,7 +41,10 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
static AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList);
|
||||
static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId);
|
||||
static void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
|
||||
static int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality);
|
||||
|
||||
|
||||
|
||||
@@ -47,64 +53,100 @@ static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t fl
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void AqHomeDataServer_HandleGetValues(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, GWEN_UNUSED const GWEN_TAG16_LIST *tagList)
|
||||
void AqHomeDataServer_HandleGetValues(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_VALUE_LIST *origValueList;
|
||||
|
||||
AQH_VALUE_LIST *valueList;
|
||||
uint32_t refMsgId;
|
||||
|
||||
refMsgId=AQH_IpcMessage_GetMsgId(msg);
|
||||
|
||||
DBG_INFO(NULL, "HandleGetValues");
|
||||
origValueList=AQH_Storage_GetValueList(xo->storage);
|
||||
if (origValueList) {
|
||||
DBG_INFO(NULL, "Have a list of %d values", AQH_Value_List_GetCount(origValueList));
|
||||
if (AQH_Value_List_GetCount(origValueList)<AQHOMEDATA_VALUESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending all entries in one message");
|
||||
_sendValueList(ep, origValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
|
||||
}
|
||||
else {
|
||||
AQH_VALUE_LIST *tmpValueList;
|
||||
const AQH_VALUE *v;
|
||||
|
||||
DBG_INFO(NULL, "Sending entries in multiple messages");
|
||||
tmpValueList=AQH_Value_List_new();
|
||||
v=AQH_Value_List_First(origValueList);
|
||||
while(v) {
|
||||
const AQH_VALUE *next;
|
||||
AQH_VALUE *copyOfValue;
|
||||
|
||||
next=AQH_Value_List_Next(v);
|
||||
copyOfValue=AQH_Value_dup(v);
|
||||
AQH_Value_List_Add(copyOfValue, tmpValueList);
|
||||
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueList(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
|
||||
AQH_Value_List_Clear(tmpValueList);
|
||||
}
|
||||
v=next;
|
||||
}
|
||||
if (AQH_Value_List_GetCount(tmpValueList)) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueList(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */
|
||||
}
|
||||
AQH_Value_List_free(tmpValueList);
|
||||
}
|
||||
valueList=_getMatchingValueList(xo, tagList);
|
||||
if (valueList) {
|
||||
_sendValueList(ep, valueList, refMsgId);
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
_sendValueList(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
|
||||
_sendValueListMsg(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
AQH_VALUE_LIST *_getMatchingValueList(AQHOME_SERVER *xo, const GWEN_TAG16_LIST *tagList)
|
||||
{
|
||||
const AQH_VALUE_LIST *origValueList;
|
||||
AQH_VALUE_LIST *tmpValueList=NULL;
|
||||
char *deviceName;
|
||||
int modality;
|
||||
|
||||
deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME, NULL):NULL;
|
||||
modality=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETVALUES_TAGS_MODALITY, 0):0;
|
||||
|
||||
origValueList=AQH_Storage_GetValueList(xo->storage);
|
||||
if (origValueList) {
|
||||
const AQH_VALUE *v;
|
||||
|
||||
tmpValueList=AQH_Value_List_new();
|
||||
v=AQH_Value_List_First(origValueList);
|
||||
while(v) {
|
||||
if (_valueMatches(v, deviceName, modality)) {
|
||||
AQH_VALUE *copyOfValue;
|
||||
|
||||
copyOfValue=AQH_Value_dup(v);
|
||||
AQH_Value_List_Add(copyOfValue, tmpValueList);
|
||||
}
|
||||
v=AQH_Value_List_Next(v);
|
||||
}
|
||||
if (AQH_Value_List_GetCount(tmpValueList)<1) {
|
||||
AQH_Value_List_free(tmpValueList);
|
||||
tmpValueList=NULL;
|
||||
}
|
||||
}
|
||||
free(deviceName);
|
||||
|
||||
return tmpValueList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t refMsgId)
|
||||
{
|
||||
AQH_VALUE_LIST *tmpValueList;
|
||||
const AQH_VALUE *v;
|
||||
|
||||
tmpValueList=AQH_Value_List_new();
|
||||
v=AQH_Value_List_First(vl);
|
||||
while(v) {
|
||||
const AQH_VALUE *next;
|
||||
AQH_VALUE *copyOfValue;
|
||||
|
||||
next=AQH_Value_List_Next(v);
|
||||
copyOfValue=AQH_Value_dup(v);
|
||||
AQH_Value_List_Add(copyOfValue, tmpValueList);
|
||||
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueListMsg(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
|
||||
AQH_Value_List_Clear(tmpValueList);
|
||||
}
|
||||
v=next;
|
||||
}
|
||||
if (AQH_Value_List_GetCount(tmpValueList)) {
|
||||
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
|
||||
_sendValueListMsg(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */
|
||||
}
|
||||
AQH_Value_List_free(tmpValueList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
|
||||
{
|
||||
AQH_MESSAGE *msg;
|
||||
|
||||
@@ -115,3 +157,27 @@ void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, ui
|
||||
|
||||
|
||||
|
||||
int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modality)
|
||||
{
|
||||
if (modality!=AQH_ValueModality_Unknown) {
|
||||
int valModality;
|
||||
|
||||
valModality=AQH_Value_GetModality(v);
|
||||
if (valModality!=modality)
|
||||
return 0;
|
||||
}
|
||||
if (deviceName && *deviceName) {
|
||||
const char *s;
|
||||
|
||||
s=AQH_Value_GetDeviceNameForSystem(v);
|
||||
if (s && *s && GWEN_Text_ComparePattern(s, deviceName, 0)==-1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
getdevices.h
|
||||
adddata.h
|
||||
getdatapoints.h
|
||||
getfirstdata.h
|
||||
getlastdata.h
|
||||
getperioddata.h
|
||||
setdata.h
|
||||
moddevice.h
|
||||
watch.h
|
||||
@@ -49,6 +52,9 @@
|
||||
getdevices.c
|
||||
adddata.c
|
||||
getdatapoints.c
|
||||
getfirstdata.c
|
||||
getlastdata.c
|
||||
getperioddata.c
|
||||
setdata.c
|
||||
moddevice.c
|
||||
watch.c
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "./getvalues.h"
|
||||
#include "./getdatapoints.h"
|
||||
#include "../client.h"
|
||||
#include "../utils.h"
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId);
|
||||
static int _handleResponseMessage(AQH_OBJECT *o, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, int first);
|
||||
static void _handleDataResponse(const GWEN_TAG16_LIST *tagList, int printMean, int printDiff);
|
||||
static uint64_t _getTimeStampFromString(const char *s);
|
||||
|
||||
|
||||
|
||||
@@ -110,18 +109,23 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
|
||||
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
|
||||
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
|
||||
num=GWEN_DB_GetIntValue(dbArgs, "numOfLastDatapoints", 0, 0);
|
||||
tsBegin=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
|
||||
tsBegin=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
|
||||
if (tsBegin==(uint64_t) (-1)) {
|
||||
DBG_ERROR(NULL, "Bad begin timestamp");
|
||||
return NULL;
|
||||
}
|
||||
tsEnd=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
|
||||
tsEnd=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
|
||||
if (tsEnd==(uint64_t) (-1)) {
|
||||
DBG_ERROR(NULL, "Bad end timestamp");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, msgId, 0, valueName, tsBegin, tsEnd, num);
|
||||
// TODO: use "mode" correctly
|
||||
return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ,
|
||||
msgId, 0,
|
||||
AQH_MSGDATA_GETDATA_MODE_LAST,
|
||||
valueName,
|
||||
tsBegin, tsEnd, num);
|
||||
}
|
||||
|
||||
|
||||
@@ -178,45 +182,3 @@ void _handleDataResponse(const GWEN_TAG16_LIST *tagList, int printMean, int prin
|
||||
|
||||
|
||||
|
||||
uint64_t _getTimeStampFromString(const char *s)
|
||||
{
|
||||
if (s && *s) {
|
||||
if (*s=='-') {
|
||||
uint64_t x=0;
|
||||
uint64_t now=time(NULL);
|
||||
|
||||
s++;
|
||||
while(*s && isdigit(*s)) {
|
||||
unsigned int i;
|
||||
|
||||
i=*(s++)-'0';
|
||||
x*=10;
|
||||
x+=i;
|
||||
}
|
||||
if (*s) {
|
||||
switch(*s) {
|
||||
case 0:
|
||||
case 'm': x*=60; break;
|
||||
case 'h': x*=(60*60); break;
|
||||
case 'd': x*=(60*60*24); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return (now-x);
|
||||
}
|
||||
else {
|
||||
unsigned long int x;
|
||||
|
||||
if (1!=sscanf(s, "%lu", &x)) {
|
||||
DBG_ERROR(NULL, "ERROR: Invalid timestamp");
|
||||
return (uint64_t) (-1);
|
||||
}
|
||||
return (uint64_t) x;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
153
apps/aqhome-tool/data/getfirstdata.c
Normal file
153
apps/aqhome-tool/data/getfirstdata.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/****************************************************************************
|
||||
* 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 "./getfirstdata.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 <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 _runCommand(AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Tool_GetFirstData(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, "valueName", 1, 1, "N", "valuename", I18S("Value name (e.g. server/temp/system)"), NULL},
|
||||
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
|
||||
{ 0, A_INT, "printMean", 0, 1, "M", "mean", I18S("Print mean value of data received"), NULL},
|
||||
{ 0, A_INT, "printDiff", 0, 1, "D", "diff", I18S("Print diff last-first value"), 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 *valueName;
|
||||
uint64_t num;
|
||||
int printMean;
|
||||
int printDiff;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
valueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, NULL);
|
||||
num=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 1);
|
||||
printMean=GWEN_DB_GetIntValue(dbLocalArgs, "printMean", 0, 0);
|
||||
printDiff=GWEN_DB_GetIntValue(dbLocalArgs, "printDiff", 0, 0);
|
||||
|
||||
if (num>0) {
|
||||
uint64_t *dataPoints;
|
||||
uint64_t recvdNum;
|
||||
|
||||
dataPoints=malloc(num*sizeof(uint64_t)*2);
|
||||
|
||||
recvdNum=AQH_DataClient_GetFirstData(dc, valueName, dataPoints, num);
|
||||
if (recvdNum>0) {
|
||||
if (printMean)
|
||||
Utils_PrintMeanData(dataPoints, recvdNum, NULL);
|
||||
else if (printDiff)
|
||||
Utils_PrintDiffData(dataPoints, recvdNum, NULL);
|
||||
else
|
||||
Utils_PrintDataPoints(dataPoints, recvdNum, NULL);
|
||||
}
|
||||
free(dataPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-tool/data/getfirstdata.h
Normal file
21
apps/aqhome-tool/data/getfirstdata.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_GETFIRSTDATA_H
|
||||
#define AQHOME_TOOL_GETFIRSTDATA_H
|
||||
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
|
||||
|
||||
|
||||
int AQH_Tool_GetFirstData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
153
apps/aqhome-tool/data/getlastdata.c
Normal file
153
apps/aqhome-tool/data/getlastdata.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/****************************************************************************
|
||||
* 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 "./getlastdata.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 <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 _runCommand(AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Tool_GetLastData(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, "valueName", 1, 1, "N", "valuename", I18S("Value name (e.g. server/temp/system)"), NULL},
|
||||
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
|
||||
{ 0, A_INT, "printMean", 0, 1, "M", "mean", I18S("Print mean value of data received"), NULL},
|
||||
{ 0, A_INT, "printDiff", 0, 1, "D", "diff", I18S("Print diff last-first value"), 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 *valueName;
|
||||
uint64_t num;
|
||||
int printMean;
|
||||
int printDiff;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
valueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, NULL);
|
||||
num=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 1);
|
||||
printMean=GWEN_DB_GetIntValue(dbLocalArgs, "printMean", 0, 0);
|
||||
printDiff=GWEN_DB_GetIntValue(dbLocalArgs, "printDiff", 0, 0);
|
||||
|
||||
if (num>0) {
|
||||
uint64_t *dataPoints;
|
||||
uint64_t recvdNum;
|
||||
|
||||
dataPoints=malloc(num*sizeof(uint64_t)*2);
|
||||
|
||||
recvdNum=AQH_DataClient_GetLastData(dc, valueName, dataPoints, num);
|
||||
if (recvdNum>0) {
|
||||
if (printMean)
|
||||
Utils_PrintMeanData(dataPoints, recvdNum, NULL);
|
||||
else if (printDiff)
|
||||
Utils_PrintDiffData(dataPoints, recvdNum, NULL);
|
||||
else
|
||||
Utils_PrintDataPoints(dataPoints, recvdNum, NULL);
|
||||
}
|
||||
free(dataPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-tool/data/getlastdata.h
Normal file
21
apps/aqhome-tool/data/getlastdata.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_GETLASTDATA_H
|
||||
#define AQHOME_TOOL_GETLASTDATA_H
|
||||
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
|
||||
|
||||
|
||||
int AQH_Tool_GetLastData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
167
apps/aqhome-tool/data/getperioddata.c
Normal file
167
apps/aqhome-tool/data/getperioddata.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/****************************************************************************
|
||||
* 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 "./getperioddata.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 <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 _runCommand(AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* code
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_Tool_GetPeriodData(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, "valueName", 1, 1, "N", "valuename", I18S("Value name (e.g. server/temp/system)"), 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},
|
||||
{ 0, A_INT, "printMean", 0, 1, "M", "mean", I18S("Print mean value of data received"), NULL},
|
||||
{ 0, A_INT, "printDiff", 0, 1, "D", "diff", I18S("Print diff last-first value"), 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 *valueName;
|
||||
uint64_t num;
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
int printMean;
|
||||
int printDiff;
|
||||
|
||||
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||
valueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, NULL);
|
||||
num=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 1);
|
||||
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;
|
||||
}
|
||||
printMean=GWEN_DB_GetIntValue(dbLocalArgs, "printMean", 0, 0);
|
||||
printDiff=GWEN_DB_GetIntValue(dbLocalArgs, "printDiff", 0, 0);
|
||||
|
||||
if (num>0) {
|
||||
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) {
|
||||
if (printMean)
|
||||
Utils_PrintMeanData(dataPoints, recvdNum, NULL);
|
||||
else if (printDiff)
|
||||
Utils_PrintDiffData(dataPoints, recvdNum, NULL);
|
||||
else
|
||||
Utils_PrintDataPoints(dataPoints, recvdNum, NULL);
|
||||
}
|
||||
free(dataPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
21
apps/aqhome-tool/data/getperioddata.h
Normal file
21
apps/aqhome-tool/data/getperioddata.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_GETPERIODDATA_H
|
||||
#define AQHOME_TOOL_GETPERIODDATA_H
|
||||
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
|
||||
|
||||
|
||||
int AQH_Tool_GetPeriodData(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
#include "../client.h"
|
||||
#include "../utils.h"
|
||||
|
||||
#include "aqhome/aqhome.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_values.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
|
||||
|
||||
#include <gwenhywfar/args.h>
|
||||
#include <gwenhywfar/i18n.h>
|
||||
@@ -67,6 +69,8 @@ int AQH_Tool_GetValues(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
|
||||
{ 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, "device", 0, 1, "d", "device", I18S("device name to match"), NULL},
|
||||
{ A_ARG, A_CHAR, "modality", 0, 1, "m", NULL, I18S("Modality to match"), NULL},
|
||||
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
|
||||
{ 0, A_INT, "printHeader", 0, 1, "H", "printheader", I18S("Print header if given"), NULL},
|
||||
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
|
||||
@@ -90,11 +94,23 @@ int AQH_Tool_GetValues(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
|
||||
|
||||
AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
|
||||
{
|
||||
return AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID,
|
||||
AQH_IPC_PROTOCOL_DATA_VERSION,
|
||||
AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ,
|
||||
msgId, 0,
|
||||
0, NULL);
|
||||
GWEN_DB_NODE *dbArgs;
|
||||
const char *deviceName;
|
||||
const char *s;
|
||||
int modality;
|
||||
|
||||
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
|
||||
deviceName=GWEN_DB_GetCharValue(dbArgs, "device", 0, NULL);
|
||||
s=GWEN_DB_GetCharValue(dbArgs, "modality", 0, NULL);
|
||||
if (s && *s) {
|
||||
modality=AQH_ValueModality_fromString(s);
|
||||
if (modality==AQH_ValueModality_Unknown) {
|
||||
}
|
||||
}
|
||||
else
|
||||
modality=AQH_ValueModality_Unknown;
|
||||
|
||||
return AQH_IpcdMessageGetValues_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ, msgId, 0, deviceName, modality);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -17,6 +17,9 @@
|
||||
#include "./data/getdevices.h"
|
||||
#include "./data/adddata.h"
|
||||
#include "./data/getdatapoints.h"
|
||||
#include "./data/getfirstdata.h"
|
||||
#include "./data/getlastdata.h"
|
||||
#include "./data/getperioddata.h"
|
||||
#include "./data/setdata.h"
|
||||
#include "./data/moddevice.h"
|
||||
#include "./data/watch.h"
|
||||
@@ -92,6 +95,9 @@ int main(int argc, char **argv)
|
||||
GWEN_FE_DAH("adddata", AQH_Tool_AddDataPoint, I18N("Send a datapoint to the data server")),
|
||||
GWEN_FE_DAH("addjsondata", AQH_Tool_AddDataPoint, I18N("(same as adddata)")),
|
||||
GWEN_FE_DAH("getdata", AQH_Tool_GetDataPoints, I18N("Request list of datapoints for a value on the data server")),
|
||||
GWEN_FE_DAH("getfirstdata", AQH_Tool_GetFirstData, I18N("Request first datapoints for a value on the data server")),
|
||||
GWEN_FE_DAH("getlastdata", AQH_Tool_GetLastData, I18N("Request last datapoints for a value on the data server")),
|
||||
GWEN_FE_DAH("getperioddata", AQH_Tool_GetPeriodData, I18N("Request datapoints from a date range for a value on the data server")),
|
||||
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")),
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "aqhome/msg/ipc/nodes/m_ipcn_setaccmsggrps.h"
|
||||
#include "aqhome/ipc2/tcp_object.h"
|
||||
#include "aqhome/ipc2/ipc_client.h"
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
@@ -27,6 +28,7 @@
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define UTILS_IPC_ENDPOINT_DEFAULT_MSGSIZE 4096
|
||||
@@ -361,4 +363,47 @@ void Utils_PrintValue(const AQH_VALUE *value, int printHeader)
|
||||
|
||||
|
||||
|
||||
uint64_t Utils_GetTimeStampFromString(const char *s)
|
||||
{
|
||||
if (s && *s) {
|
||||
if (*s=='-') {
|
||||
uint64_t x=0;
|
||||
uint64_t now=time(NULL);
|
||||
|
||||
s++;
|
||||
while(*s && isdigit(*s)) {
|
||||
unsigned int i;
|
||||
|
||||
i=*(s++)-'0';
|
||||
x*=10;
|
||||
x+=i;
|
||||
}
|
||||
if (*s) {
|
||||
switch(*s) {
|
||||
case 0:
|
||||
case 'm': x*=60; break;
|
||||
case 'h': x*=(60*60); break;
|
||||
case 'd': x*=(60*60*24); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return (now-x);
|
||||
}
|
||||
else {
|
||||
unsigned long int x;
|
||||
|
||||
if (1!=sscanf(s, "%lu", &x)) {
|
||||
DBG_ERROR(NULL, "ERROR: Invalid timestamp");
|
||||
return (uint64_t) (-1);
|
||||
}
|
||||
return (uint64_t) x;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ void Utils_PrintValue(const AQH_VALUE *value, int printHeader);
|
||||
|
||||
AQH_DEVICE *Utils_DeviceFromArgs(GWEN_DB_NODE *dbArgs);
|
||||
|
||||
uint64_t Utils_GetTimeStampFromString(const char *s);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
14
aqhome-cgi.sh
Normal file
14
aqhome-cgi.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# AQHOME_LOGLEVEL=info LD_LIBRARY_PATH="../../aqhome/:$LD_LIBRARY_PATH" ./aqhomed -l aqhome.log -db aqhome.db -ma 127.0.0.1
|
||||
|
||||
# export AQHOME_LOGLEVEL=info
|
||||
export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
|
||||
|
||||
# aqhomed -l /var/log/aqhome.log -db /var/cache/aqhome/nodes.db -ma 192.168.117.192 -mp 1883 -t 127.0.0.1 -W /var/cache/aqhome
|
||||
|
||||
# 0-build/apps/aqhomed/aqhomed -l aqhome.log -db aqhome.db -ma 192.168.117.192 -mp 1883 -t 127.0.0.1 -p aqhomed.pid
|
||||
|
||||
# 0-build/apps/aqhomed/aqhomed -l aqhome.log -db aqhome.db -p aqhomed.pid -W /tmp/aqhome/aqhomed -ma 192.168.117.192 -mp 1883 -t 127.0.0.1 --mqttclientid=AQHOMEMQTTLOGTEST1
|
||||
0-build/apps/aqhome-cgi/aqhome-cgi
|
||||
#0-build/apps/aqhome-nodes/aqhome-nodes -l aqhome-nodes.log -db aqhome-nodes.db -p aqhome-nodes.pid -t 127.0.0.1 -ba 127.0.0.1 "$@"
|
||||
@@ -69,6 +69,7 @@
|
||||
hexfile
|
||||
data
|
||||
events2
|
||||
dataclient
|
||||
</subdirs>
|
||||
|
||||
|
||||
@@ -79,6 +80,7 @@
|
||||
aqhhexfile
|
||||
aqhdata
|
||||
aqhevents2
|
||||
aqhdataclient
|
||||
</useTargets>
|
||||
|
||||
<libraries>
|
||||
|
||||
@@ -267,6 +267,8 @@ int AQH_ValueModality_fromString(const char *s)
|
||||
return AQH_ValueModality_TVOC;
|
||||
else if (strcasecmp(s, "stats")==0)
|
||||
return AQH_ValueModality_Stats;
|
||||
else if (strcasecmp(s, "light")==0)
|
||||
return AQH_ValueModality_Light;
|
||||
}
|
||||
return AQH_ValueModality_Unknown;
|
||||
}
|
||||
@@ -285,6 +287,7 @@ const char *AQH_ValueModality_toString(int i)
|
||||
case AQH_ValueModality_Co2: return "co2";
|
||||
case AQH_ValueModality_TVOC: return "tvoc";
|
||||
case AQH_ValueModality_Stats: return "stats";
|
||||
case AQH_ValueModality_Light: return "light";
|
||||
case AQH_ValueModality_Unknown:
|
||||
default: return "unknown";
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ enum {
|
||||
AQH_ValueModality_Motion,
|
||||
AQH_ValueModality_Co2,
|
||||
AQH_ValueModality_TVOC,
|
||||
AQH_ValueModality_Stats
|
||||
AQH_ValueModality_Stats,
|
||||
AQH_ValueModality_Light
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -305,6 +305,17 @@ AQH_STORAGE_GETLASTDATAPOINT_FN AQH_Storage_SetGetLastDatapointFn(AQH_STORAGE *s
|
||||
|
||||
|
||||
|
||||
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN AQH_Storage_SetGetFirstNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTNDATAPOINTS_FN fn)
|
||||
{
|
||||
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN oldFn;
|
||||
|
||||
oldFn=sto->getFirstNDatapointsFn;
|
||||
sto->getFirstNDatapointsFn=fn;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_STORAGE_GETLASTNDATAPOINTS_FN AQH_Storage_SetGetLastNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTNDATAPOINTS_FN fn)
|
||||
{
|
||||
AQH_STORAGE_GETLASTNDATAPOINTS_FN oldFn;
|
||||
@@ -383,8 +394,8 @@ int AQH_Storage_AddDatapoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t timest
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t fromTime, uint64_t toTime, uint64_t maxArrayLen)
|
||||
uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t fromTime, uint64_t toTime,
|
||||
uint64_t maxDataPointsRequested)
|
||||
{
|
||||
AQH_DATAFILE *df;
|
||||
uint64_t numEntries;
|
||||
@@ -399,13 +410,9 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
|
||||
return NULL;
|
||||
}
|
||||
numEntries=AQH_DataFile_GetNumberOfEntries(df);
|
||||
if (fromTime==0 && toTime==0)
|
||||
arrayLen=(numEntries*2)+1;
|
||||
else
|
||||
arrayLen=(AQH_STORAGE_DATAPOINTS_STEPS*2)+1;
|
||||
if (arrayLen>maxArrayLen+1)
|
||||
arrayLen=maxArrayLen+1;
|
||||
|
||||
if (maxDataPointsRequested>numEntries)
|
||||
maxDataPointsRequested=numEntries;
|
||||
arrayLen=(maxDataPointsRequested*2)+1;
|
||||
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
|
||||
if (arrayPtr==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen);
|
||||
@@ -427,30 +434,11 @@ 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)>maxArrayLen) {
|
||||
if ((arrayPos+1)>arrayLen) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
|
||||
break;
|
||||
}
|
||||
if (arrayPos+1>=arrayLen) {
|
||||
uint64_t newArrayLen;
|
||||
void *p;
|
||||
|
||||
newArrayLen=arrayLen+(AQH_STORAGE_DATAPOINTS_STEPS*2);
|
||||
if (newArrayLen>maxArrayLen+1)
|
||||
newArrayLen=maxArrayLen+1;
|
||||
if (newArrayLen==arrayLen) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
|
||||
break;
|
||||
}
|
||||
p=realloc((void*) arrayPtr, newArrayLen*sizeof(uint64_t));
|
||||
if (p==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen+AQH_STORAGE_DATAPOINTS_STEPS);
|
||||
free(arrayPtr);
|
||||
return NULL;
|
||||
}
|
||||
arrayPtr=(uint64_t*) p;
|
||||
arrayLen=newArrayLen;
|
||||
}
|
||||
arrayPtr[arrayPos++]=ts;
|
||||
arrayPtr[arrayPos++]=u.i;
|
||||
}
|
||||
@@ -468,6 +456,67 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
|
||||
|
||||
|
||||
|
||||
uint64_t *AQH_Storage_GetFirstNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested)
|
||||
{
|
||||
AQH_DATAFILE *df;
|
||||
uint64_t numEntries;
|
||||
uint64_t numOfDataEntries;
|
||||
uint64_t arrayLen;
|
||||
uint64_t arrayPos;
|
||||
uint64_t *arrayPtr;
|
||||
uint64_t firstRecord;
|
||||
uint64_t i;
|
||||
|
||||
df=_getDataFileByValueId(sto, valueId);
|
||||
if (df==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No file for value id %lu", (unsigned long int) valueId);
|
||||
return NULL;
|
||||
}
|
||||
numEntries=AQH_DataFile_GetNumberOfEntries(df);
|
||||
numOfDataEntries=numEntries-1; /* first entry is reserved, don't count it here */
|
||||
if (numOfDataEntries<1) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "No data records for value id %lu", (unsigned long int) valueId);
|
||||
return NULL;
|
||||
}
|
||||
firstRecord=1;
|
||||
if (numOfDataEntries>maxDataPointsRequested) /* more entries in file than requested */
|
||||
arrayLen=(maxDataPointsRequested*2)+1; /* +1 because the first array entry contains the number of entries */
|
||||
else
|
||||
arrayLen=(numOfDataEntries*2)+1;
|
||||
|
||||
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
|
||||
if (arrayPtr==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen);
|
||||
return NULL;
|
||||
}
|
||||
arrayPos=1;
|
||||
|
||||
for (i=firstRecord; i<numEntries; i++) {
|
||||
union {double f; uint64_t i;} u;
|
||||
uint64_t ts;
|
||||
int rv;
|
||||
|
||||
rv=AQH_DataFile_ReadRecord(df, i, &ts, &(u.f));
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
free(arrayPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((arrayPos+1)>=arrayLen) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Requested number of entries reached");
|
||||
break;
|
||||
}
|
||||
arrayPtr[arrayPos++]=ts;
|
||||
arrayPtr[arrayPos++]=u.i;
|
||||
} /* for */
|
||||
|
||||
arrayPtr[0]=arrayPos-1;
|
||||
return arrayPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t *AQH_Storage_GetLastNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested)
|
||||
{
|
||||
AQH_DATAFILE *df;
|
||||
|
||||
@@ -53,6 +53,8 @@ typedef uint64_t *(*AQH_STORAGE_GETDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t val
|
||||
uint64_t maxArrayLen);
|
||||
typedef int (*AQH_STORAGE_GETFIRSTDATAPOINT_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
|
||||
typedef int (*AQH_STORAGE_GETLASTDATAPOINT_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
|
||||
|
||||
typedef uint64_t *(*AQH_STORAGE_GETFIRSTNDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
|
||||
typedef uint64_t *(*AQH_STORAGE_GETLASTNDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
|
||||
|
||||
|
||||
@@ -96,6 +98,8 @@ AQHOME_API uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueI
|
||||
uint64_t maxArrayLen);
|
||||
AQHOME_API int AQH_Storage_GetFirstDataPoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
|
||||
AQHOME_API int AQH_Storage_GetLastDataPoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
|
||||
|
||||
AQHOME_API uint64_t *AQH_Storage_GetFirstNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
|
||||
AQHOME_API uint64_t *AQH_Storage_GetLastNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
|
||||
|
||||
|
||||
@@ -105,6 +109,8 @@ AQHOME_API AQH_STORAGE_ADDDATAPOINT_FN AQH_Storage_SetAddDatapointFn(AQH_STORAGE
|
||||
AQHOME_API AQH_STORAGE_GETDATAPOINTS_FN AQH_Storage_SetGetDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETDATAPOINTS_FN fn);
|
||||
AQHOME_API AQH_STORAGE_GETFIRSTDATAPOINT_FN AQH_Storage_SetGetFirstDatapointFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTDATAPOINT_FN fn);
|
||||
AQHOME_API AQH_STORAGE_GETLASTDATAPOINT_FN AQH_Storage_SetGetLastDatapointFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTDATAPOINT_FN fn);
|
||||
|
||||
AQHOME_API AQH_STORAGE_GETFIRSTNDATAPOINTS_FN AQH_Storage_SetGetFirstNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTNDATAPOINTS_FN fn);
|
||||
AQHOME_API AQH_STORAGE_GETLASTNDATAPOINTS_FN AQH_Storage_SetGetLastNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTNDATAPOINTS_FN fn);
|
||||
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ struct AQH_STORAGE {
|
||||
AQH_STORAGE_GETFIRSTDATAPOINT_FN getFirstDatapointFn;
|
||||
AQH_STORAGE_GETLASTDATAPOINT_FN getLastDatapointFn;
|
||||
AQH_STORAGE_GETLASTNDATAPOINTS_FN getLastNDatapointsFn;
|
||||
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN getFirstNDatapointsFn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
81
aqhome/dataclient/0BUILD
Normal file
81
aqhome/dataclient/0BUILD
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="ConvenienceLibrary" name="aqhdataclient" >
|
||||
|
||||
<includes type="c" >
|
||||
$(gwenhywfar_cflags)
|
||||
$(aqdatabase_cflags)
|
||||
-I$(topsrcdir)
|
||||
-I$(topbuilddir)
|
||||
</includes>
|
||||
|
||||
<includes type="tm2" >
|
||||
--include=$(builddir)
|
||||
--include=$(srcdir)
|
||||
--include=$(aqdatabase_AQDATABASE_TYPEMAKERDIR)/c
|
||||
</includes>
|
||||
|
||||
|
||||
<define name="BUILDING_AQHOME" />
|
||||
|
||||
<setVar name="local/cflags">$(visibility_cflags)</setVar>
|
||||
|
||||
|
||||
<setVar name="tm2flags" >
|
||||
--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)/dataclient" >
|
||||
$(local/built_headers_pub)
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" install="$(pkgincludedir)/dataclient" >
|
||||
client.h
|
||||
</headers>
|
||||
|
||||
|
||||
<headers dist="true" >
|
||||
client_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
<sources>
|
||||
$(local/typefiles)
|
||||
|
||||
client.c
|
||||
</sources>
|
||||
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
<useTargets>
|
||||
</useTargets>
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
</gwbuild>
|
||||
555
aqhome/dataclient/client.c
Normal file
555
aqhome/dataclient/client.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/****************************************************************************
|
||||
* 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 "./client_p.h"
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
#include "aqhome/msg/ipc/nodes/m_ipcn.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_connect.h"
|
||||
#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_getdata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd_setdata.h"
|
||||
#include "aqhome/ipc2/tcp_object.h"
|
||||
#include "aqhome/ipc2/ipc_client.h"
|
||||
#include <aqhome/ipc2/ipc_endpoint.h>
|
||||
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/timestamp.h>
|
||||
#include <gwenhywfar/db.h>
|
||||
#include <gwenhywfar/i18n.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
|
||||
#define AQH_DATA_CLIENT_DEFAULT_CMD_TIMEOUT 5
|
||||
|
||||
|
||||
|
||||
static int _connectEndpoint(AQH_DATACLIENT *dc, const char *addr, int port, uint32_t flags);
|
||||
static int _exchangeConnectMsgs(AQH_DATACLIENT *dc, const char *userId, const char *passwd, const char *clientId, uint32_t flags);
|
||||
static uint64_t _getFirstOrLastData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum, int mode);
|
||||
static uint64_t _handleDataResponses(AQH_DATACLIENT *dc, uint64_t *dataPtr, uint64_t maxNum, uint32_t msgId);
|
||||
static int _handleResult(AQH_DATACLIENT *dc, uint32_t msgId);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_DATACLIENT *AQH_DataClient_new(AQH_EVENT_LOOP *eventLoop, uint8_t protoId, uint8_t protoVer)
|
||||
{
|
||||
AQH_DATACLIENT *dc;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_DATACLIENT, dc);
|
||||
|
||||
dc->eventLoop=eventLoop;
|
||||
dc->protoId=protoId;
|
||||
dc->protoVer=protoVer;
|
||||
dc->timeoutInSeconds=AQH_DATA_CLIENT_DEFAULT_CMD_TIMEOUT;
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_DataClient_free(AQH_DATACLIENT *dc)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_Object_free(dc->ipcEndpoint);
|
||||
GWEN_FREE_OBJECT(dc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_ReadLocalArgs(AQH_DATACLIENT *dc,
|
||||
GWEN_DB_NODE *dbGlobalArgs, const GWEN_ARGS *args,
|
||||
int argc, char **argv)
|
||||
{
|
||||
if (dc) {
|
||||
int rv;
|
||||
|
||||
GWEN_DB_Group_free(dc->dbLocalArgs);
|
||||
dc->dbLocalArgs=GWEN_DB_GetGroup(dbGlobalArgs, GWEN_DB_FLAGS_DEFAULT, "local");
|
||||
rv=GWEN_Args_Check(argc, argv, 1, GWEN_ARGS_MODE_ALLOW_FREEPARAM, args, dc->dbLocalArgs);
|
||||
if (rv==GWEN_ARGS_RESULT_ERROR) {
|
||||
fprintf(stderr, "ERROR: Could not parse arguments\n");
|
||||
return 1;
|
||||
}
|
||||
else if (rv==GWEN_ARGS_RESULT_HELP) {
|
||||
GWEN_BUFFER *ubuf;
|
||||
|
||||
ubuf=GWEN_Buffer_new(0, 1024, 0, 1);
|
||||
if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) {
|
||||
fprintf(stderr, "ERROR: Could not create help string\n");
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(ubuf));
|
||||
GWEN_Buffer_free(ubuf);
|
||||
return 1;
|
||||
}
|
||||
dc->timeoutInSeconds=GWEN_DB_GetIntValue(dc->dbLocalArgs, "timeout", 0, 5);
|
||||
|
||||
AQH_MergeConfigFileIntoConfig(dc->dbLocalArgs, "ConfigFile");
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_DB_NODE *AQH_DataClient_GetDbLocalArgs(const AQH_DATACLIENT *dc)
|
||||
{
|
||||
return dc?dc->dbLocalArgs:NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_Connect(AQH_DATACLIENT *dc,
|
||||
const char *addr, int port,
|
||||
const char *userId, const char *passwd,
|
||||
const char *clientId,
|
||||
uint32_t flags)
|
||||
{
|
||||
if (dc) {
|
||||
int rv;
|
||||
|
||||
AQH_Object_free(dc->ipcEndpoint);
|
||||
dc->ipcEndpoint=NULL;
|
||||
|
||||
rv=_connectEndpoint(dc, addr, port, 0 /* connection flags */);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=_exchangeConnectMsgs(dc, userId, passwd, clientId, flags);
|
||||
if (rv<0) {
|
||||
AQH_Object_free(dc->ipcEndpoint);
|
||||
dc->ipcEndpoint=NULL;
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_Disconnect(AQH_DATACLIENT *dc)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_Object_free(dc->ipcEndpoint);
|
||||
dc->ipcEndpoint=NULL;
|
||||
return 0;
|
||||
}
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_DataClient_SetTimeout(AQH_DATACLIENT *dc, int i)
|
||||
{
|
||||
if (dc) {
|
||||
dc->timeoutInSeconds=i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
AQH_MESSAGE *msgIn;
|
||||
uint32_t msgId;
|
||||
AQH_DEVICE_LIST *fullDeviceList;
|
||||
|
||||
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);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
|
||||
GWEN_TAG16_LIST *tagList;
|
||||
|
||||
tagList=AQH_IpcMessageTag16_ParsePayload(msgIn, 0);
|
||||
if (tagList) {
|
||||
uint16_t code;
|
||||
|
||||
code=AQH_IpcMessage_GetCode(msgIn);
|
||||
if (code==AQH_MSGTYPE_IPC_DATA_GETDEVICES_RSP) {
|
||||
AQH_DEVICE_LIST *deviceList;
|
||||
|
||||
deviceList=AQH_IpcdMessageDevices_ReadDeviceList(tagList);
|
||||
if (deviceList) {
|
||||
AQH_Device_List_AddList(fullDeviceList, deviceList);
|
||||
AQH_Device_List_free(deviceList);
|
||||
}
|
||||
if (AQH_IpcdMessageDevices_GetFlags(tagList) & AQH_MSGDATA_DEVICES_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));
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
AQH_Device_List_free(fullDeviceList);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
|
||||
}
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
}
|
||||
AQH_Message_free(msgIn);
|
||||
} /* while */
|
||||
|
||||
if (AQH_Device_List_GetCount(fullDeviceList)>0)
|
||||
return fullDeviceList;
|
||||
AQH_Device_List_free(fullDeviceList);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_VALUE_LIST *AQH_DataClient_GetValues(AQH_DATACLIENT *dc, const char *deviceName, int modality)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
AQH_MESSAGE *msgIn;
|
||||
uint32_t msgId;
|
||||
AQH_VALUE_LIST *fullValueList;
|
||||
|
||||
fullValueList=AQH_Value_List_new();
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageGetValues_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ, msgId, 0, deviceName, modality);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
|
||||
GWEN_TAG16_LIST *tagList;
|
||||
|
||||
tagList=AQH_IpcMessageTag16_ParsePayload(msgIn, 0);
|
||||
if (tagList) {
|
||||
uint16_t code;
|
||||
|
||||
code=AQH_IpcMessage_GetCode(msgIn);
|
||||
if (code==AQH_MSGTYPE_IPC_DATA_GETVALUES_RSP) {
|
||||
AQH_VALUE_LIST *valueList;
|
||||
|
||||
valueList=AQH_IpcdMessageValues_ReadValueList(tagList);
|
||||
if (valueList) {
|
||||
AQH_Value_List_AddList(fullValueList, valueList);
|
||||
AQH_Value_List_free(valueList);
|
||||
}
|
||||
if (AQH_IpcdMessageValues_GetFlags(tagList) & AQH_MSGDATA_VALUES_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));
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
AQH_Value_List_free(fullValueList);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
|
||||
}
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
}
|
||||
AQH_Message_free(msgIn);
|
||||
} /* while */
|
||||
|
||||
if (AQH_Value_List_GetCount(fullValueList)>0)
|
||||
return fullValueList;
|
||||
AQH_Value_List_free(fullValueList);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t AQH_DataClient_GetFirstData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum)
|
||||
{
|
||||
return _getFirstOrLastData(dc, valueName, dataPtr, maxNum, AQH_MSGDATA_GETDATA_MODE_FIRST);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t AQH_DataClient_GetLastData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum)
|
||||
{
|
||||
return _getFirstOrLastData(dc, valueName, dataPtr, maxNum, AQH_MSGDATA_GETDATA_MODE_LAST);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char *valueName,
|
||||
uint64_t *dataPtr, uint64_t maxNum,
|
||||
uint64_t tsBegin, uint64_t tsEnd)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
uint32_t msgId;
|
||||
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ,
|
||||
msgId, 0,
|
||||
AQH_MSGDATA_GETDATA_MODE_PERIOD,
|
||||
valueName, tsBegin, tsEnd, maxNum);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
return _handleDataResponses(dc, dataPtr, maxNum, msgId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_SetData(AQH_DATACLIENT *dc, const AQH_VALUE *v, const char *data)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
uint32_t msgId;
|
||||
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageSetData_new(AQH_MSGTYPE_IPC_DATA_SETDATA, msgId, 0, v, data);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
return _handleResult(dc, msgId);
|
||||
}
|
||||
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t timeStamp, double dataPoint)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
uint32_t msgId;
|
||||
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageMultiData_newForOne(AQH_MSGTYPE_IPC_DATA_UPDATEDATA, msgId, 0, v, timeStamp, dataPoint);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
return _handleResult(dc, msgId);
|
||||
}
|
||||
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int _connectEndpoint(AQH_DATACLIENT *dc, const char *addr, int port, uint32_t flags)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_OBJECT *ep;
|
||||
int fd;
|
||||
|
||||
fd=AQH_TcpObject_CreateConnectedSocket(addr, port);
|
||||
if (fd<0) {
|
||||
DBG_ERROR(NULL, "Error connecting to broker server %s:%d", addr, port);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
ep=AQH_IpcClientObject_new(dc->eventLoop, fd);
|
||||
assert(ep);
|
||||
AQH_Endpoint_AddFlags(ep, flags);
|
||||
dc->ipcEndpoint=ep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _exchangeConnectMsgs(AQH_DATACLIENT *dc, const char *userId, const char *passwd, const char *clientId, uint32_t flags)
|
||||
{
|
||||
AQH_MESSAGE *msgOut;
|
||||
uint32_t msgId;
|
||||
|
||||
DBG_INFO(NULL, "Sending connect message for proto=%d.%d", dc->protoId, dc->protoVer);
|
||||
msgId=AQH_Endpoint_GetNextMessageId(dc->ipcEndpoint);
|
||||
msgOut=AQH_IpcMessageConnect_new(dc->protoId, dc->protoVer,
|
||||
AQH_MSGTYPE_IPC_CONNECT_REQ,
|
||||
msgId, 0,
|
||||
clientId, userId, passwd, flags);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
return AQH_IpcEndpoint_WaitForResultMsg(dc->ipcEndpoint,
|
||||
dc->protoId, dc->protoVer, AQH_MSGTYPE_IPC_RESULT,
|
||||
msgId, dc->timeoutInSeconds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t _getFirstOrLastData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum, int mode)
|
||||
{
|
||||
if (dc) {
|
||||
AQH_MESSAGE *msgOut;
|
||||
uint32_t msgId;
|
||||
|
||||
msgId=++(dc->lastMsgId);
|
||||
msgOut=AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ,
|
||||
msgId, 0,
|
||||
mode,
|
||||
valueName, 0, 0, maxNum);
|
||||
AQH_Endpoint_AddMsgOut(dc->ipcEndpoint, msgOut);
|
||||
|
||||
return _handleDataResponses(dc, dataPtr, maxNum, msgId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint64_t _handleDataResponses(AQH_DATACLIENT *dc, uint64_t *dataPtr, uint64_t maxNum, uint32_t msgId)
|
||||
{
|
||||
AQH_MESSAGE *msgIn;
|
||||
uint64_t fullNumberOfPoints=0;
|
||||
|
||||
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
|
||||
GWEN_TAG16_LIST *tagList;
|
||||
|
||||
tagList=AQH_IpcMessageTag16_ParsePayload(msgIn, 0);
|
||||
if (tagList) {
|
||||
uint16_t code;
|
||||
|
||||
code=AQH_IpcMessage_GetCode(msgIn);
|
||||
if (code==AQH_MSGTYPE_IPC_DATA_GETDATA_RSP) {
|
||||
const uint64_t *recvDataPtr;
|
||||
uint64_t recvNumberOfPoints;
|
||||
|
||||
AQH_IpcdMessageMultiData_ReadDatapoints(tagList, &recvDataPtr, &recvNumberOfPoints);
|
||||
if (recvNumberOfPoints) {
|
||||
uint64_t i;
|
||||
|
||||
for (i=0; i<recvNumberOfPoints; i++) {
|
||||
if (fullNumberOfPoints<maxNum) {
|
||||
dataPtr[fullNumberOfPoints*2]=recvDataPtr[i*2];
|
||||
dataPtr[(fullNumberOfPoints*2)+1]=recvDataPtr[(i*2)+1];
|
||||
fullNumberOfPoints++;
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(NULL, "Too many bytes received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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));
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
|
||||
}
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
}
|
||||
AQH_Message_free(msgIn);
|
||||
} /* while */
|
||||
return fullNumberOfPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleResult(AQH_DATACLIENT *dc, uint32_t msgId)
|
||||
{
|
||||
AQH_MESSAGE *msgIn;
|
||||
|
||||
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
|
||||
GWEN_TAG16_LIST *tagList;
|
||||
|
||||
tagList=AQH_IpcMessageTag16_ParsePayload(msgIn, 0);
|
||||
if (tagList) {
|
||||
uint16_t code;
|
||||
|
||||
code=AQH_IpcMessage_GetCode(msgIn);
|
||||
if (code==AQH_MSGTYPE_IPC_DATA_RESULT) {
|
||||
int result;
|
||||
|
||||
result=AQH_IpcMessageResult_GetResult(tagList);
|
||||
DBG_INFO(NULL, "Server result: %d", result);
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
AQH_Message_free(msgIn);
|
||||
if (result!=AQH_MSGDATA_RESULT_SUCCESS) {
|
||||
DBG_INFO(NULL, "here (%d)", result);
|
||||
return GWEN_ERROR_GENERIC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
|
||||
}
|
||||
GWEN_Tag16_List_free(tagList);
|
||||
}
|
||||
AQH_Message_free(msgIn);
|
||||
} /* while */
|
||||
|
||||
return GWEN_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AQH_DataClient_ConnectWithArgs(AQH_DATACLIENT *dc, uint32_t flags)
|
||||
{
|
||||
const char *brokerAddress;
|
||||
int brokerPort;
|
||||
const char *userId;
|
||||
const char *passwd;
|
||||
const char *clientId;
|
||||
int rv;
|
||||
|
||||
brokerAddress=GWEN_DB_GetCharValue(dc->dbLocalArgs, "brokerAddress", 0, NULL);
|
||||
if (!(brokerAddress && *brokerAddress))
|
||||
brokerAddress=GWEN_DB_GetCharValue(dc->dbLocalArgs, "ConfigFile/brokerAddress", 0, "127.0.0.1");
|
||||
|
||||
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "brokerPort", 0, -1);
|
||||
if (brokerPort<0)
|
||||
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "ConfigFile/brokerPort", 0, 45456);
|
||||
|
||||
userId=GWEN_DB_GetCharValue(dc->dbLocalArgs, "userId", 0, NULL);
|
||||
passwd=GWEN_DB_GetCharValue(dc->dbLocalArgs, "password", 0, NULL);
|
||||
clientId=GWEN_DB_GetCharValue(dc->dbLocalArgs, "brokerClientId", 0, NULL);
|
||||
|
||||
rv=AQH_DataClient_Connect(dc, brokerAddress, brokerPort, userId, passwd, clientId, flags);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
57
aqhome/dataclient/client.h
Normal file
57
aqhome/dataclient/client.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
* 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_DATA_CLIENT_H
|
||||
#define AQHOME_DATA_CLIENT_H
|
||||
|
||||
#include <aqhome/api.h>
|
||||
#include <aqhome/events2/object.h>
|
||||
#include <aqhome/data/value.h>
|
||||
#include <aqhome/data/device.h>
|
||||
|
||||
#include <gwenhywfar/args.h>
|
||||
|
||||
|
||||
typedef struct AQH_DATACLIENT AQH_DATACLIENT;
|
||||
|
||||
|
||||
AQHOME_API AQH_DATACLIENT *AQH_DataClient_new(AQH_EVENT_LOOP *eventLoop, uint8_t protoId, uint8_t protoVer);
|
||||
AQHOME_API void AQH_DataClient_free(AQH_DATACLIENT *dc);
|
||||
|
||||
AQHOME_API void AQH_DataClient_SetTimeout(AQH_DATACLIENT *dc, int i);
|
||||
|
||||
|
||||
AQHOME_API int AQH_DataClient_Connect(AQH_DATACLIENT *dc,
|
||||
const char *addr, int port,
|
||||
const char *userId, const char *passwd,
|
||||
const char *clientId,
|
||||
uint32_t flags);
|
||||
AQHOME_API int AQH_DataClient_Disconnect(AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
AQHOME_API AQH_DEVICE_LIST *AQH_DataClient_GetDevices(AQH_DATACLIENT *dc);
|
||||
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);
|
||||
AQHOME_API uint64_t AQH_DataClient_GetLastData(AQH_DATACLIENT *dc, const char *valueName, uint64_t *dataPtr, uint64_t maxNum);
|
||||
AQHOME_API uint64_t AQH_DataClient_GetPeriodData(AQH_DATACLIENT *dc, const char *valueName,
|
||||
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_UpdateData(AQH_DATACLIENT *dc, const AQH_VALUE *v, uint64_t timeStamp, double dataPoint);
|
||||
|
||||
|
||||
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_ConnectWithArgs(AQH_DATACLIENT *dc, uint32_t flags);
|
||||
AQHOME_API GWEN_DB_NODE *AQH_DataClient_GetDbLocalArgs(const AQH_DATACLIENT *dc);
|
||||
|
||||
|
||||
#endif
|
||||
32
aqhome/dataclient/client_p.h
Normal file
32
aqhome/dataclient/client_p.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/****************************************************************************
|
||||
* 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_DATA_CLIENT_P_H
|
||||
#define AQHOME_DATA_CLIENT_P_H
|
||||
|
||||
#include "aqhome/dataclient/client.h"
|
||||
|
||||
|
||||
struct AQH_DATACLIENT {
|
||||
AQH_EVENT_LOOP *eventLoop;
|
||||
|
||||
AQH_OBJECT *ipcEndpoint;
|
||||
int timeoutInSeconds;
|
||||
|
||||
uint8_t protoId;
|
||||
uint8_t protoVer;
|
||||
|
||||
uint32_t lastMsgId;
|
||||
|
||||
GWEN_DB_NODE *dbLocalArgs;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gwenhywfar/inherit.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
//#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
@@ -170,6 +171,7 @@ int AQH_FdObject_Read(AQH_OBJECT *o, uint8_t *ptrBuffer, uint32_t lenBuffer)
|
||||
else if (rv>0) {
|
||||
/* data received */
|
||||
DBG_DEBUG(AQH_LOGDOMAIN, "Received %d bytes", (int) rv);
|
||||
// GWEN_Text_LogString((const char*) ptrBuffer, rv, NULL, GWEN_LoggerLevel_Error);
|
||||
return (int) rv;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#define AQH_MSG_READER_HEADER_SIZE 4
|
||||
#define AQH_MSG_READER_MINMSGSIZE 12
|
||||
#define AQH_MSG_READER_MAXMSGSIZE 10240
|
||||
#define AQH_MSG_READER_MAXMSGSIZE 20480
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
m_ipcd_values.h
|
||||
m_ipcd_getdata.h
|
||||
m_ipcd_setdata.h
|
||||
m_ipcd_getvalues.h
|
||||
</headers>
|
||||
|
||||
|
||||
@@ -67,6 +68,7 @@
|
||||
m_ipcd_values.c
|
||||
m_ipcd_getdata.c
|
||||
m_ipcd_setdata.c
|
||||
m_ipcd_getvalues.c
|
||||
</sources>
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static const char *_modeToChar(int mode);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@@ -37,6 +39,7 @@
|
||||
|
||||
AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
||||
uint32_t msgId, uint32_t refMsgId,
|
||||
int mode,
|
||||
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num)
|
||||
{
|
||||
AQH_MESSAGE *msg;
|
||||
@@ -49,6 +52,7 @@ AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_BEGIN, tsBegin, buf);
|
||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_END, tsEnd, buf);
|
||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_NUM, num, buf);
|
||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_MODE, mode, buf);
|
||||
|
||||
msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId,
|
||||
GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
|
||||
@@ -64,19 +68,22 @@ void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1
|
||||
char *valueName;
|
||||
uint64_t tsBegin;
|
||||
uint64_t tsEnd;
|
||||
uint64_t mode;
|
||||
|
||||
valueName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL):NULL;
|
||||
tsBegin=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0):0;
|
||||
tsEnd=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0):0;
|
||||
mode=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, 0):0;
|
||||
|
||||
GWEN_Buffer_AppendArgs(dbuf,
|
||||
"GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, tsBegin=%lu, tsEnd=%lu)\n",
|
||||
"GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, mode=%s, tsBegin=%lu, tsEnd=%lu)\n",
|
||||
AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)),
|
||||
sText?sText:"",
|
||||
AQH_IpcMessage_GetCode(msg),
|
||||
AQH_IpcMessage_GetProtoId(msg),
|
||||
AQH_IpcMessage_GetProtoVersion(msg),
|
||||
valueName?valueName:"<empty>",
|
||||
valueName?valueName:"<empty>",
|
||||
_modeToChar(mode),
|
||||
(unsigned long int) tsBegin,
|
||||
(unsigned long int) tsEnd);
|
||||
free(valueName);
|
||||
@@ -85,3 +92,15 @@ void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1
|
||||
|
||||
|
||||
|
||||
const char *_modeToChar(int mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case AQH_MSGDATA_GETDATA_MODE_FIRST: return "first";
|
||||
case AQH_MSGDATA_GETDATA_MODE_LAST: return "last";
|
||||
case AQH_MSGDATA_GETDATA_MODE_PERIOD: return "period";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,10 +24,20 @@
|
||||
#define AQH_MSGDATA_GETDATA_TAGS_BEGIN 0x0020
|
||||
#define AQH_MSGDATA_GETDATA_TAGS_END 0x0021
|
||||
#define AQH_MSGDATA_GETDATA_TAGS_NUM 0x0022
|
||||
#define AQH_MSGDATA_GETDATA_TAGS_MODE 0x0023
|
||||
|
||||
|
||||
enum {
|
||||
AQH_MSGDATA_GETDATA_MODE_FIRST=0,
|
||||
AQH_MSGDATA_GETDATA_MODE_LAST,
|
||||
AQH_MSGDATA_GETDATA_MODE_PERIOD
|
||||
};
|
||||
|
||||
|
||||
|
||||
AQHOME_API AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
||||
uint32_t msgId, uint32_t refMsgId,
|
||||
int mode,
|
||||
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num);
|
||||
|
||||
AQHOME_API void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList,
|
||||
|
||||
81
aqhome/msg/ipc/data/m_ipcd_getvalues.c
Normal file
81
aqhome/msg/ipc/data/m_ipcd_getvalues.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
* 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 "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
|
||||
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
||||
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||
#include "aqhome/msg/ipc/m_ipc.h"
|
||||
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/tag16.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementation
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
AQH_MESSAGE *AQH_IpcdMessageGetValues_new(uint16_t code, uint32_t msgId, uint32_t refMsgId,
|
||||
const char *deviceName, int modality)
|
||||
{
|
||||
AQH_MESSAGE *msg;
|
||||
GWEN_BUFFER *buf;
|
||||
|
||||
buf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
|
||||
if (deviceName && *deviceName)
|
||||
GWEN_Tag16_WriteStringTagToBuffer(AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME, deviceName, buf);
|
||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETVALUES_TAGS_MODALITY, modality, buf);
|
||||
|
||||
msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId,
|
||||
GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
|
||||
GWEN_Buffer_free(buf);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_IpcdMessageGetValues_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList,
|
||||
GWEN_BUFFER *dbuf, const char *sText)
|
||||
{
|
||||
char *deviceName;
|
||||
uint64_t modality;
|
||||
|
||||
deviceName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME, NULL):NULL;
|
||||
modality=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETVALUES_TAGS_MODALITY, 0):0;
|
||||
|
||||
GWEN_Buffer_AppendArgs(dbuf,
|
||||
"GETVALUES(%s) %s (code=%d, proto=%d, proto version=%d, device=%s, modality=%s)\n",
|
||||
AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)),
|
||||
sText?sText:"",
|
||||
AQH_IpcMessage_GetCode(msg),
|
||||
AQH_IpcMessage_GetProtoId(msg),
|
||||
AQH_IpcMessage_GetProtoVersion(msg),
|
||||
deviceName?deviceName:"<empty>",
|
||||
AQH_ValueModality_toString(modality));
|
||||
free(deviceName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
36
aqhome/msg/ipc/data/m_ipcd_getvalues.h
Normal file
36
aqhome/msg/ipc/data/m_ipcd_getvalues.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
* 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 AQH_M_IPCD_GETVALUES_H
|
||||
#define AQH_M_IPCD_GETVALUES_H
|
||||
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
#include <aqhome/ipc2/message.h>
|
||||
#include <aqhome/data/value.h>
|
||||
|
||||
#include <gwenhywfar/tag16.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MSGDATA_GETVALUES_TAGS_DEVICENAME 0x0001
|
||||
#define AQH_MSGDATA_GETVALUES_TAGS_MODALITY 0x0002
|
||||
|
||||
|
||||
|
||||
AQHOME_API AQH_MESSAGE *AQH_IpcdMessageGetValues_new(uint16_t code, uint32_t msgId, uint32_t refMsgId,
|
||||
const char *deviceName, int modality);
|
||||
|
||||
AQHOME_API void AQH_IpcdMessageGetValues_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList,
|
||||
GWEN_BUFFER *dbuf, const char *sText);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
|
||||
|
||||
#include "aqhome/aqhome.h"
|
||||
#include "aqhome/msg/node/m_value.h"
|
||||
#include "aqhome/msg/node/m_node.h"
|
||||
|
||||
@@ -102,19 +103,7 @@ uint16_t AQH_ValueMessage_GetValueDenom(const AQH_MESSAGE *msg)
|
||||
|
||||
const char *AQH_ValueMessage_GetValueTypeName(const AQH_MESSAGE *msg)
|
||||
{
|
||||
uint8_t t;
|
||||
|
||||
t=AQH_ValueMessage_GetValueType(msg);
|
||||
switch(t) {
|
||||
case AQH_MSG_VALUE_TYPE_TEMP: return "temperature";
|
||||
case AQH_MSG_VALUE_TYPE_HUMIDITY: return "humidity";
|
||||
case AQH_MSG_VALUE_TYPE_DOOR: return "door_window";
|
||||
case AQH_MSG_VALUE_TYPE_MOTION: return "motion";
|
||||
case AQH_MSG_VALUE_TYPE_CO2: return "CO2";
|
||||
case AQH_MSG_VALUE_TYPE_TVOC: return "TVOC";
|
||||
default: break;
|
||||
}
|
||||
return "unknown";
|
||||
return AQH_ValueModality_toString(AQH_ValueMessage_GetValueType(msg));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -100,6 +100,17 @@ AppNetwork_Every100ms_jump:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine AppNetwork_Every100ms @global
|
||||
;
|
||||
; @clobbers R16, R17, X
|
||||
|
||||
AppNetwork_EveryDay:
|
||||
bigjmp NET_Interface_ResetStats ; (R16, R17, X)
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine AppNetwork_HandleMsg @global
|
||||
;
|
||||
@@ -124,7 +135,7 @@ AppNetwork_HandleMsg_handleRangeMsg:
|
||||
rjmp AppNetwork_HandleMsg_clcRet
|
||||
|
||||
AppNetwork_HandleMsg_handleAddrMsg:
|
||||
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
||||
bigcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
||||
mov r16, r18
|
||||
subi r16, NETMSG_CMD_NEED_ADDRESS
|
||||
ldi zl, LOW(appNetworkMsgTable)
|
||||
@@ -175,18 +186,18 @@ appNetworkHandlePingRequest:
|
||||
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||
ld r17, X
|
||||
push r17
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
pop r17
|
||||
brcc appNetworkHandlePingRequest_end ; jmp on error
|
||||
push r16 ; buffer num
|
||||
mov r16, r17 ; DEST addr
|
||||
brcc appNetworkHandlePingRequest_end ; jmp on error
|
||||
push r16 ; buffer num
|
||||
mov r16, r17 ; DEST addr
|
||||
adiw xh:xl, 1
|
||||
ldi yl, LOW(netInterfaceData)
|
||||
ldi yh, HIGH(netInterfaceData)
|
||||
rcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
||||
bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
||||
sbiw xh:xl, 1
|
||||
pop r16 ; buffer num
|
||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
pop r16 ; buffer num
|
||||
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
appNetworkHandlePingRequest_end:
|
||||
ret
|
||||
|
||||
@@ -393,16 +404,16 @@ appNetworkHandleMsgDenyAddr_end:
|
||||
; @clobbers R16 (R17, R18, R19, R20, R21, X)
|
||||
|
||||
appNetworkSendAddrMsg:
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
brcc appNetworkSendAddrMsg_end
|
||||
adiw xh:xl, 1
|
||||
push r16
|
||||
rcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||
pop r16
|
||||
sbiw xh:xl, 1
|
||||
rcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||
brcs appNetworkSendAddrMsg_end
|
||||
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||
clc
|
||||
appNetworkSendAddrMsg_end:
|
||||
ret
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||
|
||||
AppNetwork_SendTxdStats:
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
brcc AppNetwork_SendTxdStats_end
|
||||
push r16
|
||||
adiw xh:xl, 1
|
||||
rcall NETMSG_SendStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
bigcall NETMSG_SendStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
sbiw xh:xl, 1
|
||||
pop r16
|
||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
AppNetwork_SendTxdStats_end:
|
||||
ret
|
||||
; @end
|
||||
@@ -39,14 +39,14 @@ AppNetwork_SendTxdStats_end:
|
||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||
|
||||
AppNetwork_SendRxdStats:
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
brcc AppNetwork_SendRxdStats_end
|
||||
push r16
|
||||
adiw xh:xl, 1
|
||||
rcall NETMSG_RecvStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
bigcall NETMSG_RecvStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
sbiw xh:xl, 1
|
||||
pop r16
|
||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
AppNetwork_SendRxdStats_end:
|
||||
ret
|
||||
; @end
|
||||
@@ -60,14 +60,14 @@ AppNetwork_SendRxdStats_end:
|
||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||
|
||||
AppNetwork_SendMemStats:
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
brcc AppNetwork_SendMemStats_end
|
||||
push r16
|
||||
adiw xh:xl, 1
|
||||
rcall NETMSG_MemStats_Write ; (R16, R17, R18, R19, R20, R21)
|
||||
bigcall NETMSG_MemStats_Write ; (R16, R17, R18, R19, R20, R21)
|
||||
sbiw xh:xl, 1
|
||||
pop r16
|
||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
AppNetwork_SendMemStats_end:
|
||||
ret
|
||||
; @end
|
||||
@@ -81,14 +81,14 @@ AppNetwork_SendMemStats_end:
|
||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||
|
||||
AppNetwork_SendDevice:
|
||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||
brcc AppNetwork_SendDevice_end
|
||||
push r16
|
||||
adiw xh:xl, 1
|
||||
rcall NETMSG_Device_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
bigcall NETMSG_Device_Write ; (R16, R17, R18, R19, R20, R21, Z)
|
||||
sbiw xh:xl, 1
|
||||
pop r16
|
||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||
AppNetwork_SendDevice_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
.equ APP_REPORT_SENSORS_INTERVAL_SECS = 60
|
||||
.equ APP_REPORT_SENSORS_INTERVAL_SECS = 120
|
||||
|
||||
|
||||
|
||||
@@ -78,35 +78,45 @@ AppReportSensors_OnEverySecond_store:
|
||||
#ifdef MODULES_SI7021
|
||||
cpi r16, 1
|
||||
breq AppReportSensors_OnEverySecond_measureValue1
|
||||
cpi r16, 19
|
||||
cpi r16, 11
|
||||
breq AppReportSensors_OnEverySecond_measureValue2
|
||||
cpi r16, 39
|
||||
cpi r16, 16
|
||||
breq AppReportSensors_OnEverySecond_sendValue1
|
||||
cpi r16, 49
|
||||
cpi r16, 21
|
||||
breq AppReportSensors_OnEverySecond_sendValue2
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SGP40
|
||||
cpi r16, 27
|
||||
cpi r16, 32
|
||||
breq AppReportSensors_OnEverySecond_measureValue4
|
||||
cpi r16, 55
|
||||
cpi r16, 42
|
||||
breq AppReportSensors_OnEverySecond_sendValue4
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SGP30
|
||||
cpi r16, 29
|
||||
breq AppReportSensors_OnEverySecond_measureValue5
|
||||
cpi r16, 57
|
||||
cpi r16, 53
|
||||
breq AppReportSensors_OnEverySecond_sendValue5
|
||||
cpi r16, 59
|
||||
cpi r16, 63
|
||||
breq AppReportSensors_OnEverySecond_sendValue6
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_DS18B20
|
||||
cpi r16, 9
|
||||
cpi r16, 84
|
||||
breq AppReportSensors_OnEverySecond_sendValue3
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
cpi r16, 94
|
||||
breq AppReportSensors_OnEverySecond_sendCCS811_TVOC
|
||||
cpi r16, 104
|
||||
breq AppReportSensors_OnEverySecond_sendCCS811_CO2
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_BRIGHTNESS
|
||||
cpi r16, 97
|
||||
breq AppReportSensors_OnEverySecond_sendBrightness
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
#ifdef MODULES_SI7021
|
||||
@@ -133,13 +143,23 @@ AppReportSensors_OnEverySecond_sendValue3:
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SGP30
|
||||
AppReportSensors_OnEverySecond_measureValue5:
|
||||
rjmp SGP30_Measure
|
||||
AppReportSensors_OnEverySecond_sendValue5:
|
||||
rjmp SGP30_SendTVOC
|
||||
ret
|
||||
AppReportSensors_OnEverySecond_sendValue6:
|
||||
rjmp SGP30_SendCO2
|
||||
AppReportSensors_OnEverySecond_sendValue5:
|
||||
rjmp SGP30_SendTVOC
|
||||
ret
|
||||
AppReportSensors_OnEverySecond_sendValue6:
|
||||
rjmp SGP30_SendCO2
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
AppReportSensors_OnEverySecond_sendCCS811_TVOC:
|
||||
rjmp CCS811_SendTVOC
|
||||
AppReportSensors_OnEverySecond_sendCCS811_CO2:
|
||||
rjmp CCS811_SendCO2
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_BRIGHTNESS
|
||||
AppReportSensors_OnEverySecond_sendBrightness:
|
||||
rjmp Brightness_Send
|
||||
#endif
|
||||
|
||||
; @end
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
.equ APP_STATS_INTERVAL_MINS = 11
|
||||
.equ APP_STATS_INTERVAL_MINS = 31
|
||||
|
||||
|
||||
|
||||
@@ -75,67 +75,94 @@ AppStats_OnEveryMinute_store:
|
||||
sts appStatsTimer, r16
|
||||
ldi yl, LOW(netInterfaceData)
|
||||
ldi yh, HIGH(netInterfaceData)
|
||||
|
||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
|
||||
ldi xl, LOW(netInterfaceData)
|
||||
ldi xh, HIGH(netInterfaceData)
|
||||
cpi r16, 1
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 2
|
||||
breq AppStats_OnEveryMinute_sendPacketsIn
|
||||
cpi r16, 3
|
||||
breq AppStats_OnEveryMinute_sendPacketsOut
|
||||
cpi r16, 4
|
||||
breq AppStats_OnEveryMinute_sendContentErrs
|
||||
breq AppStats_OnEveryMinute_sendPacketsIn
|
||||
cpi r16, 5
|
||||
breq AppStats_OnEveryMinute_sendIoErrs
|
||||
breq AppStats_OnEveryMinute_sendPacketsOut
|
||||
cpi r16, 6
|
||||
breq AppStats_OnEveryMinute_sendNoBufErrs
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 7
|
||||
breq AppStats_OnEveryMinute_sendCollisionErrs
|
||||
cpi r16, 8
|
||||
breq AppStats_OnEveryMinute_sendBusyErrs
|
||||
#ifdef MODULES_HEAP
|
||||
breq AppStats_OnEveryMinute_sendContentErrs
|
||||
cpi r16, 9
|
||||
breq AppStats_OnEveryMinute_sendHeapUsed
|
||||
breq AppStats_OnEveryMinute_sendIoErrs
|
||||
cpi r16, 10
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 11
|
||||
breq AppStats_OnEveryMinute_sendNoBufErrs
|
||||
cpi r16, 13
|
||||
breq AppStats_OnEveryMinute_sendCollisionErrs
|
||||
cpi r16, 14
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 15
|
||||
breq AppStats_OnEveryMinute_sendBusyErrs
|
||||
|
||||
#ifdef APP_STATS_NETDEV2
|
||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN2
|
||||
ldi xl, LOW(netInterfaceData2)
|
||||
ldi xh, HIGH(netInterfaceData2)
|
||||
cpi r16, 16
|
||||
breq AppStats_OnEveryMinute_sendPacketsIn
|
||||
cpi r16, 17
|
||||
breq AppStats_OnEveryMinute_sendPacketsOut
|
||||
cpi r16, 18
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 19
|
||||
breq AppStats_OnEveryMinute_sendContentErrs
|
||||
cpi r16, 20
|
||||
breq AppStats_OnEveryMinute_sendIoErrs
|
||||
cpi r16, 21
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 22
|
||||
breq AppStats_OnEveryMinute_sendNoBufErrs
|
||||
cpi r16, 23
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
cpi r16, 24
|
||||
breq AppStats_OnEveryMinute_sendCollisionErrs
|
||||
cpi r16, 25
|
||||
breq AppStats_OnEveryMinute_sendBusyErrs
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_HEAP
|
||||
cpi r16, 26
|
||||
breq AppStats_OnEveryMinute_sendHeapUsed
|
||||
cpi r16, 27
|
||||
breq AppStats_OnEveryMinute_sendHeapfree
|
||||
#endif
|
||||
cpi r16, 28
|
||||
breq AppStats_OnEveryMinute_sendDevice
|
||||
ret
|
||||
|
||||
AppStats_OnEveryMinute_sendDevice:
|
||||
rjmp AppNetwork_SendDevice
|
||||
|
||||
AppStats_OnEveryMinute_sendPacketsIn:
|
||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
|
||||
ldd r18, Y+NET_IFACE_OFFS_PACKETSIN_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_PACKETSIN_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 0
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendPacketsOut:
|
||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_OUT
|
||||
ldd r18, Y+NET_IFACE_OFFS_PACKETSOUT_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_PACKETSOUT_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 1
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendContentErrs:
|
||||
ldi r17, AQHOME_VALUEID_STATS_ERRS_CONTENT
|
||||
ldd r18, Y+NET_IFACE_OFFS_ERR_CONTENT_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_ERR_CONTENT_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 2
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendIoErrs:
|
||||
ldi r17, AQHOME_VALUEID_STATS_ERRS_IO
|
||||
ldd r18, Y+NET_IFACE_OFFS_ERR_IO_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_ERR_IO_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 3
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendNoBufErrs:
|
||||
ldi r17, AQHOME_VALUEID_STATS_ERRS_NOBUF
|
||||
ldd r18, Y+NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_ERR_NOBUF_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 4
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendCollisionErrs:
|
||||
ldi r17, AQHOME_VALUEID_STATS_ERRS_COLLISIONS
|
||||
ldd r18, Y+NET_IFACE_OFFS_ERR_COLLISIONS_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_ERR_COLLISIONS_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 5
|
||||
rjmp appStatsSendDeviceStat
|
||||
AppStats_OnEveryMinute_sendBusyErrs:
|
||||
ldi r17, AQHOME_VALUEID_STATS_ERRS_BUSY
|
||||
ldd r18, Y+NET_IFACE_OFFS_ERR_BUSY_LOW
|
||||
ldd r19, Y+NET_IFACE_OFFS_ERR_BUSY_HIGH
|
||||
rjmp appStatsSend16BitValue
|
||||
ldi r16, 6
|
||||
rjmp appStatsSendDeviceStat
|
||||
|
||||
#ifdef MODULES_HEAP
|
||||
AppStats_OnEveryMinute_sendHeapUsed:
|
||||
ldi r17, AQHOME_VALUEID_STATS_HEAP_USED
|
||||
@@ -152,6 +179,30 @@ AppStats_OnEveryMinute_sendHeapfree:
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine AppStats_OnEveryMinute @global
|
||||
;
|
||||
; @param r16 index into device table (e.g. 0 for NET_IFACE_OFFS_PACKETSIN_LOW)
|
||||
; @param r17 offset to first value id (e.g. AQHOME_VALUEID_STATS_PACKETS_IN for device 0,
|
||||
; AQHOME_VALUEID_STATS_PACKETS_IN2 for device 1)
|
||||
; @param Y pointer to device to send data to
|
||||
; @param X pointer to device to inspect
|
||||
|
||||
appStatsSendDeviceStat:
|
||||
add r17, r16
|
||||
lsl r16
|
||||
adiw xh:xl, NET_IFACE_OFFS_PACKETSIN_LOW
|
||||
add xl, r16
|
||||
adc xh, r16
|
||||
sub xh, r16
|
||||
ld r18, X+
|
||||
ld r19, X
|
||||
rjmp appStatsSend16BitValue
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine AppStats_OnEveryMinute @global
|
||||
;
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
wait_50us.asm
|
||||
watchdog.asm
|
||||
list.asm
|
||||
list_t.asm
|
||||
tree.asm
|
||||
tree_t.asm
|
||||
</extradist>
|
||||
|
||||
</gwbuild>
|
||||
|
||||
@@ -54,11 +54,26 @@ List_InitObject:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine List_FiniObject @global
|
||||
;
|
||||
; @param Y pointer to object
|
||||
; @clobbers r16
|
||||
|
||||
List_FiniObject:
|
||||
clr r16 ; set this->NEXT to NULL
|
||||
std Y+LIST_OFFS_NEXT_LO, r16
|
||||
std Y+LIST_OFFS_NEXT_HI, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine List_GetNextObject @global
|
||||
|
||||
; @param Y pointer to object
|
||||
; @return X pointer to parent object
|
||||
; @return X pointer to successor object
|
||||
; @clobbers none
|
||||
|
||||
List_GetNextObject:
|
||||
@@ -101,13 +116,13 @@ List_GetPredecessorFor:
|
||||
cp r16, yl
|
||||
brne List_GetPredecessorFor_next
|
||||
cp r17, yh
|
||||
breq List_GetLastObject_haveIt
|
||||
breq List_GetPredecessorFor_haveIt
|
||||
List_GetPredecessorFor_next:
|
||||
mov xl, r16
|
||||
mov xh, r17
|
||||
rjmp List_GetPredecessorFor
|
||||
List_GetPredecessorFor_haveIt:
|
||||
sbiw xh:xl, 1
|
||||
sbiw xh:xl, 2
|
||||
List_GetPredecessorFor_ret:
|
||||
ret
|
||||
; @end
|
||||
@@ -127,8 +142,14 @@ List_AddObject:
|
||||
rcall List_GetLastObject ; (r16, r17, X, Y)
|
||||
pop yh
|
||||
pop yl
|
||||
st X+, yl ; WID_OFFS_WNEXT_LO
|
||||
st X+, yh ; WID_OFFS_WNEXT_HI
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
clc
|
||||
breq List_AddObject_ret
|
||||
st X+, yl ; LIST_OFFS_NEXT_LO
|
||||
st X+, yh ; LIST_OFFS_NEXT_HI
|
||||
sec
|
||||
List_AddObject_ret:
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -163,4 +184,68 @@ List_UnlinkObject_ret:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine List_UnlinkAllObjects
|
||||
|
||||
; @param Y pointer to first object in a list
|
||||
; @clobbers r16, r17, r18, Y
|
||||
|
||||
List_UnlinkAllObjects:
|
||||
clr r18
|
||||
List_UnlinkAllObjects_loop:
|
||||
ldd r16, Y+LIST_OFFS_NEXT_LO
|
||||
ldd r17, Y+LIST_OFFS_NEXT_HI
|
||||
std Y+LIST_OFFS_NEXT_LO, r18
|
||||
std Y+LIST_OFFS_NEXT_HI, r18
|
||||
mov yl, r16
|
||||
mov yh, r17
|
||||
or r16, r17
|
||||
brne List_UnlinkAllObjects_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine List_ForEveryObject
|
||||
;
|
||||
; Calls the given function for every object until it
|
||||
; returns with a set carry flag or until the full list
|
||||
; is handled.
|
||||
; Registers that can be used by the given function are all
|
||||
; except R16, R18 and R19 (those are used by this routine).
|
||||
;
|
||||
; @param Y pointer to first object in a list
|
||||
; @param Z routine to call for every object
|
||||
; @clobbers r16, r17, r18, r19, X, Y (r24, r25)
|
||||
|
||||
List_ForEveryObject:
|
||||
List_ForEveryObject_loop:
|
||||
ldd r18, Y+LIST_OFFS_NEXT_LO ; next
|
||||
ldd r19, Y+LIST_OFFS_NEXT_HI ; next
|
||||
clr r16
|
||||
std Y+LIST_OFFS_NEXT_LO, r16
|
||||
std Y+LIST_OFFS_NEXT_HI, r16
|
||||
push r18 ; next
|
||||
push r19 ; next
|
||||
rcall List_ForEveryObject_callZ
|
||||
pop r19 ; next
|
||||
pop r18 ; next
|
||||
brcs List_ForEveryObject_ret
|
||||
mov yl, r18
|
||||
mov yh, r19
|
||||
or r18, r19
|
||||
brne List_ForEveryObject_loop
|
||||
List_ForEveryObject_ret:
|
||||
ret
|
||||
List_ForEveryObject_callZ:
|
||||
ijmp
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif ; AQH_AVR_COMMON_LIST_H
|
||||
|
||||
240
avr/common/list_t.asm
Normal file
240
avr/common/list_t.asm
Normal file
@@ -0,0 +1,240 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2025 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
#ifndef AQH_AVR_COMMON_LIST_T_H
|
||||
#define AQH_AVR_COMMON_LIST_T_H
|
||||
|
||||
|
||||
|
||||
.equ LIST_TEST_OBJECT_OFFS_LIST = 0
|
||||
.equ LIST_TEST_OBJECT_OFFS_VALUE1 = LIST_SIZE
|
||||
.equ LIST_TEST_OBJECT_OFFS_VALUE2 = LIST_SIZE+1
|
||||
.equ LIST_TEST_OBJECT_SIZE = LIST_SIZE+2
|
||||
|
||||
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
listTest_list: .byte 2
|
||||
listTest_object1: .byte LIST_TEST_OBJECT_SIZE
|
||||
listTest_object2: .byte LIST_TEST_OBJECT_SIZE
|
||||
listTest_object3: .byte LIST_TEST_OBJECT_SIZE
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine listTest_Object_Init
|
||||
; @param Y pointer to object to init
|
||||
; @param r18 value 1
|
||||
; @param r19 value 2
|
||||
|
||||
listTest_Object_Init:
|
||||
bigcall List_InitObject ; (R16)
|
||||
std Y+LIST_TEST_OBJECT_OFFS_VALUE1, r18
|
||||
std Y+LIST_TEST_OBJECT_OFFS_VALUE2, r19
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
listTest1:
|
||||
ldi yl, LOW(listTest_object1)
|
||||
ldi yh, HIGH(listTest_object1)
|
||||
ldi r18, 1
|
||||
ldi r19, 2
|
||||
rcall listTest_Object_Init
|
||||
sts listTest_list, yl
|
||||
sts listTest_list+1, yh
|
||||
mov xl, yl ; X=listTest_object1
|
||||
mov xh, yh
|
||||
|
||||
ldi yl, LOW(listTest_object2)
|
||||
ldi yh, HIGH(listTest_object2)
|
||||
ldi r18, 3
|
||||
ldi r19, 4
|
||||
rcall listTest_Object_Init
|
||||
|
||||
; X=object 1, Y=object 2
|
||||
bigcall List_AddObject ; (r16, r17, x)
|
||||
|
||||
lds yl, listTest_list
|
||||
lds yh, listTest_list+1
|
||||
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 1
|
||||
ldi r16, 1
|
||||
brne listTest1_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 2
|
||||
ldi r16, 2
|
||||
brne listTest1_error
|
||||
|
||||
bigcall List_GetNextObject
|
||||
ldi r16, 3
|
||||
cpi xl, LOW(listTest_object2)
|
||||
brne listTest1_error
|
||||
cpi xh, HIGH(listTest_object2)
|
||||
brne listTest1_error
|
||||
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 3
|
||||
ldi r16, 4
|
||||
brne listTest1_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 4
|
||||
ldi r16, 5
|
||||
brne listTest1_error
|
||||
|
||||
bigcall List_GetNextObject
|
||||
mov r16, xh
|
||||
or r16, xl
|
||||
ldi r16, 6
|
||||
brne listTest1_error
|
||||
sec
|
||||
ret
|
||||
listTest1_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
listTest2:
|
||||
lds xl, listTest_list
|
||||
lds xh, listTest_list+1
|
||||
|
||||
ldi yl, LOW(listTest_object3)
|
||||
ldi yh, HIGH(listTest_object3)
|
||||
ldi r18, 5
|
||||
ldi r19, 6
|
||||
rcall listTest_Object_Init
|
||||
|
||||
; X=object 1, Y=object 2
|
||||
bigcall List_AddObject ; (r16, r17, x)
|
||||
|
||||
mov xl, yl
|
||||
mov xh, yh
|
||||
bigcall List_GetLastObject
|
||||
ldi r16, 1
|
||||
cpi xl, LOW(listTest_object3)
|
||||
brne listTest2_error
|
||||
cpi xh, HIGH(listTest_object3)
|
||||
brne listTest2_error
|
||||
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 5
|
||||
ldi r16, 2
|
||||
brne listTest2_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 6
|
||||
ldi r16, 3
|
||||
brne listTest2_error
|
||||
|
||||
sec
|
||||
ret
|
||||
listTest2_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
listTest3:
|
||||
lds xl, listTest_list
|
||||
lds xh, listTest_list+1
|
||||
ldi yl, LOW(listTest_object2)
|
||||
ldi yh, HIGH(listTest_object2)
|
||||
bigcall List_UnlinkObject
|
||||
|
||||
lds yl, listTest_list
|
||||
lds yh, listTest_list+1
|
||||
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 1
|
||||
ldi r16, 1
|
||||
brne listTest3_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 2
|
||||
ldi r16, 2
|
||||
brne listTest3_error
|
||||
|
||||
bigcall List_GetNextObject
|
||||
ldi r16, 3
|
||||
cpi xl, LOW(listTest_object3)
|
||||
brne listTest3_error
|
||||
cpi xh, HIGH(listTest_object3)
|
||||
brne listTest3_error
|
||||
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 5
|
||||
ldi r16, 4
|
||||
brne listTest3_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 6
|
||||
ldi r16, 5
|
||||
brne listTest3_error
|
||||
|
||||
bigcall List_GetNextObject
|
||||
mov r16, xh
|
||||
or r16, xl
|
||||
ldi r16, 6
|
||||
brne listTest3_error
|
||||
sec
|
||||
ret
|
||||
listTest3_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
listTest4:
|
||||
lds xl, listTest_list
|
||||
lds xh, listTest_list+1
|
||||
ldi yl, LOW(listTest_object3)
|
||||
ldi yh, HIGH(listTest_object3)
|
||||
bigcall List_UnlinkObject
|
||||
|
||||
lds yl, listTest_list
|
||||
lds yh, listTest_list+1
|
||||
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 1
|
||||
ldi r16, 1
|
||||
brne listTest4_error
|
||||
ldd r16, Y+LIST_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 2
|
||||
ldi r16, 2
|
||||
brne listTest4_error
|
||||
|
||||
bigcall List_GetNextObject
|
||||
mov r16, xh
|
||||
or r16, xl
|
||||
ldi r16, 6
|
||||
brne listTest4_error
|
||||
sec
|
||||
ret
|
||||
listTest4_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -17,10 +17,10 @@
|
||||
; defs
|
||||
|
||||
.equ TREE_OFFS_LIST = 0
|
||||
.equ TREE_OFFS_WPARENT_LO = TREE_OFFS_LIST+LIST_SIZE
|
||||
.equ TREE_OFFS_WPARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
|
||||
.equ TREE_OFFS_WCHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
|
||||
.equ TREE_OFFS_WCHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
|
||||
.equ TREE_OFFS_PARENT_LO = TREE_OFFS_LIST+LIST_SIZE
|
||||
.equ TREE_OFFS_PARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
|
||||
.equ TREE_OFFS_CHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
|
||||
.equ TREE_OFFS_CHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
|
||||
.equ TREE_SIZE = TREE_OFFS_LIST+LIST_SIZE+4
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@
|
||||
Tree_InitObject:
|
||||
rcall List_InitObject ; (R16)
|
||||
clr r16 ; clear this->TREE data
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_LO, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_HI, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_LO, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_HI, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_LO, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_HI, r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -59,8 +59,8 @@ Tree_InitObject:
|
||||
; @clobbers none
|
||||
|
||||
Tree_GetParentObject:
|
||||
ldd xl, Y+TREE_OFFS_WPARENT_LO
|
||||
ldd xh, Y+TREE_OFFS_WPARENT_HI
|
||||
ldd xl, Y+TREE_OFFS_PARENT_LO
|
||||
ldd xh, Y+TREE_OFFS_PARENT_HI
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -74,13 +74,46 @@ Tree_GetParentObject:
|
||||
; @clobbers none
|
||||
|
||||
Tree_GetFirstChildObject:
|
||||
ldd xl, Y+TREE_OFFS_WCHILD_LO
|
||||
ldd xh, Y+TREE_OFFS_WCHILD_HI
|
||||
ldd xl, Y+TREE_OFFS_CHILD_LO
|
||||
ldd xh, Y+TREE_OFFS_CHILD_HI
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Tree_GetLastChildObject @global
|
||||
|
||||
; @param Y pointer to object
|
||||
; @return X pointer to last child object
|
||||
; @clobbers none
|
||||
|
||||
Tree_GetLastChildObject:
|
||||
ldd xl, Y+TREE_OFFS_CHILD_LO
|
||||
ldd xh, Y+TREE_OFFS_CHILD_HI
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
breq Tree_GetLastChildObject_ret
|
||||
rcall List_GetLastObject
|
||||
Tree_GetLastChildObject_ret:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Tree_GetNextSibling @global
|
||||
|
||||
; @param Y pointer to object
|
||||
; @return X pointer to successor object
|
||||
; @clobbers none
|
||||
|
||||
Tree_GetNextSibling:
|
||||
rjmp List_GetNextObject
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Tree_GetObjectBelow @global
|
||||
|
||||
@@ -101,7 +134,7 @@ treeGetObjectBelow:
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
brne treeGetObjectBelow_ret ; got one
|
||||
rcall List_GetNextObject
|
||||
rcall Tree_GetNextSibling
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
brne treeGetObjectBelow_ret ; got one
|
||||
@@ -122,27 +155,27 @@ treeGetObjectBelow_ret:
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine Tree_AddChildObject @global
|
||||
|
||||
; @param X pointer to parent to add to
|
||||
; @param Y pointer to object to add
|
||||
; @param X pointer to parent to add to
|
||||
; @clobbers r16, r17, r18, x
|
||||
|
||||
Tree_AddChildObject:
|
||||
std Y+TREE_OFFS_WPARENT_LO, xl ; immediately store parent pointer
|
||||
std Y+TREE_OFFS_WPARENT_HI, xh
|
||||
adiw xh:xl, TREE_OFFS_WCHILD_LO
|
||||
std Y+TREE_OFFS_PARENT_LO, xl ; immediately store parent pointer
|
||||
std Y+TREE_OFFS_PARENT_HI, xh
|
||||
adiw xh:xl, TREE_OFFS_CHILD_LO ; read pointer to first child
|
||||
ld r16, X+
|
||||
ld r17, X
|
||||
mov r18, r16
|
||||
or r18, r17
|
||||
brne Tree_AddChildObject_addToChildList
|
||||
st X, yh ; no child, set THIS as first
|
||||
st X, yh ; no child, set THIS as first
|
||||
st -X, yl
|
||||
sbiw xh:xl, WID_OFFS_TREE+TREE_OFFS_WCHILD_LO
|
||||
sbiw xh:xl, TREE_OFFS_CHILD_LO
|
||||
ret
|
||||
Tree_AddChildObject_addToChildList:
|
||||
mov xl, r16
|
||||
mov xl, r16 ; X=first child
|
||||
mov xh, r17
|
||||
rjmp List_AddObject
|
||||
rjmp List_AddObject ; add Y as new object
|
||||
; @end
|
||||
|
||||
|
||||
@@ -154,17 +187,17 @@ Tree_AddChildObject_addToChildList:
|
||||
; @clobbers r16, r17, x
|
||||
|
||||
Tree_UnlinkObject:
|
||||
ldd xl, Y+TREE_OFFS_WPARENT_LO
|
||||
ldd xh, Y+TREE_OFFS_WPARENT_HI
|
||||
ldd xl, Y+TREE_OFFS_PARENT_LO
|
||||
ldd xh, Y+TREE_OFFS_PARENT_HI
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
breq Tree_UnlinkObject_ret ; not part of a tree
|
||||
adiw xh:xl, TREE_OFFS_WCHILD_LO ; get parent's first child to R17:R16
|
||||
adiw xh:xl, TREE_OFFS_CHILD_LO ; get parent's first child to R17:R16
|
||||
ld r16, X+
|
||||
ld r17, X
|
||||
cp r16, yl ; same as THIS?
|
||||
brne Tree_UnlinkObject_inList ; nope, need to check childList
|
||||
cp r17, yh
|
||||
cp r17, yh ; same as THIS?
|
||||
brne Tree_UnlinkObject_inList ; nope, need to check childList
|
||||
ldd r16, Y+TREE_OFFS_LIST+LIST_OFFS_NEXT_HI ; is first child, set this->NEXT as new first child
|
||||
st X, r16
|
||||
@@ -177,8 +210,8 @@ Tree_UnlinkObject_inList:
|
||||
rcall List_UnlinkObject ; (R16, R17, X)
|
||||
Tree_UnlinkObject_clrParentAndSibling:
|
||||
clr r16 ; clear this->PARENT
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
|
||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
|
||||
std Y+TREE_OFFS_PARENT_LO, r16
|
||||
std Y+TREE_OFFS_PARENT_HI, r16
|
||||
std Y+LIST_OFFS_NEXT_LO, r16
|
||||
std Y+LIST_OFFS_NEXT_HI, r16 ; clear this->NEXT
|
||||
Tree_UnlinkObject_ret:
|
||||
@@ -188,5 +221,6 @@ Tree_UnlinkObject_ret:
|
||||
|
||||
|
||||
|
||||
|
||||
#endif ; AQH_AVR_COMMON_TREE_H
|
||||
|
||||
|
||||
381
avr/common/tree_t.asm
Normal file
381
avr/common/tree_t.asm
Normal file
@@ -0,0 +1,381 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2025 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
.equ TREE_TEST_OBJECT_OFFS_LIST = 0
|
||||
.equ TREE_TEST_OBJECT_OFFS_VALUE1 = TREE_SIZE
|
||||
.equ TREE_TEST_OBJECT_OFFS_VALUE2 = TREE_SIZE+1
|
||||
.equ TREE_TEST_OBJECT_SIZE = TREE_SIZE+2
|
||||
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
testTree_root: .byte TREE_TEST_OBJECT_SIZE
|
||||
testTree_child1: .byte TREE_TEST_OBJECT_SIZE
|
||||
testTree_child2: .byte TREE_TEST_OBJECT_SIZE
|
||||
testTree_child3: .byte TREE_TEST_OBJECT_SIZE
|
||||
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine treeTest_Object_Init
|
||||
; @param Y pointer to object to init
|
||||
; @param r18 value 1
|
||||
; @param r19 value 2
|
||||
|
||||
treeTest_Object_Init:
|
||||
bigcall Tree_InitObject ; (R16)
|
||||
std Y+TREE_TEST_OBJECT_OFFS_VALUE1, r18
|
||||
std Y+TREE_TEST_OBJECT_OFFS_VALUE2, r19
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
treeTest1:
|
||||
ldi yl, LOW(testTree_root)
|
||||
ldi yh, HIGH(testTree_root)
|
||||
ldi r18, 1
|
||||
ldi r19, 2
|
||||
rcall treeTest_Object_Init
|
||||
mov xl, yl
|
||||
mov xh, yh
|
||||
|
||||
rcall treeTestCreateAndAddChild1
|
||||
ldi r16, 1 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
rcall treeTestCreateAndAddChild2
|
||||
ldi r16, 2 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
rcall treeTestCreateAndAddChild3
|
||||
ldi r16, 3 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
ldi yl, LOW(testTree_root)
|
||||
ldi yh, HIGH(testTree_root)
|
||||
bigcall Tree_GetFirstChildObject
|
||||
ldi r16, 4 ; error code
|
||||
cpi xl, LOW(testTree_child1)
|
||||
brne treeTest1_error
|
||||
cpi xh, HIGH(testTree_child1)
|
||||
brne treeTest1_error
|
||||
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
ldd r16, Y+TREE_TEST_OBJECT_OFFS_VALUE1
|
||||
cpi r16, 3
|
||||
ldi r16, 5 ; error code
|
||||
brne treeTest1_error
|
||||
ldd r16, Y+TREE_TEST_OBJECT_OFFS_VALUE2
|
||||
cpi r16, 4
|
||||
ldi r16, 6 ; error code
|
||||
brne treeTest1_error
|
||||
|
||||
rcall treeTestNextSiblingIs2
|
||||
ldi r16, 7 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
rcall treeTestNextSiblingIs3
|
||||
ldi r16, 8 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
rcall treeTestNextSiblingIsNull
|
||||
ldi r16, 9 ; error code
|
||||
brcc treeTest1_error
|
||||
|
||||
sec
|
||||
ret
|
||||
|
||||
treeTest1_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
treeTest2:
|
||||
ldi yl, LOW(testTree_child2)
|
||||
ldi yh, HIGH(testTree_child2)
|
||||
bigcall Tree_UnlinkObject
|
||||
|
||||
rcall treeTestCheckParentNull
|
||||
ldi r16, 1 ; error code
|
||||
brcc treeTest2_error
|
||||
|
||||
bigcall Tree_GetNextSibling
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
ldi r16, 2 ; error code
|
||||
brne treeTest2_error
|
||||
|
||||
ldi yl, LOW(testTree_root)
|
||||
ldi yh, HIGH(testTree_root)
|
||||
bigcall Tree_GetFirstChildObject
|
||||
ldi r16, 3 ; error code
|
||||
cpi xl, LOW(testTree_child1)
|
||||
brne treeTest2_error
|
||||
cpi xh, HIGH(testTree_child1)
|
||||
brne treeTest2_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
|
||||
rcall treeTestNextSiblingIs3
|
||||
ldi r16, 4 ; error code
|
||||
brcc treeTest2_error
|
||||
|
||||
sec
|
||||
ret
|
||||
treeTest2_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
treeTest3:
|
||||
ldi yl, LOW(testTree_child1)
|
||||
ldi yh, HIGH(testTree_child1)
|
||||
bigcall Tree_UnlinkObject
|
||||
|
||||
rcall treeTestCheckParentNull
|
||||
ldi r16, 1 ; error code
|
||||
brcc treeTest3_error
|
||||
|
||||
bigcall Tree_GetNextSibling
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
ldi r16, 2 ; error code
|
||||
brne treeTest3_error
|
||||
|
||||
ldi yl, LOW(testTree_root)
|
||||
ldi yh, HIGH(testTree_root)
|
||||
bigcall Tree_GetFirstChildObject
|
||||
ldi r16, 3 ; error code
|
||||
cpi xl, LOW(testTree_child3)
|
||||
brne treeTest3_error
|
||||
cpi xh, HIGH(testTree_child3)
|
||||
brne treeTest3_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
|
||||
rcall treeTestNextSiblingIsNull
|
||||
ldi r16, 4 ; error code
|
||||
brcc treeTest3_error
|
||||
|
||||
sec
|
||||
ret
|
||||
treeTest3_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
treeTest4:
|
||||
ldi yl, LOW(testTree_child1)
|
||||
ldi yh, HIGH(testTree_child1)
|
||||
ldi xl, LOW(testTree_root)
|
||||
ldi xh, HIGH(testTree_root)
|
||||
bigcall Tree_AddChildObject
|
||||
|
||||
rcall treeTestCheckParentRoot
|
||||
ldi r16, 1 ; error code
|
||||
brcc treeTest4_error
|
||||
|
||||
ldi yl, LOW(testTree_root)
|
||||
ldi yh, HIGH(testTree_root)
|
||||
bigcall Tree_GetFirstChildObject
|
||||
ldi r16, 2 ; error code
|
||||
cpi xl, LOW(testTree_child3)
|
||||
brne treeTest4_error
|
||||
cpi xh, HIGH(testTree_child3)
|
||||
brne treeTest4_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
|
||||
rcall treeTestNextSiblingIs1
|
||||
ldi r16, 3 ; error code
|
||||
brcc treeTest4_error
|
||||
|
||||
rcall treeTestNextSiblingIsNull
|
||||
ldi r16, 4 ; error code
|
||||
brcc treeTest4_error
|
||||
|
||||
sec
|
||||
ret
|
||||
treeTest4_error:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
treeTestCreateAndAddChild1:
|
||||
ldi yl, LOW(testTree_child1)
|
||||
ldi yh, HIGH(testTree_child1)
|
||||
ldi r18, 3
|
||||
ldi r19, 4
|
||||
rcall treeTest_Object_Init
|
||||
|
||||
ldi xl, LOW(testTree_root)
|
||||
ldi xh, HIGH(testTree_root)
|
||||
bigcall Tree_AddChildObject
|
||||
|
||||
rcall treeTestCheckParentRoot
|
||||
brcc treeTestCreateAndAddChild1_error
|
||||
sec
|
||||
ret
|
||||
treeTestCreateAndAddChild1_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
treeTestCreateAndAddChild2:
|
||||
ldi yl, LOW(testTree_child2)
|
||||
ldi yh, HIGH(testTree_child2)
|
||||
ldi r18, 5
|
||||
ldi r19, 6
|
||||
rcall treeTest_Object_Init
|
||||
|
||||
ldi xl, LOW(testTree_root)
|
||||
ldi xh, HIGH(testTree_root)
|
||||
bigcall Tree_AddChildObject
|
||||
|
||||
rcall treeTestCheckParentRoot
|
||||
brcc treeTestCreateAndAddChild2_error
|
||||
sec
|
||||
ret
|
||||
treeTestCreateAndAddChild2_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
treeTestCreateAndAddChild3:
|
||||
ldi yl, LOW(testTree_child3)
|
||||
ldi yh, HIGH(testTree_child3)
|
||||
ldi r18, 7
|
||||
ldi r19, 8
|
||||
rcall treeTest_Object_Init
|
||||
|
||||
ldi xl, LOW(testTree_root)
|
||||
ldi xh, HIGH(testTree_root)
|
||||
bigcall Tree_AddChildObject
|
||||
|
||||
rcall treeTestCheckParentRoot
|
||||
brcc treeTestCreateAndAddChild3_error
|
||||
sec
|
||||
ret
|
||||
treeTestCreateAndAddChild3_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
treeTestCheckParentNull:
|
||||
bigcall Tree_GetParentObject
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
brne treeTestCheckParentNull_error
|
||||
sec
|
||||
ret
|
||||
treeTestCheckParentNull_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
treeTestCheckParentRoot:
|
||||
bigcall Tree_GetParentObject
|
||||
cpi xl, LOW(testTree_root)
|
||||
brne treeTestCheckParentRoot_error
|
||||
cpi xh, HIGH(testTree_root)
|
||||
brne treeTestCheckParentRoot_error
|
||||
sec
|
||||
ret
|
||||
treeTestCheckParentRoot_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
treeTestNextSiblingIs1:
|
||||
bigcall Tree_GetNextSibling
|
||||
cpi xl, LOW(testTree_child1)
|
||||
brne treeTestNextSiblingIs1_error
|
||||
cpi xh, HIGH(testTree_child1)
|
||||
brne treeTestNextSiblingIs1_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
sec
|
||||
ret
|
||||
treeTestNextSiblingIs1_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
treeTestNextSiblingIs2:
|
||||
bigcall Tree_GetNextSibling
|
||||
cpi xl, LOW(testTree_child2)
|
||||
brne treeTestNextSiblingIs2_error
|
||||
cpi xh, HIGH(testTree_child2)
|
||||
brne treeTestNextSiblingIs2_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
sec
|
||||
ret
|
||||
treeTestNextSiblingIs2_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
treeTestNextSiblingIs3:
|
||||
bigcall Tree_GetNextSibling
|
||||
cpi xl, LOW(testTree_child3)
|
||||
brne treeTestNextSiblingIs3_error
|
||||
cpi xh, HIGH(testTree_child3)
|
||||
brne treeTestNextSiblingIs3_error
|
||||
mov yl, xl
|
||||
mov yh, xh
|
||||
sec
|
||||
ret
|
||||
treeTestNextSiblingIs3_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
treeTestNextSiblingIsNull:
|
||||
bigcall Tree_GetNextSibling
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
brne treeTestNextSiblingIsNull_error
|
||||
sec
|
||||
ret
|
||||
treeTestNextSiblingIsNull_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -26,13 +26,19 @@
|
||||
all
|
||||
c01
|
||||
c02
|
||||
n14
|
||||
n16
|
||||
n19
|
||||
n20
|
||||
n21
|
||||
n22
|
||||
n23
|
||||
n24
|
||||
n25
|
||||
n26
|
||||
n27
|
||||
r04
|
||||
r05
|
||||
t03
|
||||
</subdirs>
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
.equ AQHOME_VALUETYPE_CO2 = 7
|
||||
.equ AQHOME_VALUETYPE_TVOC = 8
|
||||
.equ AQHOME_VALUETYPE_STATS = 9
|
||||
.equ AQHOME_VALUETYPE_LIGHT = 10
|
||||
|
||||
|
||||
; Value Ids
|
||||
@@ -31,11 +32,21 @@
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_NOBUF = 0xe4
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_COLLISIONS = 0xe5
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_BUSY = 0xe6
|
||||
.equ AQHOME_VALUEID_STATS_HEAP_USED = 0xe7
|
||||
.equ AQHOME_VALUEID_STATS_HEAP_FREE = 0xe8
|
||||
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_MSGSIZE = 0xe7
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_MISSED = 0xe8
|
||||
|
||||
.equ AQHOME_VALUEID_STATS_PACKETS_IN2 = 0xe9
|
||||
.equ AQHOME_VALUEID_STATS_PACKETS_OUT2 = 0xea
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_CONTENT2 = 0xeb
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_IO2 = 0xec
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_NOBUF2 = 0xed
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_COLLISIONS2 = 0xee
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_BUSY2 = 0xef
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_MSGSIZE2 = 0xf0
|
||||
.equ AQHOME_VALUEID_STATS_ERRS_MISSED2 = 0xf1
|
||||
|
||||
.equ AQHOME_VALUEID_STATS_HEAP_USED = 0xf2
|
||||
.equ AQHOME_VALUEID_STATS_HEAP_FREE = 0xf3
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
systemInitHardware:
|
||||
; set all ports as inputs and enable internal pull-up resistors
|
||||
ldi r16, 0xff
|
||||
; ldi r16, 0xff
|
||||
clr r17
|
||||
|
||||
out DDRA, r17 ; all input
|
||||
sts PUEA, r16 ; enable pull-up on all
|
||||
outr DDRA, r17 ; all input
|
||||
outr PUEA, r17 ; disable pull-up on all
|
||||
|
||||
out DDRB, r17 ; all input
|
||||
sts PUEB, r16 ; enable pull-up on all
|
||||
outr DDRB, r17 ; all input
|
||||
outr PUEB, r17 ; disable pull-up on all
|
||||
|
||||
ret
|
||||
; @end
|
||||
@@ -50,6 +50,22 @@ systemSetSpeed:
|
||||
clr r16 ; SUT=0, CLKPS=0
|
||||
sts CCP, r17
|
||||
sts CLKPR, r16
|
||||
|
||||
#if 0
|
||||
; read and set calibration data
|
||||
push r15
|
||||
inr r15, SREG
|
||||
cli
|
||||
ldi zl, 0
|
||||
ldi zh, 1
|
||||
ldi r16, (1<<RSIG) | (1<<SPMEN)
|
||||
outr SPMCSR, r16
|
||||
lpm r17, Z
|
||||
outr OSCCAL0, r17
|
||||
outr SREG, r15
|
||||
pop r15
|
||||
#endif
|
||||
|
||||
.endif
|
||||
|
||||
ret
|
||||
@@ -118,16 +134,16 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
|
||||
|
||||
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
||||
.ifdef TIFR0
|
||||
out TIFR0, r16
|
||||
outr TIFR0, r16
|
||||
.else
|
||||
out TIFR, r16
|
||||
outr TIFR, r16
|
||||
.endif
|
||||
|
||||
ldi r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
|
||||
.ifdef TIMSK0
|
||||
out TIMSK0, r16
|
||||
outr TIMSK0, r16
|
||||
.else
|
||||
out TIMSK, r16
|
||||
outr TIMSK, r16
|
||||
.endif
|
||||
sec
|
||||
ret
|
||||
|
||||
@@ -68,20 +68,31 @@
|
||||
|
||||
|
||||
#ifdef MODULES_COMONUART0
|
||||
.include "modules/uart_hw/defs.asm"
|
||||
.include "modules/uart_hw/lowlevel.asm"
|
||||
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||
.include "modules/uart_hw/comonuart0.asm"
|
||||
;.include "modules/uart_hw/defs.asm"
|
||||
;.include "modules/uart_hw/lowlevel.asm"
|
||||
;.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||
;.include "modules/uart_hw/comonuart0.asm"
|
||||
.include "modules/uart_hw2/defs.asm"
|
||||
.include "modules/uart_hw2/comonuart0.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COMONUART1
|
||||
;.include "modules/uart_hw/defs.asm"
|
||||
;.include "modules/uart_hw/lowlevel.asm"
|
||||
;.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||
;.include "modules/uart_hw/comonuart1.asm"
|
||||
.include "modules/uart_hw2/defs.asm"
|
||||
.include "modules/uart_hw2/comonuart1.asm"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_TTYONUART1
|
||||
#ifndef MODULES_COMONUART0
|
||||
.include "modules/uart_hw/defs.asm"
|
||||
.include "modules/uart_hw/lowlevel.asm"
|
||||
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||
#endif
|
||||
.include "modules/uart_hw/ttyonuart1.asm"
|
||||
;.include "modules/uart_hw2/defs.asm"
|
||||
;.include "modules/uart_hw2/ttyonuart1.asm"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -144,6 +155,9 @@
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
.include "modules/ccs811/main.asm"
|
||||
#ifdef MODULES_NETWORK
|
||||
.include "modules/ccs811/send.asm"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TCRT1000
|
||||
@@ -157,6 +171,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_LCD
|
||||
.include "modules/lcd/main.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_ILI9341
|
||||
.include "modules/lcd2/ili9341/defs.asm"
|
||||
.include "modules/lcd2/ili9341/main.asm"
|
||||
@@ -165,6 +183,21 @@
|
||||
.include "modules/lcd2/ili9341/text.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_FONT
|
||||
.include "modules/lcd2/font/defs.asm"
|
||||
.include "modules/lcd2/font/main.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_WIN
|
||||
.include "common/list.asm"
|
||||
.include "common/tree.asm"
|
||||
.include "modules/lcd2/win/defs.asm"
|
||||
.include "modules/lcd2/win/object.asm"
|
||||
.include "modules/lcd2/win/widget.asm"
|
||||
.include "modules/lcd2/win/gui.asm"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_FONT_8X8
|
||||
.include "modules/lcd2/font/defs.asm"
|
||||
.include "modules/lcd2/font/font8x8.asm"
|
||||
@@ -177,6 +210,14 @@
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_BRIGHTNESS
|
||||
.include "modules/brightness/main.asm"
|
||||
#ifdef MODULES_NETWORK
|
||||
.include "modules/brightness/send.asm"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef APPS_MOTION
|
||||
.include "modules/f_keepup/main.asm"
|
||||
.include "modules/valsched/main.asm"
|
||||
|
||||
@@ -107,10 +107,17 @@ onSystemTimerTick:
|
||||
bigcall ComOnUart0_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COMONUART1
|
||||
bigcall ComOnUart1_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TCRT1000
|
||||
bigcall TCRT1K_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_BRIGHTNESS
|
||||
bigcall Brightness_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef APPS_NETWORK
|
||||
ldi yl, LOW(netInterfaceData)
|
||||
@@ -145,6 +152,11 @@ sysOnEverySecond:
|
||||
#ifdef APPS_REPORTSENSORS
|
||||
bigcall AppReportSensors_OnEverySecond
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SGP30
|
||||
bigcall SGP30_EverySecond
|
||||
#endif
|
||||
|
||||
bigjmp onEverySecond
|
||||
; @end
|
||||
|
||||
@@ -154,6 +166,10 @@ sysOnEveryMinute:
|
||||
bigcall AppStats_OnEveryMinute
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
bigcall CCS811_OnEveryMinute
|
||||
#endif
|
||||
|
||||
bigjmp onEveryMinute
|
||||
; @end
|
||||
|
||||
@@ -164,6 +180,12 @@ sysOnEveryHour:
|
||||
|
||||
|
||||
sysOnEveryDay:
|
||||
#ifdef APPS_NETWORK
|
||||
ldi yl, LOW(netInterfaceData)
|
||||
ldi yh, HIGH(netInterfaceData)
|
||||
bigcall AppNetwork_EveryDay
|
||||
#endif
|
||||
|
||||
bigjmp onEveryDay
|
||||
; @end
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ initModules:
|
||||
bigcall ComOnUart0_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COMONUART1
|
||||
bigcall ComOnUart1_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_MOTION
|
||||
bigcall Motion_Init
|
||||
#endif
|
||||
@@ -148,6 +152,10 @@ initModules:
|
||||
bigcall ILI9341_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_BRIGHTNESS
|
||||
bigcall Brightness_Init
|
||||
#endif
|
||||
|
||||
|
||||
; done
|
||||
ret
|
||||
@@ -190,6 +198,10 @@ runModules_ComEnd:
|
||||
bigcall ComOnUart0_Run
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COMONUART1
|
||||
bigcall ComOnUart1_Run
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_STATS
|
||||
bigcall Stats_Run
|
||||
#endif
|
||||
@@ -211,6 +223,7 @@ runModules_ComEnd:
|
||||
; rcall TCRT1K_Run
|
||||
#endif
|
||||
|
||||
|
||||
; add more modules here
|
||||
ret
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
.include "./data.asm"
|
||||
|
||||
.include "devices/all/defs.asm"
|
||||
.include "common/calls.asm"
|
||||
.include "common/utils_wait.asm"
|
||||
.include "common/utils_io.asm"
|
||||
|
||||
|
||||
@@ -33,20 +33,13 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; generic
|
||||
|
||||
.equ STACK_SIZE = 256
|
||||
|
||||
.equ NET_BUFFERS_NUM = 8
|
||||
.equ NET_BUFFERS_SIZE = 32
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; heap
|
||||
|
||||
.equ HEAP_START = SRAM_START+0x200
|
||||
.equ HEAP_SIZE = SRAM_SIZE-HEAP_START
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings including list of modules used
|
||||
|
||||
@@ -61,9 +54,8 @@
|
||||
#define MODULES_UART_BITBANG
|
||||
#define MODULES_SPI_HW
|
||||
#define MODULES_ILI9341
|
||||
;#define MODULES_FONT_8X8
|
||||
#define MODULES_FONT_6X8
|
||||
;#define MODULES_UART_BITBANG
|
||||
#define MODULES_FONT
|
||||
#define MODULES_WIN
|
||||
;#define MODULES_TWI_MASTER
|
||||
;#define MODULES_LCD
|
||||
;#define LCD_MINIMAL_FONT
|
||||
@@ -175,6 +167,7 @@ irqNotSet:
|
||||
; @routine onSystemStart
|
||||
|
||||
onSystemStart:
|
||||
bigcall test
|
||||
ret
|
||||
; @end
|
||||
|
||||
@@ -226,8 +219,18 @@ onEveryLoop:
|
||||
.include "devices/all/hw_m644p.asm"
|
||||
.include "devices/all/includes.asm"
|
||||
|
||||
.include "common/debug.asm"
|
||||
;.include "common/debug.asm"
|
||||
|
||||
;.include "modules/lcd2/font/font2.asm"
|
||||
;.include "modules/lcd2/font/font3.asm"
|
||||
;.include "modules/lcd2/font/font16x26.asm"
|
||||
;.include "modules/lcd2/font/font4.asm"
|
||||
;.include "modules/lcd2/font/font12x16.asm"
|
||||
.include "modules/lcd2/font/font5.asm"
|
||||
.include "modules/lcd2/font/font12x20.asm"
|
||||
;.include "common/list_t.asm"
|
||||
.include "common/tree_t.asm"
|
||||
.include "common/divide.asm"
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
@@ -238,3 +241,210 @@ onEveryLoop:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; @param %0 X
|
||||
; @param %1 Y
|
||||
; @param %2 W
|
||||
; @param %3 H
|
||||
.macro M_FILL_RECT
|
||||
ldi r16, LOW(@0) ; X0
|
||||
mov r4, r16
|
||||
ldi r16, HIGH(@0)
|
||||
mov r5, r16
|
||||
|
||||
ldi r16, LOW(@1) ; Y0
|
||||
mov r6, r16
|
||||
ldi r16, HIGH(@1)
|
||||
mov r7, r16
|
||||
|
||||
ldi r16, LOW(@2) ; W
|
||||
mov r8, r16
|
||||
ldi r16, HIGH(@2)
|
||||
mov r9, r16
|
||||
|
||||
ldi r16, LOW(@3) ; H
|
||||
mov r10, r16
|
||||
ldi r16, HIGH(@3)
|
||||
mov r11, r16
|
||||
|
||||
bigcall ILI9341_FillRect
|
||||
.endmacro
|
||||
|
||||
|
||||
|
||||
|
||||
test:
|
||||
; set foreground (r3:r2)
|
||||
; 0bRRRRRGGGGGGBBBBB
|
||||
ldi r16, 0b11111111
|
||||
mov r3, r16
|
||||
ldi r16, 0b11111111 ; white
|
||||
mov r2, r16
|
||||
M_FILL_RECT 0, 0, 319, 239
|
||||
|
||||
; set foreground (r3:r2)
|
||||
ldi r16, 0b00000000
|
||||
mov r3, r16
|
||||
ldi r16, 0b00011111 ; blue
|
||||
mov r2, r16
|
||||
M_FILL_RECT 0, 0, 319, 32
|
||||
|
||||
; set background (r1:r0)
|
||||
mov r0, r2
|
||||
mov r1, r3
|
||||
|
||||
; set foreground (r3:r2)
|
||||
ldi r16, 0b11111111
|
||||
mov r3, r16
|
||||
ldi r16, 0b11111111 ; white
|
||||
mov r2, r16
|
||||
|
||||
; set Xpos
|
||||
ldi r16, LOW(10)
|
||||
mov r4, r16
|
||||
ldi r16, HIGH(10)
|
||||
mov r5, r16
|
||||
|
||||
; setYpos
|
||||
ldi r16, LOW(3)
|
||||
mov r6, r16
|
||||
ldi r16, HIGH(3)
|
||||
mov r7, r16
|
||||
|
||||
; set font
|
||||
; ldi zl, LOW(font3_16x26*2)
|
||||
; ldi zh, HIGH(font3_16x26*2)
|
||||
ldi zl, LOW(font5_12x20*2)
|
||||
ldi zh, HIGH(font5_12x20*2)
|
||||
|
||||
; set buffer
|
||||
ldi xl, LOW(glyphBuffer)
|
||||
ldi xh, HIGH(glyphBuffer)
|
||||
|
||||
; write characters
|
||||
ldi r16, 'A'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
ldi r16, 'Q'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
ldi r16, 'H'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
ldi r16, 'O'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
ldi r16, 'M'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
ldi r16, 'E'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
#if 0
|
||||
push xl
|
||||
push xh
|
||||
rcall listTest1
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall listTest2
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall listTest3
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall listTest4
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
push xl
|
||||
push xh
|
||||
rcall treeTest1
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall treeTest2
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall treeTest3
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
push xl
|
||||
push xh
|
||||
rcall treeTest4
|
||||
pop xh
|
||||
pop xl
|
||||
brcc test_error
|
||||
ldi r16, '!'
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
test_error:
|
||||
ldi r17, '0'
|
||||
add r16, r17
|
||||
bigcall ili9341_WriteCharacterX1At
|
||||
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
helloWorld: .db "Hello World", 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
glyphBuffer: .byte 1024
|
||||
heapStart:
|
||||
|
||||
|
||||
.equ HEAP_START = heapStart
|
||||
.equ HEAP_SIZE = (SRAM_SIZE-STACK_SIZE)-HEAP_START
|
||||
|
||||
|
||||
@@ -2,51 +2,21 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n14_main" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
n14_main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target type="AvrHexFile" name="n14_boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
n14_boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
boot
|
||||
main
|
||||
</subdirs>
|
||||
|
||||
<data dist="true" install="$(datadir)/aqhome/devices/nodes">
|
||||
aqua_n14.xml
|
||||
</data>
|
||||
|
||||
|
||||
<extradist>
|
||||
n14_defs.asm
|
||||
defs.asm
|
||||
README
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
|
||||
14
avr/devices/n14/README
Normal file
14
avr/devices/n14/README
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
N14
|
||||
===
|
||||
|
||||
- Role: LED strip controller
|
||||
- MCU: AtTiny85
|
||||
- Connection: RJ45
|
||||
- UART: uart_bitbang2
|
||||
- Periphery:
|
||||
- LED strip connection (SK6812)
|
||||
- OWI interface
|
||||
- DS18B20 temperature sensor
|
||||
- Modules:
|
||||
- MA_LIGHT: motion activated light
|
||||
@@ -14,6 +14,16 @@
|
||||
<value name="MALONTIME" id="0x85" type="actor" dataType="uint16" />
|
||||
<value name="MALSOURCE1" id="0x86" type="actor" dataType="uint16" />
|
||||
<value name="MALSOURCE2" id="0x87" type="actor" dataType="uint16" />
|
||||
|
||||
<value name="stats_packets_in" id="0xe0" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_packets_out" id="0xe1" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_content_errors" id="0xe2" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_io_errors" id="0xe3" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_nobuf_errors" id="0xe4" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_collision_errors" id="0xe5" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_busy_errors" id="0xe6" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="LEDTIMING" id="0x88" type="actor" dataType="uint16" />
|
||||
</values>
|
||||
|
||||
</device>
|
||||
32
avr/devices/n14/boot/0BUILD
Normal file
32
avr/devices/n14/boot/0BUILD
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n14_boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
@@ -14,30 +14,19 @@
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "n14_defs.asm"
|
||||
.include "defs_all.asm"
|
||||
|
||||
|
||||
#define COM_ACCEPT_ALL_DEST
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; generic
|
||||
.include "version.asm"
|
||||
.include "../defs.asm"
|
||||
.include "devices/all/defs.asm"
|
||||
|
||||
.include "common/calls.asm"
|
||||
.include "common/utils_wait.asm"
|
||||
.include "modules/com2/defs.asm"
|
||||
.include "modules/comproto/defs.asm"
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings
|
||||
|
||||
.equ FIRMWARE_VERSION_MAJOR = 0
|
||||
.equ FIRMWARE_VERSION_MINOR = 0
|
||||
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
@@ -95,8 +84,7 @@ firmwareStart: rjmp main ; will be overwritten when flashing
|
||||
|
||||
|
||||
main:
|
||||
rjmp bootLoader ; this routine is in modules/flash/proto.asm
|
||||
|
||||
rjmp bootLoader ; this routine is in modules/bootloader/main.asm
|
||||
|
||||
|
||||
|
||||
@@ -112,6 +100,7 @@ main:
|
||||
.include "modules/flash/io.asm"
|
||||
.include "modules/flash/io_attn.asm"
|
||||
.include "modules/flash/io_bitbang.asm"
|
||||
.include "modules/flash/flashxp.asm"
|
||||
.include "modules/flash/flash1p.asm"
|
||||
.include "modules/flash/flashprocess.asm"
|
||||
.include "modules/flash/wait.asm"
|
||||
@@ -138,72 +127,3 @@ systemSetSpeed:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
DEBUG1:
|
||||
ldi r19, 50
|
||||
ldi r20, 1
|
||||
ldi r21, 9
|
||||
rcall blinkLed
|
||||
rjmp DEBUG1
|
||||
|
||||
|
||||
DEBUG2:
|
||||
ldi r19, 50
|
||||
ldi r20, 1
|
||||
ldi r21, 1
|
||||
rcall blinkLed
|
||||
rjmp DEBUG2
|
||||
|
||||
|
||||
|
||||
; @param r19 loop count
|
||||
; @param r20 on time
|
||||
; @param r21 off time
|
||||
; @clobbers (R16, R18, R22, R24, R25)
|
||||
|
||||
blinkLed:
|
||||
cbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; on
|
||||
mov r22, r20
|
||||
rcall waitForMultiple100ms ; (R252
|
||||
sbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; off
|
||||
mov r22, r21
|
||||
rcall waitForMultiple100ms ; (R22)
|
||||
dec r19
|
||||
brne blinkLed
|
||||
ret
|
||||
|
||||
|
||||
; @param r22 number of 100ms periods to wait
|
||||
waitForMultiple100ms:
|
||||
waitForMultiple100ms_loop:
|
||||
push r22
|
||||
rcall waitFor100ms
|
||||
pop r22
|
||||
dec r22
|
||||
brne waitForMultiple100ms_loop
|
||||
ret
|
||||
|
||||
|
||||
waitFor100ms:
|
||||
ldi r22, 10
|
||||
waitFor100ms_loop:
|
||||
push r22
|
||||
rcall waitFor10ms
|
||||
pop r22
|
||||
dec r22
|
||||
brne waitFor100ms_loop
|
||||
ret
|
||||
|
||||
waitFor10ms:
|
||||
ldi r22, 100
|
||||
waitFor10ms_loop:
|
||||
push r22
|
||||
rcall Utils_WaitFor100MicroSecs
|
||||
pop r22
|
||||
dec r22
|
||||
brne waitFor10ms_loop
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2024 by Martin Preuss
|
||||
; copyright : (C) 2025 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
@@ -39,6 +39,7 @@
|
||||
.equ LED_SIMPLE_OFFTIME = 30
|
||||
.equ LED_SIMPLE_DDR = DDRB
|
||||
.equ LED_SIMPLE_PORT = PORTB
|
||||
.equ LED_SIMPLE_PORTIN = PINB
|
||||
.equ LED_SIMPLE_PINNUM = PORTB4
|
||||
|
||||
|
||||
33
avr/devices/n14/main/0BUILD
Normal file
33
avr/devices/n14/main/0BUILD
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n14_firmware" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
208
avr/devices/n14/main/main.asm
Normal file
208
avr/devices/n14/main/main.asm
Normal file
@@ -0,0 +1,208 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2024 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; Source file for LED controller node on AtTiny 85
|
||||
;
|
||||
; This is for the full system (i.e. not the boot loader).
|
||||
; ***************************************************************************
|
||||
|
||||
.equ clock=8000000 ; Define the clock frequency
|
||||
|
||||
|
||||
|
||||
.nolist
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "version.asm"
|
||||
.include "../defs.asm"
|
||||
;.include "./data.asm"
|
||||
|
||||
.include "devices/all/defs.asm"
|
||||
|
||||
.include "common/calls.asm"
|
||||
.include "common/utils_wait.asm"
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; generic
|
||||
|
||||
.equ NET_BUFFERS_NUM = 6
|
||||
.equ NET_BUFFERS_SIZE = 32
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings including list of modules used
|
||||
|
||||
#define MODULES_CLOCK
|
||||
#define MODULES_LED_SIMPLE
|
||||
#define MODULES_NETWORK
|
||||
#define MODULES_UART_BITBANG
|
||||
#define MODULES_OWI_MASTER
|
||||
#define MODULES_DS18B20
|
||||
#define MODULES_SK6812
|
||||
;#define MODULES_MOTION_LIGHT
|
||||
|
||||
#define APPS_NETWORK
|
||||
#define APPS_REPORTSENSORS
|
||||
#define APPS_STATS
|
||||
#define APPS_MA_LIGHT
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for modules
|
||||
|
||||
;.equ VALUE_ID_SI7021_TEMP = 0x01
|
||||
;.equ VALUE_ID_SI7021_HUM = 0x02
|
||||
|
||||
;.equ VALUE_ID_ADC = 0x03
|
||||
;.equ VALUE_ID_REED1 = 0x04
|
||||
;.equ VALUE_ID_REED2 = 0x05
|
||||
.equ VALUE_ID_DS18B20_TEMP = 0x06
|
||||
|
||||
;.equ VALUE_ID_REED_CONF = 0x81
|
||||
.equ VALUE_ID_LED_NUMLEDS = 0x82
|
||||
.equ VALUE_ID_LED_RGBW_VALUE = 0x83
|
||||
.equ VALUE_ID_MAL_RGBW_VALUE = 0x84
|
||||
.equ VALUE_ID_MAL_ONTIME = 0x85
|
||||
.equ VALUE_ID_MAL_SOURCE1 = 0x86
|
||||
.equ VALUE_ID_MAL_SOURCE2 = 0x87
|
||||
|
||||
.equ VALUE_ID_LEDSIMPLE_TIMING = 0x88
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code segment
|
||||
|
||||
.cseg
|
||||
.org 000000
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reset and interrupt vectors
|
||||
|
||||
rjmp BOOTLOADER_ADDR ; Reset vector ; use this for flashed system
|
||||
reti ; EXT_INT0
|
||||
rjmp UART_BitBang_PcintIsr ; PCI0
|
||||
reti ; OC1A
|
||||
reti ; OVF1
|
||||
reti ; OVF0
|
||||
reti ; ERDY
|
||||
reti ; ACI
|
||||
reti ; ADCC
|
||||
reti ; OC1B
|
||||
rjmp baseTimerIrqOC0A ; OC0A
|
||||
reti ; OC0B
|
||||
reti ; WATCHDOG
|
||||
reti ; USI_STR
|
||||
reti ; USI_OVF
|
||||
|
||||
|
||||
devInfoBlock: ; 12 bytes
|
||||
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
|
||||
devInfoId: .db DEVICEINFO_ID, 0
|
||||
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
|
||||
firmwareVersion: .db FIRMWARE_VARIANT_LEDSTRIPS, FIRMWARE_VERSION_MAJOR
|
||||
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine firmwareStart @global
|
||||
|
||||
firmwareStart:
|
||||
rjmp main
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onSystemStart
|
||||
|
||||
onSystemStart:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onMessageReceived
|
||||
;
|
||||
; Called on every message received
|
||||
|
||||
onMessageReceived:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onEvery100ms
|
||||
;
|
||||
; Called every 100ms. Add your routine calls here. No arguments, no results.
|
||||
|
||||
onEvery100ms:
|
||||
onEveryMinute:
|
||||
onEveryHour:
|
||||
onEveryDay:
|
||||
ret
|
||||
; @end
|
||||
|
||||
onEverySecond:
|
||||
ret
|
||||
; debug
|
||||
ldi r19, 0x00 ; G
|
||||
ldi r18, 0xff ; R
|
||||
ldi r20, 0x55 ; B
|
||||
ldi r21, 0xaa ; W
|
||||
rcall SK6812_SetAllColor ; r23 (r16, r17)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onEveryLoop
|
||||
;
|
||||
; Called on every loop (i.e. after awakening from sleep).
|
||||
;
|
||||
onEveryLoop:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; includes
|
||||
|
||||
.include "devices/all/hw_tn85.asm"
|
||||
.include "devices/all/includes.asm"
|
||||
.include "common/debug.asm"
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for network interface
|
||||
|
||||
.equ netInterfaceData = uart_bitbang_iface
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2024 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; Source file for LED controller node on AtTiny 85
|
||||
;
|
||||
; This is for the full system (i.e. not the boot loader).
|
||||
; ***************************************************************************
|
||||
|
||||
.equ clock=8000000 ; Define the clock frequency
|
||||
|
||||
|
||||
|
||||
.nolist
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "n14_defs.asm"
|
||||
.include "defs_all.asm"
|
||||
.include "common/utils_wait.asm" ; wait macro
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings including list of modules used
|
||||
|
||||
.equ FIRMWARE_VERSION_MAJOR = 0
|
||||
.equ FIRMWARE_VERSION_MINOR = 0
|
||||
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
|
||||
|
||||
|
||||
#define MODULES_TIMER
|
||||
#define MODULES_COM
|
||||
#define MODULES_COM_WITH_ADDR_PROTO
|
||||
#define MODULES_LED_SIMPLE
|
||||
#define MODULES_STATS
|
||||
#define MODULES_OWI_MASTER
|
||||
#define MODULES_DS18B20
|
||||
#define MODULES_SK6812
|
||||
#define MODULES_MOTION_LIGHT
|
||||
|
||||
; #define COM_ACCEPT_ALL_DEST
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for modules
|
||||
|
||||
;.equ VALUE_ID_SI7021_TEMP = 0x01
|
||||
;.equ VALUE_ID_SI7021_HUM = 0x02
|
||||
|
||||
;.equ VALUE_ID_ADC = 0x03
|
||||
;.equ VALUE_ID_REED1 = 0x04
|
||||
;.equ VALUE_ID_REED2 = 0x05
|
||||
.equ VALUE_ID_DS18B20_TEMP = 0x06
|
||||
|
||||
;.equ VALUE_ID_REED_CONF = 0x81
|
||||
.equ VALUE_ID_LED_NUMLEDS = 0x82
|
||||
.equ VALUE_ID_LED_RGBW_VALUE = 0x83
|
||||
.equ VALUE_ID_MAL_RGBW_VALUE = 0x84
|
||||
.equ VALUE_ID_MAL_ONTIME = 0x85
|
||||
.equ VALUE_ID_MAL_SOURCE1 = 0x86
|
||||
.equ VALUE_ID_MAL_SOURCE2 = 0x87
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code segment
|
||||
|
||||
.cseg
|
||||
.org 000000
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reset and interrupt vectors
|
||||
|
||||
rjmp BOOTLOADER_ADDR ; Reset vector ; use this for flashed system
|
||||
reti ; EXT_INT0
|
||||
rjmp uartBitbangIsrPcint0 ; PCI0
|
||||
reti ; OC1A
|
||||
reti ; OVF1
|
||||
reti ; OVF0
|
||||
reti ; ERDY
|
||||
reti ; ACI
|
||||
reti ; ADCC
|
||||
reti ; OC1B
|
||||
rjmp baseTimerIrqOC0A ; OC0A
|
||||
reti ; OC0B
|
||||
reti ; WATCHDOG
|
||||
reti ; USI_STR
|
||||
reti ; USI_OVF
|
||||
|
||||
|
||||
devInfoBlock: ; 12 bytes
|
||||
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
|
||||
devInfoId: .db DEVICEINFO_ID, 0
|
||||
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
|
||||
firmwareVersion: .db FIRMWARE_VARIANT_LEDSTRIPS, FIRMWARE_VERSION_MAJOR
|
||||
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
|
||||
|
||||
firmwareStart: rjmp main
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; includes
|
||||
|
||||
.include "common/utils.asm"
|
||||
.include "common/utils_wait_fixed.asm"
|
||||
.include "common/utils_copy_from_flash.asm"
|
||||
.include "common/utils_copy_sdram.asm"
|
||||
.include "common/crc8.asm"
|
||||
|
||||
.include "modules/basetimer/main.asm"
|
||||
|
||||
#ifdef MODULES_TIMER
|
||||
.include "modules/timer/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_LED_SIMPLE
|
||||
.include "modules/led_simple/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_COM
|
||||
.include "modules/com2/defs.asm"
|
||||
.include "modules/com2/main.asm"
|
||||
.include "modules/com2/buffer.asm"
|
||||
#ifdef MODULES_STATS
|
||||
.include "modules/comproto/msg_recvstats.asm"
|
||||
.include "modules/comproto/msg_sendstats.asm"
|
||||
.include "modules/comproto/msg_sysstats.asm"
|
||||
.include "modules/comproto/msg_memstats.asm"
|
||||
#endif
|
||||
.include "modules/comproto/msg_pong.asm"
|
||||
.include "modules/comproto/msg_value.asm"
|
||||
.include "modules/comproto/msg_device.asm"
|
||||
.include "modules/comproto/msg_reboot.asm"
|
||||
.include "modules/uart_bitbang/defs.asm"
|
||||
.include "modules/uart_bitbang/main.asm"
|
||||
.include "modules/uart_bitbang/bytelevel.asm"
|
||||
.include "modules/uart_bitbang/packetlevel.asm"
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
.include "modules/comproto/defs.asm"
|
||||
.include "modules/comproto/main.asm"
|
||||
.include "modules/comproto/addr.asm"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MODULES_STATS
|
||||
.include "modules/stats/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_OWI_MASTER
|
||||
.include "modules/owimaster/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_DS18B20
|
||||
.include "modules/ds18b20/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_SK6812
|
||||
.include "modules/sk6812/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
.include "modules/ma_light/main.asm"
|
||||
#endif
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data in SRAM
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
#ifdef MODULES_DS18B20
|
||||
sramDs18b20Timer: .byte 2
|
||||
sramSendDs18b20TempTimer: .byte 2
|
||||
#endif
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data in FLASH
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; timer list
|
||||
|
||||
|
||||
timerList:
|
||||
; SRAM variable/counter routine flags secs (0=don't start or restart)
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
.dw cproAddresModeTimer, CPRO_Address_OnTimer, 0, 0 ; (no restart)
|
||||
#endif
|
||||
#ifdef MODULES_STATS
|
||||
.dw statsSendTimer, Stats_Timer, TIMER_FLAGS_IF_ADDR, 9000 ; every 15m
|
||||
#endif
|
||||
#ifdef MODULES_DS18B20
|
||||
.dw sramDs18b20Timer, Ds18b20_OnTimer, 0, 300 ; every 30s
|
||||
.dw sramSendDs18b20TempTimer, sendDs18b20Temp, TIMER_FLAGS_IF_ADDR, 600 ; every 60s
|
||||
#endif
|
||||
.dw 0 ; end of list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.include "main_all.asm"
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called early on system startup. No arguments, no results.
|
||||
|
||||
systemSetSpeed:
|
||||
.if clock == 1000000
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, (1<<CLKPS1) | (1<<CLKPS0)
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
.endif
|
||||
|
||||
.if clock == 8000000
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, 0
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
.endif
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called just before rebooting to bootloader. No arguments, no results.
|
||||
|
||||
systemSetBootSpeed:
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, (1<<CLKPS1) | (1<<CLKPS0)
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called on first time run, i.e. on system start. No arguments, no results.
|
||||
|
||||
onSystemStart:
|
||||
ret
|
||||
|
||||
|
||||
#ifdef MODULES_DS18B20
|
||||
sendDs18b20Temp:
|
||||
rcall Ds18b20_SendTemp
|
||||
brcs sendDs18b20Temp_okay
|
||||
; set timer to 1s to retry later
|
||||
ldi xl, LOW(sramSendDs18b20TempTimer)
|
||||
ldi xh, HIGH(sramSendDs18b20TempTimer)
|
||||
rjmp Timer_SetValueTo1s
|
||||
sendDs18b20Temp_okay:
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called every 100ms. Add your routine calls here. No arguments, no results.
|
||||
|
||||
onEvery100ms:
|
||||
#ifdef MODULES_LED_SIMPLE
|
||||
rcall LedSimple_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
rcall MotionLight_Every100ms
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onPacketReceived:
|
||||
;
|
||||
; Called after a packet was received via COM module. Add your routine calls here.
|
||||
;
|
||||
; The packet will be released in any case after return from this call.
|
||||
;
|
||||
; @return CFLAG set if message handled, cleared otherwise
|
||||
; @param X pointer to received buffer
|
||||
; @clobbers all
|
||||
|
||||
onPacketReceived:
|
||||
; get msg code
|
||||
adiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
ld r16, x
|
||||
sbiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
rcall MotionLight_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SK6812
|
||||
rcall SK6812_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM
|
||||
rcall CPRO_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
clc
|
||||
onPacketReceived_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
@@ -2,51 +2,16 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="firmware" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target type="AvrHexFile" name="boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
boot
|
||||
main
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
defs.asm
|
||||
README
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
|
||||
13
avr/devices/n19/README
Normal file
13
avr/devices/n19/README
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
N19
|
||||
===
|
||||
|
||||
- Role: Air quality and climate sensors
|
||||
- MCU: AtTiny84
|
||||
- Connection: RJ45
|
||||
- Periphery:
|
||||
- PIR sensor (AMN31112)
|
||||
- TWI interface
|
||||
- SI7021 temperature and humidity sensor
|
||||
- CCS811 air quality sensor
|
||||
|
||||
32
avr/devices/n19/boot/0BUILD
Normal file
32
avr/devices/n19/boot/0BUILD
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n19_boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "./defs.asm"
|
||||
.include "defs_all.asm"
|
||||
.include "../defs.asm"
|
||||
.include "devices/all/defs.asm"
|
||||
.include "common/calls.asm"
|
||||
.include "common/utils_wait.asm"
|
||||
|
||||
|
||||
|
||||
@@ -25,10 +27,6 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; generic
|
||||
|
||||
.include "common/utils_wait.asm"
|
||||
.include "modules/com2/defs.asm"
|
||||
.include "modules/comproto/defs.asm"
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings
|
||||
@@ -40,6 +40,7 @@
|
||||
.equ LED_SIMPLE_OFFTIME = 50
|
||||
.equ LED_SIMPLE_DDR = DDRB
|
||||
.equ LED_SIMPLE_PORT = PORTB
|
||||
.equ LED_SIMPLE_PORTIN = PINB
|
||||
.equ LED_SIMPLE_PINNUM = PORTB3
|
||||
|
||||
|
||||
|
||||
@@ -1,379 +0,0 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2024 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; Source file for LED controller node on AtTiny 85
|
||||
;
|
||||
; This is for the full system (i.e. not the boot loader).
|
||||
; ***************************************************************************
|
||||
|
||||
.equ clock=1000000 ; Define the clock frequency
|
||||
|
||||
|
||||
|
||||
.nolist
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "./defs.asm"
|
||||
.include "defs_all.asm"
|
||||
.include "common/utils_wait.asm" ; wait macro
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings including list of modules used
|
||||
|
||||
.equ FIRMWARE_VERSION_MAJOR = 0
|
||||
.equ FIRMWARE_VERSION_MINOR = 0
|
||||
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
|
||||
|
||||
|
||||
#define MODULES_TIMER
|
||||
#define MODULES_COM
|
||||
#define MODULES_COM_WITH_ADDR_PROTO
|
||||
#define MODULES_LED_SIMPLE
|
||||
#define MODULES_TWI_MASTER
|
||||
#define MODULES_SI7021
|
||||
#define MODULES_STATS
|
||||
; #define MODULES_OWI_MASTER
|
||||
; #define MODULES_DS18B20
|
||||
; #define MODULES_SK6812
|
||||
; #define MODULES_MOTION_LIGHT
|
||||
|
||||
; #define COM_ACCEPT_ALL_DEST
|
||||
#define MODULES_CCS811
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for modules
|
||||
|
||||
.equ VALUE_ID_SI7021_TEMP = 0x01
|
||||
.equ VALUE_ID_SI7021_HUM = 0x02
|
||||
|
||||
.equ VALUE_ID_CO2 = 0x07
|
||||
.equ VALUE_ID_TVOC = 0x08
|
||||
|
||||
.equ VALUE_ID_DEBUG = 0x7f
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code segment
|
||||
|
||||
.cseg
|
||||
.org 000000
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reset and interrupt vectors
|
||||
|
||||
rjmp BOOTLOADER_ADDR ; Reset vector ; use this for flashed system
|
||||
reti ; EXT_INT0
|
||||
rjmp uartBitbangIsrPcint0 ; PCI0
|
||||
reti ; OC1A
|
||||
reti ; OVF1
|
||||
reti ; OVF0
|
||||
reti ; ERDY
|
||||
reti ; ACI
|
||||
reti ; ADCC
|
||||
reti ; OC1B
|
||||
rjmp baseTimerIrqOC0A ; OC0A
|
||||
reti ; OC0B
|
||||
reti ; WATCHDOG
|
||||
reti ; USI_STR
|
||||
reti ; USI_OVF
|
||||
|
||||
|
||||
devInfoBlock: ; 12 bytes
|
||||
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
|
||||
devInfoId: .db DEVICEINFO_ID, 0
|
||||
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
|
||||
firmwareVersion: .db FIRMWARE_VARIANT_MAIN, FIRMWARE_VERSION_MAJOR
|
||||
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
|
||||
|
||||
firmwareStart: rjmp main
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; includes
|
||||
|
||||
.include "common/utils.asm"
|
||||
.include "common/utils_wait_fixed.asm"
|
||||
.include "common/utils_copy_from_flash.asm"
|
||||
.include "common/utils_copy_sdram.asm"
|
||||
.include "common/crc8.asm"
|
||||
|
||||
.include "modules/basetimer/main.asm"
|
||||
|
||||
#ifdef MODULES_TIMER
|
||||
.include "modules/timer/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_LED_SIMPLE
|
||||
.include "modules/led_simple/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_COM
|
||||
.include "modules/com2/defs.asm"
|
||||
.include "modules/com2/main.asm"
|
||||
.include "modules/com2/buffer.asm"
|
||||
#ifdef MODULES_STATS
|
||||
.include "modules/comproto/msg_recvstats.asm"
|
||||
.include "modules/comproto/msg_sendstats.asm"
|
||||
.include "modules/comproto/msg_sysstats.asm"
|
||||
.include "modules/comproto/msg_memstats.asm"
|
||||
#endif
|
||||
.include "modules/comproto/msg_pong.asm"
|
||||
.include "modules/comproto/msg_value.asm"
|
||||
.include "modules/comproto/msg_device.asm"
|
||||
.include "modules/comproto/msg_reboot.asm"
|
||||
.include "modules/uart_bitbang/defs.asm"
|
||||
.include "modules/uart_bitbang/main.asm"
|
||||
.include "modules/uart_bitbang/bytelevel.asm"
|
||||
.include "modules/uart_bitbang/packetlevel.asm"
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
.include "modules/comproto/defs.asm"
|
||||
.include "modules/comproto/main.asm"
|
||||
.include "modules/comproto/addr.asm"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MODULES_STATS
|
||||
.include "modules/stats/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_TWI_MASTER
|
||||
.include "modules/twimaster/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_OWI_MASTER
|
||||
.include "modules/owimaster/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_SI7021
|
||||
.include "modules/si7021/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_DS18B20
|
||||
.include "modules/ds18b20/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_SK6812
|
||||
.include "modules/sk6812/main.asm"
|
||||
#endif
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
.include "modules/ma_light/main.asm"
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
.include "modules/ccs811/main.asm"
|
||||
#endif
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data in SRAM
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
#ifdef MODULES_SI7021
|
||||
sramTimerSI7021Measure: .byte 2
|
||||
sramTimerSI7021SendTemp: .byte 2
|
||||
sramTimerSI7021SendHumidity: .byte 2
|
||||
#endif
|
||||
#ifdef MODULES_DS18B20
|
||||
sramDs18b20Timer: .byte 2
|
||||
sramSendDs18b20TempTimer: .byte 2
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_CCS811
|
||||
sramCcs811Timer: .byte 2
|
||||
#endif
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data in FLASH
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; timer list
|
||||
|
||||
|
||||
timerList:
|
||||
; SRAM variable/counter routine flags secs (0=don't start or restart)
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
.dw cproAddresModeTimer, CPRO_Address_OnTimer, 0, 0 ; (no restart)
|
||||
#endif
|
||||
#ifdef MODULES_STATS
|
||||
.dw statsSendTimer, Stats_Timer, TIMER_FLAGS_IF_ADDR, 9000 ; every 15m
|
||||
#endif
|
||||
#ifdef MODULES_DS18B20
|
||||
.dw sramDs18b20Timer, Ds18b20_OnTimer, 0, 300 ; every 30s
|
||||
.dw sramSendDs18b20TempTimer, sendDs18b20Temp, TIMER_FLAGS_IF_ADDR, 600 ; every 60s
|
||||
#endif
|
||||
#ifdef MODULES_SI7021
|
||||
.dw sramTimerSI7021Measure, SI7021_OnTimer, 0, 300 ; every 30s
|
||||
.dw sramTimerSI7021SendTemp, sendSI7021Temp, TIMER_FLAGS_IF_ADDR, 600 ; every 60s
|
||||
.dw sramTimerSI7021SendHumidity, sendSI7021Humidity, TIMER_FLAGS_IF_ADDR, 600 ; every 60s
|
||||
#endif
|
||||
#ifdef MODULES_CCS811
|
||||
.dw sramCcs811Timer, CCS811_OnTimer, 0, 10 ; every 1s
|
||||
#endif
|
||||
.dw 0 ; end of list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.include "main_all.asm"
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called early on system startup. No arguments, no results.
|
||||
|
||||
systemSetSpeed:
|
||||
.if clock == 1000000
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, (1<<CLKPS1) | (1<<CLKPS0)
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
.endif
|
||||
|
||||
.if clock == 8000000
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, 0
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
.endif
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called just before rebooting to bootloader. No arguments, no results.
|
||||
|
||||
systemSetBootSpeed:
|
||||
ldi r16, (1<<CLKPCE)
|
||||
ldi r17, (1<<CLKPS1) | (1<<CLKPS0)
|
||||
out CLKPR, r16
|
||||
out CLKPR, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called on first time run, i.e. on system start. No arguments, no results.
|
||||
|
||||
onSystemStart:
|
||||
ret
|
||||
|
||||
|
||||
#ifdef MODULES_DS18B20
|
||||
sendDs18b20Temp:
|
||||
rcall Ds18b20_SendTemp
|
||||
brcs sendDs18b20Temp_okay
|
||||
; set timer to 1s to retry later
|
||||
ldi xl, LOW(sramSendDs18b20TempTimer)
|
||||
ldi xh, HIGH(sramSendDs18b20TempTimer)
|
||||
rjmp Timer_SetValueTo1s
|
||||
sendDs18b20Temp_okay:
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Called every 100ms. Add your routine calls here. No arguments, no results.
|
||||
|
||||
onEvery100ms:
|
||||
#ifdef MODULES_LED_SIMPLE
|
||||
rcall LedSimple_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_Every100ms
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
rcall MotionLight_Every100ms
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onPacketReceived:
|
||||
;
|
||||
; Called after a packet was received via COM module. Add your routine calls here.
|
||||
;
|
||||
; The packet will be released in any case after return from this call.
|
||||
;
|
||||
; @return CFLAG set if message handled, cleared otherwise
|
||||
; @param X pointer to received buffer
|
||||
; @clobbers all
|
||||
|
||||
onPacketReceived:
|
||||
; get msg code
|
||||
adiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
ld r16, x
|
||||
sbiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
|
||||
#ifdef MODULES_MOTION_LIGHT
|
||||
rcall MotionLight_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_SK6812
|
||||
rcall SK6812_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_REED
|
||||
rcall REED_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM
|
||||
rcall CPRO_OnPacketReceived
|
||||
brcs onPacketReceived_end
|
||||
#endif
|
||||
|
||||
clc
|
||||
onPacketReceived_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
#ifdef MODULES_SI7021
|
||||
|
||||
sendSI7021Humidity:
|
||||
rcall SI7021_SendHumidity
|
||||
brcs sendSI7021Humidity_okay
|
||||
; set timer to 1s to retry later
|
||||
ldi xl, LOW(sramTimerSI7021SendHumidity)
|
||||
ldi xh, HIGH(sramTimerSI7021SendHumidity)
|
||||
rjmp Timer_SetValueTo1s
|
||||
sendSI7021Humidity_okay:
|
||||
ret
|
||||
|
||||
|
||||
sendSI7021Temp:
|
||||
rcall SI7021_SendTemp
|
||||
brcs sendSI7021Temp_okay
|
||||
; set timer to 1s to retry later
|
||||
ldi xl, LOW(sramTimerSI7021SendTemp)
|
||||
ldi xh, HIGH(sramTimerSI7021SendTemp)
|
||||
rjmp Timer_SetValueTo1s
|
||||
sendSI7021Temp_okay:
|
||||
ret
|
||||
#endif
|
||||
|
||||
33
avr/devices/n19/main/0BUILD
Normal file
33
avr/devices/n19/main/0BUILD
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n19_firmware" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
176
avr/devices/n19/main/main.asm
Normal file
176
avr/devices/n19/main/main.asm
Normal file
@@ -0,0 +1,176 @@
|
||||
; ***************************************************************************
|
||||
; copyright : (C) 2025 by Martin Preuss
|
||||
; email : martin@libchipcard.de
|
||||
;
|
||||
; ***************************************************************************
|
||||
; * This file is part of the project "AqHome". *
|
||||
; * Please see toplevel file COPYING of that project for license details. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; Source file for LED controller node on AtTiny 85
|
||||
;
|
||||
; This is for the full system (i.e. not the boot loader).
|
||||
; ***************************************************************************
|
||||
|
||||
.equ clock=1000000 ; Define the clock frequency
|
||||
|
||||
|
||||
|
||||
.nolist
|
||||
.include "include/tn85def.inc" ; Define device ATtiny85
|
||||
.list
|
||||
|
||||
.include "../defs.asm"
|
||||
.include "devices/all/defs.asm"
|
||||
.include "common/calls.asm"
|
||||
.include "common/utils_wait.asm" ; wait macro
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
|
||||
.equ NET_BUFFERS_NUM = 6
|
||||
.equ NET_BUFFERS_SIZE = 32
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; firmware settings including list of modules used
|
||||
|
||||
.equ FIRMWARE_VERSION_MAJOR = 0
|
||||
.equ FIRMWARE_VERSION_MINOR = 0
|
||||
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
|
||||
|
||||
#define MODULES_CLOCK
|
||||
#define MODULES_LED_SIMPLE
|
||||
#define MODULES_NETWORK
|
||||
#define MODULES_UART_BITBANG
|
||||
#define MODULES_TWI_MASTER
|
||||
#define MODULES_SI7021
|
||||
#define MODULES_CCS811
|
||||
|
||||
#define APPS_NETWORK
|
||||
#define APPS_REPORTSENSORS
|
||||
#define APPS_STATS
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for modules
|
||||
|
||||
.equ VALUE_ID_SI7021_TEMP = 0x01
|
||||
.equ VALUE_ID_SI7021_HUM = 0x02
|
||||
|
||||
.equ VALUE_ID_CO2 = 0x07
|
||||
.equ VALUE_ID_TVOC = 0x08
|
||||
|
||||
.equ VALUE_ID_DEBUG = 0x7f
|
||||
|
||||
.equ VALUE_ID_LEDSIMPLE_TIMING = 0x88
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code segment
|
||||
|
||||
.cseg
|
||||
.org 000000
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Reset and interrupt vectors
|
||||
|
||||
rjmp BOOTLOADER_ADDR ; Reset vector ; use this for flashed system
|
||||
reti ; EXT_INT0
|
||||
rjmp UART_BitBang_PcintIsr ; PCI0
|
||||
reti ; OC1A
|
||||
reti ; OVF1
|
||||
reti ; OVF0
|
||||
reti ; ERDY
|
||||
reti ; ACI
|
||||
reti ; ADCC
|
||||
reti ; OC1B
|
||||
rjmp baseTimerIrqOC0A ; OC0A
|
||||
reti ; OC0B
|
||||
reti ; WATCHDOG
|
||||
reti ; USI_STR
|
||||
reti ; USI_OVF
|
||||
|
||||
|
||||
devInfoBlock: ; 12 bytes
|
||||
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
|
||||
devInfoId: .db DEVICEINFO_ID, 0
|
||||
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
|
||||
firmwareVersion: .db FIRMWARE_VARIANT_MAIN, FIRMWARE_VERSION_MAJOR
|
||||
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
|
||||
|
||||
firmwareStart:
|
||||
rjmp main
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onSystemStart
|
||||
|
||||
onSystemStart:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onMessageReceived
|
||||
;
|
||||
; Called on every message received
|
||||
|
||||
onMessageReceived:
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onEvery100ms
|
||||
;
|
||||
; Called every 100ms. Add your routine calls here. No arguments, no results.
|
||||
|
||||
onEvery100ms:
|
||||
onEverySecond:
|
||||
onEveryMinute:
|
||||
onEveryHour:
|
||||
onEveryDay:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onEveryLoop
|
||||
;
|
||||
; Called on every loop (i.e. after awakening from sleep).
|
||||
;
|
||||
onEveryLoop:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; includes
|
||||
|
||||
.include "devices/all/hw_tn85.asm"
|
||||
.include "devices/all/includes.asm"
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; defines for network interface
|
||||
|
||||
.equ netInterfaceData = uart_bitbang_iface
|
||||
|
||||
|
||||
|
||||
@@ -2,44 +2,9 @@
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n20_firmware" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target type="AvrHexFile" name="n20_boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
boot
|
||||
main
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
@@ -50,4 +15,3 @@
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
|
||||
32
avr/devices/n20/boot/0BUILD
Normal file
32
avr/devices/n20/boot/0BUILD
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n20_boot" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
boot.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
.list
|
||||
|
||||
.include "version.asm"
|
||||
.include "./defs.asm"
|
||||
.include "../defs.asm"
|
||||
.include "devices/all/defs.asm"
|
||||
|
||||
.include "common/calls.asm"
|
||||
33
avr/devices/n20/main/0BUILD
Normal file
33
avr/devices/n20/main/0BUILD
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml?>
|
||||
|
||||
<gwbuild>
|
||||
|
||||
<target type="AvrHexFile" name="n20_firmware" >
|
||||
|
||||
<includes type="avrasm" >
|
||||
-I $(builddir)
|
||||
-I $(srcdir)
|
||||
-I $(topsrcdir)/avr
|
||||
-I $(topbuilddir)/avr
|
||||
</includes>
|
||||
|
||||
|
||||
<sources type="avrasm" >
|
||||
main.asm
|
||||
</sources>
|
||||
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<subdirs>
|
||||
</subdirs>
|
||||
|
||||
<extradist>
|
||||
</extradist>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
.list
|
||||
|
||||
.include "version.asm"
|
||||
.include "./defs.asm"
|
||||
.include "../defs.asm"
|
||||
.include "devices/all/defs.asm"
|
||||
|
||||
.include "common/calls.asm"
|
||||
@@ -67,7 +67,7 @@
|
||||
;#define MODULES_DS18B20
|
||||
;#define MODULES_MOTION
|
||||
;#define MODULES_TCRT1000
|
||||
;#define MODULES_CCS811
|
||||
#define MODULES_CCS811
|
||||
|
||||
#define APPS_NETWORK
|
||||
;#define APPS_MOTION
|
||||
@@ -11,7 +11,11 @@
|
||||
defs.asm
|
||||
README
|
||||
</extradist>
|
||||
|
||||
|
||||
<data dist="true" install="$(datadir)/aqhome/devices/nodes">
|
||||
aqua_n21.xml
|
||||
</data>
|
||||
|
||||
|
||||
</gwbuild>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<values>
|
||||
<value name="SI7021_TEMP" id="0x01" type="sensor" dataType="rational" modality="temperature" units="C" denom="100" />
|
||||
<value name="SI7021_HUM" id="0x02" type="sensor" dataType="rational" modality="humidity" units="%" denom="1" />
|
||||
<value name="ADC" id="0x03" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="MOTION" id="0x07" type="sensor" dataType="rational" modality="motion" denom="1" />
|
||||
<value name="DOOR" id="0x08" type="sensor" dataType="rational" modality="door" denom="1" />
|
||||
|
||||
@@ -18,10 +19,6 @@
|
||||
<value name="stats_collision_errors" id="0xe5" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_busy_errors" id="0xe6" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="stats_heap_used" id="0xe7" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_heap_free" id="0xe8" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_noram_errors" id="0xe9" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="LEDTIMING" id="0x88" type="actor" dataType="uint16" />
|
||||
</values>
|
||||
|
||||
@@ -173,7 +173,6 @@ onMessageReceived:
|
||||
|
||||
onEvery100ms:
|
||||
onEverySecond:
|
||||
onEveryMinute:
|
||||
onEveryHour:
|
||||
onEveryDay:
|
||||
ret
|
||||
@@ -181,6 +180,14 @@ onEveryDay:
|
||||
|
||||
|
||||
|
||||
onEveryMinute:
|
||||
lds r16, tcrt1kLastValue
|
||||
ldi r17, VALUE_ID_ADC
|
||||
ldi r22, AQHOME_VALUETYPE_UNKNOWN ; VALUE TYPE
|
||||
rjmp Main_Send8BitValueReport
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine onEveryLoop
|
||||
;
|
||||
|
||||
@@ -5,6 +5,8 @@ N22
|
||||
- Role: LED strip controller
|
||||
- MCU: AtTiny85
|
||||
- Connection: RJ45
|
||||
- Predecessor: N16
|
||||
- UART: uart_bitbang2
|
||||
- Periphery:
|
||||
- LED strip connection (SK6812)
|
||||
- OWI interface
|
||||
|
||||
@@ -5,6 +5,7 @@ N23
|
||||
- Role: Air quality and climate sensors
|
||||
- MCU: AtTiny84
|
||||
- Connection: RJ45
|
||||
- Predecessor: N19
|
||||
- Periphery:
|
||||
- PIR sensor (AMN31112)
|
||||
- TWI interface
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
<value name="stats_collision_errors" id="0xe5" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_busy_errors" id="0xe6" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="stats_heap_used" id="0xe7" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_heap_free" id="0xe8" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_noram_errors" id="0xe9" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="LEDTIMING" id="0x88" type="actor" dataType="uint16" />
|
||||
</values>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ N24
|
||||
- Role: Air quality and climate sensors
|
||||
- MCU: AtTiny84
|
||||
- Connection: RJ45
|
||||
- Predecessor: N23, N19
|
||||
- Periphery:
|
||||
- PIR sensor (AMN31112)
|
||||
- TWI interface
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<value name="SGP40_VALUE" id="0x08" type="sensor" dataType="rational" modality="tvoc" denom="1" />
|
||||
<value name="SGP30_TVOC" id="0x09" type="sensor" dataType="rational" modality="tvoc" denom="1" />
|
||||
<value name="SGP30_CO2" id="0x0a" type="sensor" dataType="rational" modality="co2" denom="1" />
|
||||
<value name="LIGHT" id="0x0b" type="sensor" dataType="rational" modality="light" denom="1" />
|
||||
|
||||
<value name="stats_packets_in" id="0xe0" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_packets_out" id="0xe1" type="sensor" dataType="uint16" denom="1" />
|
||||
@@ -20,10 +21,6 @@
|
||||
<value name="stats_collision_errors" id="0xe5" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_busy_errors" id="0xe6" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="stats_heap_used" id="0xe7" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_heap_free" id="0xe8" type="sensor" dataType="uint16" denom="1" />
|
||||
<value name="stats_noram_errors" id="0xe9" type="sensor" dataType="uint16" denom="1" />
|
||||
|
||||
<value name="LEDTIMING" id="0x88" type="actor" dataType="uint16" />
|
||||
</values>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
; AtTiny84
|
||||
; --------
|
||||
; VCC 1 14 GND
|
||||
; AUX-PB0 PB0 2 13 PA0 AUX-PA0
|
||||
; AUX-PB0 PB0 2 13 PA0 LUM
|
||||
; PIR PB1 3 12 PA1 COM-DATA
|
||||
; /RESET PB3 4 11 PA2 AUX-PA2
|
||||
; PB2 5 10 PA3 LED
|
||||
@@ -146,3 +146,14 @@
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Brightness
|
||||
|
||||
|
||||
.equ BRIGHTNESS_ADC_PORT = PORTA ; adc0
|
||||
.equ BRIGHTNESS_ADC_DDR = DDRA
|
||||
.equ BRIGHTNESS_ADC_PIN = PORTA0
|
||||
.equ BRIGHTNESS_ADC_MUX = 0
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user