Merge branch 'mp-2025_07-improvr_uart_hw2'
This commit is contained in:
5
0BUILD
5
0BUILD
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<gwbuild>
|
<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.14" so_current="0" so_age="0" so_revision="14" write_config_h="TRUE">
|
||||||
<setVar name="package">$(project_name)</setVar>
|
<setVar name="package">$(project_name)</setVar>
|
||||||
<setVar name="version">
|
<setVar name="version">
|
||||||
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
|
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
|
||||||
@@ -51,6 +51,8 @@
|
|||||||
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
|
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
|
||||||
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
|
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
|
||||||
|
|
||||||
|
<setVar name="httpdatadir">/var/www</setVar>
|
||||||
|
|
||||||
<option id="enable_testcode" type="string">
|
<option id="enable_testcode" type="string">
|
||||||
<default>TRUE</default>
|
<default>TRUE</default>
|
||||||
<choices>TRUE FALSE</choices>
|
<choices>TRUE FALSE</choices>
|
||||||
@@ -126,6 +128,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<checkheaders>
|
<checkheaders>
|
||||||
signal.h
|
signal.h
|
||||||
sys/stat.h
|
sys/stat.h
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<gwbuild>
|
<gwbuild>
|
||||||
|
|
||||||
|
|
||||||
<target type="Program" name="aqhome-cgi" install="$(sbindir)" >
|
<target type="Program" name="aqhome-cgi" install="$(libdir)/cgi-bin" >
|
||||||
|
|
||||||
<includes type="c" >
|
<includes type="c" >
|
||||||
$(gwenhywfar_cflags)
|
$(gwenhywfar_cflags)
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
<libraries>
|
<libraries>
|
||||||
$(gwenhywfar_libs)
|
$(gwenhywfar_libs)
|
||||||
-lm
|
-lm
|
||||||
|
$(aqcgi_libs)
|
||||||
</libraries>
|
</libraries>
|
||||||
|
|
||||||
<subdirs>
|
<subdirs>
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
<useTargets>
|
<useTargets>
|
||||||
aqhome
|
aqhome
|
||||||
aqhcgi_service
|
aqhcgi_service
|
||||||
|
aqhcgi_modules
|
||||||
</useTargets>
|
</useTargets>
|
||||||
|
|
||||||
<libraries>
|
<libraries>
|
||||||
@@ -127,6 +129,7 @@
|
|||||||
|
|
||||||
<subdirs>
|
<subdirs>
|
||||||
service
|
service
|
||||||
|
modules
|
||||||
</subdirs>
|
</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)
|
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;
|
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
|
||||||
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
<?xml?>
|
<?xml?>
|
||||||
|
|
||||||
<gwbuild>
|
<gwbuild>
|
||||||
|
|
||||||
<subdirs>
|
<subdirs>
|
||||||
uart
|
en
|
||||||
ccs811
|
|
||||||
</subdirs>
|
</subdirs>
|
||||||
|
|
||||||
</gwbuild>
|
</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>
|
<descr>Waiting for approval by admin</descr>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item name="active">
|
||||||
|
<descr>User active</descr>
|
||||||
|
</item>
|
||||||
|
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
</enums>
|
</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 int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
|
||||||
static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName);
|
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);
|
GWEN_DB_Group_free(db);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||||
|
|
||||||
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "here (%d)", rv);
|
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)
|
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) {
|
if (sv && groupName && subGroupName) {
|
||||||
AQH_SERVICE_FILE *xs;
|
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;
|
GWEN_DB_NODE *db=NULL;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
|
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
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;
|
return db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
DBG_ERROR(NULL, "Missing argument");
|
||||||
|
}
|
||||||
return NULL;
|
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);
|
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||||
if (xs) {
|
if (xs) {
|
||||||
GWEN_DB_NODE *db=NULL;
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
|
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
|
||||||
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
GWEN_DB_Group_free(db);
|
|
||||||
return rv;
|
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);
|
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
|
||||||
if (xs) {
|
if (xs) {
|
||||||
GWEN_DB_NODE *db=NULL;
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName);
|
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);
|
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
|
||||||
GWEN_DB_Group_free(db);
|
|
||||||
return rv;
|
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"
|
#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.
|
* 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
|
* The license for this file can be found in the file COPYING which you
|
||||||
* should have received along with this file.
|
* should have received along with this file.
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
* ------------------------------------------------------------------------------------------------
|
* ------------------------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048
|
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 1024
|
||||||
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024
|
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 512
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -44,13 +44,15 @@
|
|||||||
|
|
||||||
static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||||
const AQH_VALUE *value,
|
const AQH_VALUE *value,
|
||||||
|
int mode,
|
||||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId);
|
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);
|
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,
|
static void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||||
uint32_t refMsgId);
|
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 tsBegin;
|
||||||
uint64_t tsEnd;
|
uint64_t tsEnd;
|
||||||
uint64_t numRequested;
|
uint64_t numRequested;
|
||||||
|
int mode;
|
||||||
|
|
||||||
tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
|
tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
|
||||||
tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0);
|
tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0);
|
||||||
numRequested=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_NUM, 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);
|
value=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName);
|
||||||
if (value) {
|
if (value) {
|
||||||
int resultCode;
|
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);
|
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -114,30 +118,31 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
|
|||||||
|
|
||||||
int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||||
const AQH_VALUE *value,
|
const AQH_VALUE *value,
|
||||||
|
int mode,
|
||||||
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||||
uint32_t refMsgId)
|
uint32_t refMsgId)
|
||||||
{
|
{
|
||||||
if (num==0)
|
switch(mode) {
|
||||||
return _getAndSendDataPointsNoNum(storage, ep, value, tsBegin, tsEnd, refMsgId);
|
case AQH_MSGDATA_GETDATA_MODE_FIRST: return _getAndSendDataPointsFirst(storage, ep, value, num, refMsgId);
|
||||||
else if (num==1) {
|
case AQH_MSGDATA_GETDATA_MODE_PERIOD: return _getAndSendDataPointsPeriod(storage, ep, value, tsBegin, tsEnd, num, refMsgId);
|
||||||
_getAndSendLastDatapoint(storage, ep, value, refMsgId);
|
default:
|
||||||
return AQH_MSGDATA_RESULT_SUCCESS;
|
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,
|
int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||||
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
|
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
|
||||||
uint32_t refMsgId)
|
uint32_t refMsgId)
|
||||||
{
|
{
|
||||||
uint64_t valueId;
|
uint64_t valueId;
|
||||||
uint64_t *tablePtr;
|
uint64_t *tablePtr;
|
||||||
|
|
||||||
valueId=AQH_Value_GetId(value);
|
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) {
|
if (tablePtr) {
|
||||||
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
|
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
|
||||||
free(tablePtr);
|
free(tablePtr);
|
||||||
@@ -151,9 +156,9 @@ int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
|
||||||
const AQH_VALUE *value, uint64_t num,
|
const AQH_VALUE *value, uint64_t num,
|
||||||
uint32_t refMsgId)
|
uint32_t refMsgId)
|
||||||
{
|
{
|
||||||
uint64_t valueId;
|
uint64_t valueId;
|
||||||
uint64_t *tablePtr;
|
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,
|
void _sendDataPointsResponse(AQH_OBJECT *ep,
|
||||||
const AQH_VALUE *value, const uint64_t *tablePtr,
|
const AQH_VALUE *value, const uint64_t *tablePtr,
|
||||||
uint32_t refMsgId)
|
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 "./s_getvalues.h"
|
||||||
#include "./server_p.h"
|
#include "./server_p.h"
|
||||||
|
#include "aqhome/aqhome.h"
|
||||||
#include "aqhome/ipc2/endpoint.h"
|
#include "aqhome/ipc2/endpoint.h"
|
||||||
#include "aqhome/msg/ipc/m_ipc.h"
|
#include "aqhome/msg/ipc/m_ipc.h"
|
||||||
#include "aqhome/msg/ipc/data/m_ipcd.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/data/m_ipcd_values.h"
|
||||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||||
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
#include "aqhome/msg/ipc/m_ipc_tag16.h"
|
||||||
|
|
||||||
|
#include <gwenhywfar/text.h>
|
||||||
#include <gwenhywfar/debug.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;
|
AQHOME_SERVER *xo;
|
||||||
|
|
||||||
xo=AqHomeDataServer_GetServerData(o);
|
xo=AqHomeDataServer_GetServerData(o);
|
||||||
if (xo) {
|
if (xo) {
|
||||||
const AQH_VALUE_LIST *origValueList;
|
AQH_VALUE_LIST *valueList;
|
||||||
|
|
||||||
uint32_t refMsgId;
|
uint32_t refMsgId;
|
||||||
|
|
||||||
refMsgId=AQH_IpcMessage_GetMsgId(msg);
|
refMsgId=AQH_IpcMessage_GetMsgId(msg);
|
||||||
|
|
||||||
DBG_INFO(NULL, "HandleGetValues");
|
DBG_INFO(NULL, "HandleGetValues");
|
||||||
origValueList=AQH_Storage_GetValueList(xo->storage);
|
valueList=_getMatchingValueList(xo, tagList);
|
||||||
if (origValueList) {
|
if (valueList) {
|
||||||
DBG_INFO(NULL, "Have a list of %d values", AQH_Value_List_GetCount(origValueList));
|
_sendValueList(ep, valueList, refMsgId);
|
||||||
if (AQH_Value_List_GetCount(origValueList)<AQHOMEDATA_VALUESPERMSG) {
|
AQH_Value_List_free(valueList);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* empty list */
|
/* 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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ void AQH_NodeServer_HandleGetNodes(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESS
|
|||||||
AQH_Endpoint_GetNextMessageId(ep), AQH_IpcMessage_GetMsgId(msg),
|
AQH_Endpoint_GetNextMessageId(ep), AQH_IpcMessage_GetMsgId(msg),
|
||||||
niNext?0:AQH_MSGNODE_GETDEVICES_RSP_FLAGS_LASTMSG, ni);
|
niNext?0:AQH_MSGNODE_GETDEVICES_RSP_FLAGS_LASTMSG, ni);
|
||||||
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
AQH_Endpoint_AddMsgOut(ep, outMsg);
|
||||||
DBG_ERROR(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
|
DBG_DEBUG(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
|
||||||
ni=niNext;
|
ni=niNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <aqhome/msg/node/m_value.h>
|
#include <aqhome/msg/node/m_value.h>
|
||||||
#include <aqhome/msg/node/m_recvstats.h>
|
#include <aqhome/msg/node/m_recvstats.h>
|
||||||
#include <aqhome/msg/node/m_sendstats.h>
|
#include <aqhome/msg/node/m_sendstats.h>
|
||||||
|
#include <aqhome/msg/node/m_memstats.h>
|
||||||
#include <aqhome/data/value.h>
|
#include <aqhome/data/value.h>
|
||||||
|
|
||||||
#include <gwenhywfar/args.h>
|
#include <gwenhywfar/args.h>
|
||||||
@@ -122,7 +123,9 @@ static void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH
|
|||||||
static void _forwardValueMessageToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
static void _forwardValueMessageToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||||
static void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
static void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||||
static void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
static void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||||
|
static void _forwardDataFromMemStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||||
static void _forwardTtyMsgToClients(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
static void _forwardTtyMsgToClients(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
|
||||||
|
static void _publishIntWithIdx(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int idx, int vModality, const char *vUnits, int v);
|
||||||
static void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v);
|
static void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v);
|
||||||
static void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, double v);
|
static void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, double v);
|
||||||
static void _setDeviceName(AQH_VALUE *value, uint32_t uid);
|
static void _setDeviceName(AQH_VALUE *value, uint32_t uid);
|
||||||
@@ -827,9 +830,11 @@ void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAG
|
|||||||
|
|
||||||
code=AQH_NodeMessage_GetMsgType(msg);
|
code=AQH_NodeMessage_GetMsgType(msg);
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
|
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
|
||||||
case AQH_MSG_TYPE_COMSENDSTATS: _forwardDataFromSendStatsMsgToBroker(xo, msg); break;
|
case AQH_MSG_TYPE_COMSENDSTATS: _forwardDataFromSendStatsMsgToBroker(xo, msg); break;
|
||||||
case AQH_MSG_TYPE_COMRECVSTATS: _forwardDataFromRecvStatsMsgToBroker(xo, msg); break;
|
case AQH_MSG_TYPE_COMRECVSTATS: _forwardDataFromRecvStatsMsgToBroker(xo, msg); break;
|
||||||
|
case AQH_MSG_TYPE_MEMSTATS: _forwardDataFromMemStatsMsgToBroker(xo, msg); break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -898,24 +903,21 @@ void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
|
|||||||
packetsOutInt=AQH_SendStatsMessage_GetPacketsOut(msg);
|
packetsOutInt=AQH_SendStatsMessage_GetPacketsOut(msg);
|
||||||
if (packetsOutInt) {
|
if (packetsOutInt) {
|
||||||
uint32_t uid;
|
uint32_t uid;
|
||||||
double packetsOut;
|
int devNum;
|
||||||
double collisions;
|
|
||||||
double busy;
|
|
||||||
double collisionsPercentage=0.0;
|
|
||||||
double busyPercentage=0.0;
|
|
||||||
|
|
||||||
uid=AQH_SendStatsMessage_GetUid(msg);
|
uid=AQH_SendStatsMessage_GetUid(msg);
|
||||||
packetsOut=/*(double)*/ packetsOutInt;
|
devNum=AQH_SendStatsMessage_GetInterface(msg);
|
||||||
collisions=/*(double)*/ AQH_SendStatsMessage_GetCollisions(msg);
|
|
||||||
busy=/*(double)*/ AQH_SendStatsMessage_GetBusyErrors(msg);
|
|
||||||
|
|
||||||
collisionsPercentage=collisions*100.0/packetsOut;
|
if (devNum==0) {
|
||||||
busyPercentage=busy*100.0/packetsOut;
|
_publishInt(xo, uid, "net/packetsOut", 0, NULL, packetsOutInt);
|
||||||
|
_publishInt(xo, uid, "net/collisions", 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
||||||
_publishInt( xo, uid, "net/packetsOut", 0, NULL, packetsOutInt);
|
_publishInt(xo, uid, "net/busy", 0, NULL, (int) AQH_SendStatsMessage_GetBusyErrors(msg));
|
||||||
_publishInt( xo, uid, "net/collisions", 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
}
|
||||||
_publishDouble(xo, uid, "net/collisionsPercent", 0, "%", collisionsPercentage);
|
else {
|
||||||
_publishDouble(xo, uid, "net/busyPercent", 0, "%", busyPercentage);
|
_publishIntWithIdx(xo, uid, "net/packetsOut", devNum, 0, NULL, packetsOutInt);
|
||||||
|
_publishIntWithIdx(xo, uid, "net/collisions", devNum, 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
|
||||||
|
_publishIntWithIdx(xo, uid, "net/busy", devNum, 0, NULL, (int) AQH_SendStatsMessage_GetBusyErrors(msg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -928,30 +930,56 @@ void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
|
|||||||
packetsInInt=AQH_RecvStatsMessage_GetPacketsIn(msg);
|
packetsInInt=AQH_RecvStatsMessage_GetPacketsIn(msg);
|
||||||
if (packetsInInt) {
|
if (packetsInInt) {
|
||||||
uint32_t uid;
|
uint32_t uid;
|
||||||
double packetsIn;
|
int devNum;
|
||||||
double crcErrors;
|
|
||||||
double ioErrors;
|
|
||||||
double crcErrorsPercentage=0.0;
|
|
||||||
double ioErrorsPercentage=0.0;
|
|
||||||
|
|
||||||
uid=AQH_SendStatsMessage_GetUid(msg);
|
uid=AQH_RecvStatsMessage_GetUid(msg);
|
||||||
packetsIn=/*(double)*/ packetsInInt;
|
devNum=AQH_RecvStatsMessage_GetInterface(msg);
|
||||||
crcErrors=/*(double)*/AQH_RecvStatsMessage_GetCrcErrors(msg);
|
|
||||||
ioErrors=/*(double)*/AQH_RecvStatsMessage_GetIoErrors(msg);
|
|
||||||
|
|
||||||
crcErrorsPercentage=crcErrors*100.0/packetsIn;
|
if (devNum==0) {
|
||||||
ioErrorsPercentage=ioErrors*100.0/packetsIn;
|
_publishInt(xo, uid, "net/packetsIn", 0, NULL, packetsInInt);
|
||||||
|
_publishInt(xo, uid, "net/crcErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
||||||
_publishInt( xo, uid, "net/packetsIn", 0, NULL, packetsInInt);
|
_publishInt(xo, uid, "net/ioErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
||||||
_publishInt( xo, uid, "net/crcerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
_publishInt(xo, uid, "net/nobufferErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetNoBufferErrors(msg));
|
||||||
_publishInt( xo, uid, "net/ioerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
_publishInt(xo, uid, "net/msgSizeErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetMsgSizeErrors(msg));
|
||||||
_publishDouble(xo, uid, "net/crcerrorsPercent", 0, "%", crcErrorsPercentage);
|
_publishInt(xo, uid, "net/missed", 0, NULL, (int) AQH_RecvStatsMessage_GetMissed(msg));
|
||||||
_publishDouble(xo, uid, "net/ioerrorsPercent", 0, "%", ioErrorsPercentage);
|
}
|
||||||
|
else {
|
||||||
|
_publishIntWithIdx(xo, uid, "net/packetsIn", devNum, 0, NULL, packetsInInt);
|
||||||
|
_publishIntWithIdx(xo, uid, "net/crcErrors", devNum, 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
|
||||||
|
_publishIntWithIdx(xo, uid, "net/ioErrors", devNum, 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
|
||||||
|
_publishIntWithIdx(xo, uid, "net/nobufferErrors", devNum, 0, NULL, (int) AQH_RecvStatsMessage_GetNoBufferErrors(msg));
|
||||||
|
_publishIntWithIdx(xo, uid, "net/msgSizeErrors", devNum, 0, NULL, (int) AQH_RecvStatsMessage_GetMsgSizeErrors(msg));
|
||||||
|
_publishIntWithIdx(xo, uid, "net/missed", devNum, 0, NULL, (int) AQH_RecvStatsMessage_GetMissed(msg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _forwardDataFromMemStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
uint32_t uid;
|
||||||
|
|
||||||
|
uid=AQH_MemStatsMessage_GetUid(msg);
|
||||||
|
|
||||||
|
_publishInt( xo, uid, "mem/buffersUsed", 0, NULL, AQH_MemStatsMessage_GetBuffersUsed(msg));
|
||||||
|
_publishInt( xo, uid, "mem/maxBuffersUsed", 0, NULL, AQH_MemStatsMessage_GetMaxBuffersUsed(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _publishIntWithIdx(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int idx, int vModality, const char *vUnits, int v)
|
||||||
|
{
|
||||||
|
GWEN_BUFFER *tbuf;
|
||||||
|
|
||||||
|
tbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||||
|
GWEN_Buffer_AppendArgs(tbuf, "%s%d", vPath, idx);
|
||||||
|
_publishInt(xo, uid, GWEN_Buffer_GetStart(tbuf), vModality, vUnits, v);
|
||||||
|
GWEN_Buffer_free(tbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v)
|
void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v)
|
||||||
{
|
{
|
||||||
_publishDouble(xo, uid, vPath, vModality, vUnits, /*(double)*/ v);
|
_publishDouble(xo, uid, vPath, vModality, vUnits, /*(double)*/ v);
|
||||||
|
|||||||
@@ -37,9 +37,13 @@
|
|||||||
getdevices.h
|
getdevices.h
|
||||||
adddata.h
|
adddata.h
|
||||||
getdatapoints.h
|
getdatapoints.h
|
||||||
|
getfirstdata.h
|
||||||
|
getlastdata.h
|
||||||
|
getperioddata.h
|
||||||
setdata.h
|
setdata.h
|
||||||
moddevice.h
|
moddevice.h
|
||||||
watch.h
|
watch.h
|
||||||
|
devicestate.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
<sources>
|
<sources>
|
||||||
@@ -49,9 +53,13 @@
|
|||||||
getdevices.c
|
getdevices.c
|
||||||
adddata.c
|
adddata.c
|
||||||
getdatapoints.c
|
getdatapoints.c
|
||||||
|
getfirstdata.c
|
||||||
|
getlastdata.c
|
||||||
|
getperioddata.c
|
||||||
setdata.c
|
setdata.c
|
||||||
moddevice.c
|
moddevice.c
|
||||||
watch.c
|
watch.c
|
||||||
|
devicestate.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
<useTargets>
|
<useTargets>
|
||||||
|
|||||||
265
apps/aqhome-tool/data/devicestate.c
Normal file
265
apps/aqhome-tool/data/devicestate.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "./devicestate.h"
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
|
#include "aqhome/aqhome.h"
|
||||||
|
#include "aqhome/dataclient/client.h"
|
||||||
|
#include "aqhome/msg/ipc/m_ipc.h"
|
||||||
|
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||||
|
#include "aqhome/msg/ipc/data/m_ipcd.h"
|
||||||
|
#include "aqhome/msg/ipc/data/m_ipcd_getdata.h"
|
||||||
|
#include "aqhome/msg/ipc/data/m_ipcd_multidata.h"
|
||||||
|
#include "aqhome/dataclient/client.h"
|
||||||
|
|
||||||
|
#include <gwenhywfar/args.h>
|
||||||
|
#include <gwenhywfar/i18n.h>
|
||||||
|
#include <gwenhywfar/debug.h>
|
||||||
|
#include <gwenhywfar/text.h>
|
||||||
|
#include <gwenhywfar/timestamp.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* defs
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I18S(msg) msg
|
||||||
|
#define I18N(msg) GWEN_I18N_Translate(PACKAGE, msg)
|
||||||
|
|
||||||
|
#define A_ARG GWEN_ARGS_FLAGS_HAS_ARGUMENT
|
||||||
|
#define A_END (GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST)
|
||||||
|
#define A_CHAR GWEN_ArgsType_Char
|
||||||
|
#define A_INT GWEN_ArgsType_Int
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* forward declarations
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int _runCommand(AQH_DATACLIENT *dc);
|
||||||
|
static void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device);
|
||||||
|
static void _handleValue(AQH_DATACLIENT *dc, const AQH_VALUE *value);
|
||||||
|
static void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues);
|
||||||
|
static void _printSingleDataPoint(uint64_t timestamp, double data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
* code
|
||||||
|
* ------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
|
||||||
|
{
|
||||||
|
AQH_EVENT_LOOP *eventLoop;
|
||||||
|
AQH_DATACLIENT *dc;
|
||||||
|
int rv;
|
||||||
|
const GWEN_ARGS args[]= {
|
||||||
|
/* flags type name min max s long short_descr, long_descr */
|
||||||
|
{ A_ARG, A_CHAR, "brokerAddress", 0, 1, "t", "tcpaddress", I18S("TCP address to connect to [127.0.0.1]"), NULL},
|
||||||
|
{ A_ARG, A_INT, "brokerPort", 0, 1, "P", "tcpport", I18S("Specify the TCP port to listen on"), NULL},
|
||||||
|
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL},
|
||||||
|
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL},
|
||||||
|
{ A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL},
|
||||||
|
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
|
||||||
|
{ A_ARG, A_CHAR, "device", 1, 1, "d", "device", I18S("device name"), NULL},
|
||||||
|
{ A_ARG, A_CHAR, "valueName", 0, 1, "N", "valuename", I18S("Value name for device(e.g. LIGHT)"), NULL},
|
||||||
|
{ A_ARG, A_INT, "numOfDatapoints", 0, 1, "n", NULL, I18S("Get up to n datapoints"), NULL},
|
||||||
|
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
eventLoop=AQH_EventLoop_new();
|
||||||
|
dc=AQH_DataClient_new(eventLoop, AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION);
|
||||||
|
|
||||||
|
rv=AQH_DataClient_ReadLocalArgs(dc, dbGlobalArgs, args, argc, argv);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "here (%d)", rv);
|
||||||
|
AQH_DataClient_free(dc);
|
||||||
|
AQH_EventLoop_free(eventLoop);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv=AQH_DataClient_ConnectWithArgs(dc, 0);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "Error connecting (%d)", rv);
|
||||||
|
AQH_DataClient_free(dc);
|
||||||
|
AQH_EventLoop_free(eventLoop);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv=_runCommand(dc);
|
||||||
|
if (rv<0) {
|
||||||
|
DBG_ERROR(NULL, "Error running (%d)", rv);
|
||||||
|
AQH_DataClient_free(dc);
|
||||||
|
AQH_EventLoop_free(eventLoop);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
AQH_DataClient_free(dc);
|
||||||
|
AQH_EventLoop_free(eventLoop);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _runCommand(AQH_DATACLIENT *dc)
|
||||||
|
{
|
||||||
|
GWEN_DB_NODE *dbLocalArgs;
|
||||||
|
const char *deviceName;
|
||||||
|
AQH_DEVICE_LIST *deviceList;
|
||||||
|
AQH_DEVICE *device;
|
||||||
|
|
||||||
|
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||||
|
deviceName=GWEN_DB_GetCharValue(dbLocalArgs, "device", 0, "*");
|
||||||
|
|
||||||
|
deviceList=AQH_DataClient_GetDevices(dc);
|
||||||
|
if (deviceList==NULL) {
|
||||||
|
DBG_ERROR(NULL, "Error getting devices");
|
||||||
|
return GWEN_ERROR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
device=AQH_Device_List_First(deviceList);
|
||||||
|
while(device) {
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
s=AQH_Device_GetNameForSystem(device);
|
||||||
|
if (s && *s && -1!=GWEN_Text_ComparePattern(s, deviceName, 0)) {
|
||||||
|
_handleDevice(dc, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
device=AQH_Device_List_Next(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
AQH_Device_List_free(deviceList);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _handleDevice(AQH_DATACLIENT *dc, const AQH_DEVICE *device)
|
||||||
|
{
|
||||||
|
AQH_VALUE_LIST *valueList;
|
||||||
|
const char *devName;
|
||||||
|
const char *roomName;
|
||||||
|
const char *location;
|
||||||
|
const char *descr;
|
||||||
|
|
||||||
|
devName=AQH_Device_GetNameForSystem(device);
|
||||||
|
roomName=AQH_Device_GetRoomName(device);
|
||||||
|
location=AQH_Device_GetLocation(device);
|
||||||
|
descr=AQH_Device_GetDescription(device);
|
||||||
|
|
||||||
|
fprintf(stdout, "%s (room: %s, loc: %s, descr: %s)\n",
|
||||||
|
devName,
|
||||||
|
roomName?roomName:"--",
|
||||||
|
location?location:"--",
|
||||||
|
descr?descr:"--");
|
||||||
|
valueList=AQH_DataClient_GetValues(dc, devName, 0);
|
||||||
|
if (valueList) {
|
||||||
|
const AQH_VALUE *value;
|
||||||
|
|
||||||
|
value=AQH_Value_List_First(valueList);
|
||||||
|
while(value) {
|
||||||
|
if (AQH_Value_GetValueType(value)==AQH_ValueType_Sensor)
|
||||||
|
_handleValue(dc, value);
|
||||||
|
value=AQH_Value_List_Next(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AQH_Value_List_free(valueList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _handleValue(AQH_DATACLIENT *dc, const AQH_VALUE *value)
|
||||||
|
{
|
||||||
|
GWEN_DB_NODE *dbLocalArgs;
|
||||||
|
const char *wantedValueName;
|
||||||
|
const char *valueName;
|
||||||
|
int numDataPoints;
|
||||||
|
|
||||||
|
dbLocalArgs=AQH_DataClient_GetDbLocalArgs(dc);
|
||||||
|
numDataPoints=GWEN_DB_GetIntValue(dbLocalArgs, "numOfDatapoints", 0, 5);
|
||||||
|
wantedValueName=GWEN_DB_GetCharValue(dbLocalArgs, "valueName", 0, "*");
|
||||||
|
|
||||||
|
valueName=AQH_Value_GetName(value);
|
||||||
|
if (valueName &&
|
||||||
|
-1==GWEN_Text_ComparePattern(valueName, "stats_*", 0) &&
|
||||||
|
-1!=GWEN_Text_ComparePattern(valueName, wantedValueName, 0)) {
|
||||||
|
const char *valueNameForSystem;
|
||||||
|
uint64_t *dataPoints;
|
||||||
|
uint64_t recvdNum;
|
||||||
|
|
||||||
|
valueNameForSystem=AQH_Value_GetNameForSystem(value);
|
||||||
|
fprintf(stdout, " %s: ", valueName?valueName:"<empty>");
|
||||||
|
|
||||||
|
dataPoints=malloc(numDataPoints*sizeof(uint64_t)*2);
|
||||||
|
|
||||||
|
recvdNum=AQH_DataClient_GetLastData(dc, valueNameForSystem, dataPoints, numDataPoints);
|
||||||
|
if (recvdNum>0)
|
||||||
|
_printDataPoints(dataPoints, recvdNum);
|
||||||
|
|
||||||
|
free(dataPoints);
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _printDataPoints(const uint64_t *dataPoints, uint32_t numValues)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for(i=0; i<numValues; i++) {
|
||||||
|
uint64_t timestamp;
|
||||||
|
union {double f; uint64_t i;} u;
|
||||||
|
|
||||||
|
if (i)
|
||||||
|
fprintf(stdout, " | ");
|
||||||
|
timestamp=*(dataPoints++);
|
||||||
|
u.i=*(dataPoints++);
|
||||||
|
|
||||||
|
_printSingleDataPoint(timestamp, u.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _printSingleDataPoint(uint64_t timestamp, double data)
|
||||||
|
{
|
||||||
|
GWEN_TIMESTAMP *ts;
|
||||||
|
|
||||||
|
ts=GWEN_Timestamp_fromLocalTime((time_t) timestamp);
|
||||||
|
if (ts)
|
||||||
|
fprintf(stdout, "%lf (%04d/%02d/%02d-%02d:%02d:%02d)",
|
||||||
|
data,
|
||||||
|
GWEN_Timestamp_GetYear(ts),
|
||||||
|
GWEN_Timestamp_GetMonth(ts),
|
||||||
|
GWEN_Timestamp_GetDay(ts),
|
||||||
|
GWEN_Timestamp_GetHour(ts),
|
||||||
|
GWEN_Timestamp_GetMinute(ts),
|
||||||
|
GWEN_Timestamp_GetSecond(ts));
|
||||||
|
else
|
||||||
|
fprintf(stdout, "%lf", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
21
apps/aqhome-tool/data/devicestate.h
Normal file
21
apps/aqhome-tool/data/devicestate.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* This file is part of the project AqHome.
|
||||||
|
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
|
||||||
|
*
|
||||||
|
* The license for this file can be found in the file COPYING which you
|
||||||
|
* should have received along with this file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AQHOME_TOOL_DEVICESTATE_H
|
||||||
|
#define AQHOME_TOOL_DEVICESTATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <gwenhywfar/db.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int AQH_Tool_DeviceState(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./getvalues.h"
|
#include "./getdatapoints.h"
|
||||||
#include "../client.h"
|
#include "../client.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
@@ -52,7 +52,6 @@
|
|||||||
static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId);
|
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 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 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);
|
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
|
||||||
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
|
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
|
||||||
num=GWEN_DB_GetIntValue(dbArgs, "numOfLastDatapoints", 0, 0);
|
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)) {
|
if (tsBegin==(uint64_t) (-1)) {
|
||||||
DBG_ERROR(NULL, "Bad begin timestamp");
|
DBG_ERROR(NULL, "Bad begin timestamp");
|
||||||
return NULL;
|
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)) {
|
if (tsEnd==(uint64_t) (-1)) {
|
||||||
DBG_ERROR(NULL, "Bad end timestamp");
|
DBG_ERROR(NULL, "Bad end timestamp");
|
||||||
return NULL;
|
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 "../client.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
|
#include "aqhome/aqhome.h"
|
||||||
#include "aqhome/msg/ipc/m_ipc.h"
|
#include "aqhome/msg/ipc/m_ipc.h"
|
||||||
#include "aqhome/msg/ipc/m_ipc_result.h"
|
#include "aqhome/msg/ipc/m_ipc_result.h"
|
||||||
#include "aqhome/msg/ipc/data/m_ipcd.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_values.h"
|
||||||
|
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
|
||||||
|
|
||||||
#include <gwenhywfar/args.h>
|
#include <gwenhywfar/args.h>
|
||||||
#include <gwenhywfar/i18n.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_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, "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, "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},
|
{ 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},
|
{ 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}
|
{ 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)
|
AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
|
||||||
{
|
{
|
||||||
return AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID,
|
GWEN_DB_NODE *dbArgs;
|
||||||
AQH_IPC_PROTOCOL_DATA_VERSION,
|
const char *deviceName;
|
||||||
AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ,
|
const char *s;
|
||||||
msgId, 0,
|
int modality;
|
||||||
0, NULL);
|
|
||||||
|
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.
|
* 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
|
* The license for this file can be found in the file COPYING which you
|
||||||
* should have received along with this file.
|
* should have received along with this file.
|
||||||
@@ -17,9 +17,13 @@
|
|||||||
#include "./data/getdevices.h"
|
#include "./data/getdevices.h"
|
||||||
#include "./data/adddata.h"
|
#include "./data/adddata.h"
|
||||||
#include "./data/getdatapoints.h"
|
#include "./data/getdatapoints.h"
|
||||||
|
#include "./data/getfirstdata.h"
|
||||||
|
#include "./data/getlastdata.h"
|
||||||
|
#include "./data/getperioddata.h"
|
||||||
#include "./data/setdata.h"
|
#include "./data/setdata.h"
|
||||||
#include "./data/moddevice.h"
|
#include "./data/moddevice.h"
|
||||||
#include "./data/watch.h"
|
#include "./data/watch.h"
|
||||||
|
#include "./data/devicestate.h"
|
||||||
|
|
||||||
#include <aqhome/api.h>
|
#include <aqhome/api.h>
|
||||||
#include <aqhome/aqhome.h>
|
#include <aqhome/aqhome.h>
|
||||||
@@ -92,9 +96,13 @@ int main(int argc, char **argv)
|
|||||||
GWEN_FE_DAH("adddata", AQH_Tool_AddDataPoint, I18N("Send a datapoint to the data server")),
|
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("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("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("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("moddevice", AQH_Tool_ModDevice, I18N("Modify a device on the data server")),
|
||||||
GWEN_FE_DAH("watch", AQH_Tool_Watch, I18N("Watch and print changes of values on the data server")),
|
GWEN_FE_DAH("watch", AQH_Tool_Watch, I18N("Watch and print changes of values on the data server")),
|
||||||
|
GWEN_FE_DAH("devicestate", AQH_Tool_DeviceState, I18N("Show state of devices")),
|
||||||
GWEN_FE_END(),
|
GWEN_FE_END(),
|
||||||
};
|
};
|
||||||
const GWEN_FUNCS *func;
|
const GWEN_FUNCS *func;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "aqhome/msg/ipc/nodes/m_ipcn_setaccmsggrps.h"
|
#include "aqhome/msg/ipc/nodes/m_ipcn_setaccmsggrps.h"
|
||||||
#include "aqhome/ipc2/tcp_object.h"
|
#include "aqhome/ipc2/tcp_object.h"
|
||||||
#include "aqhome/ipc2/ipc_client.h"
|
#include "aqhome/ipc2/ipc_client.h"
|
||||||
|
#include "aqhome/dataclient/client.h"
|
||||||
|
|
||||||
|
|
||||||
#include <gwenhywfar/debug.h>
|
#include <gwenhywfar/debug.h>
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
#define UTILS_IPC_ENDPOINT_DEFAULT_MSGSIZE 4096
|
#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);
|
AQH_DEVICE *Utils_DeviceFromArgs(GWEN_DB_NODE *dbArgs);
|
||||||
|
|
||||||
|
uint64_t Utils_GetTimeStampFromString(const char *s);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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
|
hexfile
|
||||||
data
|
data
|
||||||
events2
|
events2
|
||||||
|
dataclient
|
||||||
</subdirs>
|
</subdirs>
|
||||||
|
|
||||||
|
|
||||||
@@ -79,6 +80,7 @@
|
|||||||
aqhhexfile
|
aqhhexfile
|
||||||
aqhdata
|
aqhdata
|
||||||
aqhevents2
|
aqhevents2
|
||||||
|
aqhdataclient
|
||||||
</useTargets>
|
</useTargets>
|
||||||
|
|
||||||
<libraries>
|
<libraries>
|
||||||
|
|||||||
@@ -267,6 +267,8 @@ int AQH_ValueModality_fromString(const char *s)
|
|||||||
return AQH_ValueModality_TVOC;
|
return AQH_ValueModality_TVOC;
|
||||||
else if (strcasecmp(s, "stats")==0)
|
else if (strcasecmp(s, "stats")==0)
|
||||||
return AQH_ValueModality_Stats;
|
return AQH_ValueModality_Stats;
|
||||||
|
else if (strcasecmp(s, "light")==0)
|
||||||
|
return AQH_ValueModality_Light;
|
||||||
}
|
}
|
||||||
return AQH_ValueModality_Unknown;
|
return AQH_ValueModality_Unknown;
|
||||||
}
|
}
|
||||||
@@ -285,6 +287,7 @@ const char *AQH_ValueModality_toString(int i)
|
|||||||
case AQH_ValueModality_Co2: return "co2";
|
case AQH_ValueModality_Co2: return "co2";
|
||||||
case AQH_ValueModality_TVOC: return "tvoc";
|
case AQH_ValueModality_TVOC: return "tvoc";
|
||||||
case AQH_ValueModality_Stats: return "stats";
|
case AQH_ValueModality_Stats: return "stats";
|
||||||
|
case AQH_ValueModality_Light: return "light";
|
||||||
case AQH_ValueModality_Unknown:
|
case AQH_ValueModality_Unknown:
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ enum {
|
|||||||
AQH_ValueModality_Motion,
|
AQH_ValueModality_Motion,
|
||||||
AQH_ValueModality_Co2,
|
AQH_ValueModality_Co2,
|
||||||
AQH_ValueModality_TVOC,
|
AQH_ValueModality_TVOC,
|
||||||
AQH_ValueModality_Stats
|
AQH_ValueModality_Stats,
|
||||||
|
AQH_ValueModality_Light
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define AQH_STORAGE_DATAPOINTS_STEPS 128
|
#define AQH_STORAGE_DATAPOINTS_STEPS 128
|
||||||
|
#define AQH_STORAGE_MAXOPENFILES 128
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -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 AQH_Storage_SetGetLastNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTNDATAPOINTS_FN fn)
|
||||||
{
|
{
|
||||||
AQH_STORAGE_GETLASTNDATAPOINTS_FN oldFn;
|
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 *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t fromTime, uint64_t toTime, uint64_t maxArrayLen)
|
uint64_t maxDataPointsRequested)
|
||||||
{
|
{
|
||||||
AQH_DATAFILE *df;
|
AQH_DATAFILE *df;
|
||||||
uint64_t numEntries;
|
uint64_t numEntries;
|
||||||
@@ -399,13 +410,9 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
numEntries=AQH_DataFile_GetNumberOfEntries(df);
|
numEntries=AQH_DataFile_GetNumberOfEntries(df);
|
||||||
if (fromTime==0 && toTime==0)
|
if (maxDataPointsRequested>numEntries)
|
||||||
arrayLen=(numEntries*2)+1;
|
maxDataPointsRequested=numEntries;
|
||||||
else
|
arrayLen=(maxDataPointsRequested*2)+1;
|
||||||
arrayLen=(AQH_STORAGE_DATAPOINTS_STEPS*2)+1;
|
|
||||||
if (arrayLen>maxArrayLen+1)
|
|
||||||
arrayLen=maxArrayLen+1;
|
|
||||||
|
|
||||||
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
|
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
|
||||||
if (arrayPtr==NULL) {
|
if (arrayPtr==NULL) {
|
||||||
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen);
|
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 ((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");
|
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
|
||||||
break;
|
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++]=ts;
|
||||||
arrayPtr[arrayPos++]=u.i;
|
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)
|
uint64_t *AQH_Storage_GetLastNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested)
|
||||||
{
|
{
|
||||||
AQH_DATAFILE *df;
|
AQH_DATAFILE *df;
|
||||||
@@ -601,6 +650,16 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
|
|||||||
DBG_ERROR(AQH_LOGDOMAIN, "Error opening/creating datafile for valueId \"%lu\"", (unsigned long int) valueId);
|
DBG_ERROR(AQH_LOGDOMAIN, "Error opening/creating datafile for valueId \"%lu\"", (unsigned long int) valueId);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (AQH_DataFile_List_GetCount(sto->dataFileList)>=AQH_STORAGE_MAXOPENFILES) {
|
||||||
|
AQH_DATAFILE *dfLast;
|
||||||
|
|
||||||
|
dfLast=AQH_DataFile_List_Last(sto->dataFileList);
|
||||||
|
if (dfLast) {
|
||||||
|
AQH_DataFile_Close(dfLast);
|
||||||
|
AQH_DataFile_List_Del(dfLast);
|
||||||
|
AQH_DataFile_free(dfLast);
|
||||||
|
}
|
||||||
|
}
|
||||||
DBG_DEBUG(AQH_LOGDOMAIN, "Adding datafile for valueId \"%lu\" to list", (unsigned long int) valueId);
|
DBG_DEBUG(AQH_LOGDOMAIN, "Adding datafile for valueId \"%lu\" to list", (unsigned long int) valueId);
|
||||||
AQH_DataFile_List_Add(df, sto->dataFileList);
|
AQH_DataFile_List_Add(df, sto->dataFileList);
|
||||||
}
|
}
|
||||||
@@ -612,8 +671,17 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
|
|||||||
|
|
||||||
AQH_DATAFILE *_findDataFileByValueId(const AQH_STORAGE *sto, uint64_t valueId)
|
AQH_DATAFILE *_findDataFileByValueId(const AQH_STORAGE *sto, uint64_t valueId)
|
||||||
{
|
{
|
||||||
if (sto && sto->dataFileList)
|
if (sto && sto->dataFileList) {
|
||||||
return AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
|
AQH_DATAFILE *df;
|
||||||
|
|
||||||
|
df=AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
|
||||||
|
if (df) {
|
||||||
|
/* move to front of list */
|
||||||
|
AQH_DataFile_List_Del(df);
|
||||||
|
AQH_DataFile_List_Insert(df, sto->dataFileList);
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ typedef uint64_t *(*AQH_STORAGE_GETDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t val
|
|||||||
uint64_t maxArrayLen);
|
uint64_t maxArrayLen);
|
||||||
typedef int (*AQH_STORAGE_GETFIRSTDATAPOINT_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
|
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 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);
|
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);
|
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_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 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);
|
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_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_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_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);
|
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_GETFIRSTDATAPOINT_FN getFirstDatapointFn;
|
||||||
AQH_STORAGE_GETLASTDATAPOINT_FN getLastDatapointFn;
|
AQH_STORAGE_GETLASTDATAPOINT_FN getLastDatapointFn;
|
||||||
AQH_STORAGE_GETLASTNDATAPOINTS_FN getLastNDatapointsFn;
|
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_INFO(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, 1899);
|
||||||
|
|
||||||
|
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/inherit.h>
|
||||||
#include <gwenhywfar/debug.h>
|
#include <gwenhywfar/debug.h>
|
||||||
|
#include <gwenhywfar/text.h>
|
||||||
|
|
||||||
//#include <sys/socket.h>
|
//#include <sys/socket.h>
|
||||||
#include <errno.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) {
|
else if (rv>0) {
|
||||||
/* data received */
|
/* data received */
|
||||||
DBG_DEBUG(AQH_LOGDOMAIN, "Received %d bytes", (int) rv);
|
DBG_DEBUG(AQH_LOGDOMAIN, "Received %d bytes", (int) rv);
|
||||||
|
// GWEN_Text_LogString((const char*) ptrBuffer, rv, NULL, GWEN_LoggerLevel_Error);
|
||||||
return (int) rv;
|
return (int) rv;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ AQH_MESSAGE *AQH_IpcEndpoint_WaitForResponseMsg(AQH_OBJECT *ipcEndpoint, uint32_
|
|||||||
uint16_t code;
|
uint16_t code;
|
||||||
|
|
||||||
code=AQH_IpcMessage_GetCode(msg);
|
code=AQH_IpcMessage_GetCode(msg);
|
||||||
DBG_ERROR(NULL, "Received unexpected message %d (%x), ignoring", code, code);
|
DBG_DEBUG(NULL, "Received unexpected message %d (%x), ignoring", code, code);
|
||||||
AQH_Message_free(msg);
|
AQH_Message_free(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#define AQH_MSG_READER_HEADER_SIZE 4
|
#define AQH_MSG_READER_HEADER_SIZE 4
|
||||||
#define AQH_MSG_READER_MINMSGSIZE 12
|
#define AQH_MSG_READER_MINMSGSIZE 12
|
||||||
#define AQH_MSG_READER_MAXMSGSIZE 10240
|
#define AQH_MSG_READER_MAXMSGSIZE 20480
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -176,17 +176,17 @@ int _handleSocketReady(AQH_OBJECT *o)
|
|||||||
{
|
{
|
||||||
AQH_TCPD_OBJECT *xo;
|
AQH_TCPD_OBJECT *xo;
|
||||||
|
|
||||||
DBG_INFO(NULL, "Socket ready");
|
DBG_DEBUG(NULL, "Socket ready");
|
||||||
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_TCPD_OBJECT, o);
|
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_TCPD_OBJECT, o);
|
||||||
if (xo) {
|
if (xo) {
|
||||||
int clientSk;
|
int clientSk;
|
||||||
|
|
||||||
clientSk=_acceptConnection(xo->fdSocket);
|
clientSk=_acceptConnection(xo->fdSocket);
|
||||||
if (clientSk<0) {
|
if (clientSk<0) {
|
||||||
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", clientSk);
|
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", clientSk);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DBG_INFO(AQH_LOGDOMAIN, "New connection");
|
DBG_NOTICE(AQH_LOGDOMAIN, "New connection");
|
||||||
if (0==AQH_Object_EmitSignal(o, AQH_TCPD_OBJECT_SIGNAL_NEWCONN, clientSk, NULL)) {
|
if (0==AQH_Object_EmitSignal(o, AQH_TCPD_OBJECT_SIGNAL_NEWCONN, clientSk, NULL)) {
|
||||||
DBG_ERROR(AQH_LOGDOMAIN, "New connection not handled");
|
DBG_ERROR(AQH_LOGDOMAIN, "New connection not handled");
|
||||||
close(clientSk);
|
close(clientSk);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
m_ipcd_values.h
|
m_ipcd_values.h
|
||||||
m_ipcd_getdata.h
|
m_ipcd_getdata.h
|
||||||
m_ipcd_setdata.h
|
m_ipcd_setdata.h
|
||||||
|
m_ipcd_getvalues.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
m_ipcd_values.c
|
m_ipcd_values.c
|
||||||
m_ipcd_getdata.c
|
m_ipcd_getdata.c
|
||||||
m_ipcd_setdata.c
|
m_ipcd_setdata.c
|
||||||
|
m_ipcd_getvalues.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
* ------------------------------------------------------------------------------------------------
|
* ------------------------------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static const char *_modeToChar(int mode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
@@ -37,6 +39,7 @@
|
|||||||
|
|
||||||
AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
||||||
uint32_t msgId, uint32_t refMsgId,
|
uint32_t msgId, uint32_t refMsgId,
|
||||||
|
int mode,
|
||||||
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num)
|
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num)
|
||||||
{
|
{
|
||||||
AQH_MESSAGE *msg;
|
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_BEGIN, tsBegin, buf);
|
||||||
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_END, tsEnd, 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_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,
|
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_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;
|
char *valueName;
|
||||||
uint64_t tsBegin;
|
uint64_t tsBegin;
|
||||||
uint64_t tsEnd;
|
uint64_t tsEnd;
|
||||||
|
uint64_t mode;
|
||||||
|
|
||||||
valueName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL):NULL;
|
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;
|
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;
|
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,
|
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)),
|
AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)),
|
||||||
sText?sText:"",
|
sText?sText:"",
|
||||||
AQH_IpcMessage_GetCode(msg),
|
AQH_IpcMessage_GetCode(msg),
|
||||||
AQH_IpcMessage_GetProtoId(msg),
|
AQH_IpcMessage_GetProtoId(msg),
|
||||||
AQH_IpcMessage_GetProtoVersion(msg),
|
AQH_IpcMessage_GetProtoVersion(msg),
|
||||||
valueName?valueName:"<empty>",
|
valueName?valueName:"<empty>",
|
||||||
|
_modeToChar(mode),
|
||||||
(unsigned long int) tsBegin,
|
(unsigned long int) tsBegin,
|
||||||
(unsigned long int) tsEnd);
|
(unsigned long int) tsEnd);
|
||||||
free(valueName);
|
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_BEGIN 0x0020
|
||||||
#define AQH_MSGDATA_GETDATA_TAGS_END 0x0021
|
#define AQH_MSGDATA_GETDATA_TAGS_END 0x0021
|
||||||
#define AQH_MSGDATA_GETDATA_TAGS_NUM 0x0022
|
#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,
|
AQHOME_API AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
|
||||||
uint32_t msgId, uint32_t refMsgId,
|
uint32_t msgId, uint32_t refMsgId,
|
||||||
|
int mode,
|
||||||
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num);
|
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,
|
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
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
m_flashend.h
|
m_flashend.h
|
||||||
m_flashready.h
|
m_flashready.h
|
||||||
m_flashresponse.h
|
m_flashresponse.h
|
||||||
|
m_range.h
|
||||||
</headers>
|
</headers>
|
||||||
|
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@
|
|||||||
m_flashend.c
|
m_flashend.c
|
||||||
m_flashready.c
|
m_flashready.c
|
||||||
m_flashresponse.c
|
m_flashresponse.c
|
||||||
|
m_range.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define AQH_MSG_OFFS_MEMSTATS_SECONDS 0 /* 4 bytes */
|
#define AQH_MSG_OFFS_MEMSTATS_UID 0 /* 4 bytes */
|
||||||
#define AQH_MSG_OFFS_MEMSTATS_UID 4 /* 4 bytes */
|
#define AQH_MSG_OFFS_MEMSTATS_SECONDS 4 /* 4 bytes */
|
||||||
#define AQH_MSG_OFFS_MEMSTATS_STACKUSAGE 8 /* 2 bytes */
|
#define AQH_MSG_OFFS_MEMSTATS_STACKUSAGE 8 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_MEMSTATS_BUFFERSUSED 10 /* 1 byte */
|
#define AQH_MSG_OFFS_MEMSTATS_BUFFERSUSED 10 /* 1 byte */
|
||||||
#define AQH_MSG_OFFS_MEMSTATS_MAXBUFFERSUSED 11 /* 1 byte */
|
#define AQH_MSG_OFFS_MEMSTATS_MAXBUFFERSUSED 11 /* 1 byte */
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "aqhome/msg/node/m_flashend.h"
|
#include "aqhome/msg/node/m_flashend.h"
|
||||||
#include "aqhome/msg/node/m_flashready.h"
|
#include "aqhome/msg/node/m_flashready.h"
|
||||||
#include "aqhome/msg/node/m_flashresponse.h"
|
#include "aqhome/msg/node/m_flashresponse.h"
|
||||||
|
#include "aqhome/msg/node/m_range.h"
|
||||||
|
|
||||||
#include <gwenhywfar/text.h>
|
#include <gwenhywfar/text.h>
|
||||||
|
|
||||||
@@ -212,6 +213,7 @@ const char *AQH_NodeMessage_MsgTypeToChar(uint8_t i)
|
|||||||
case AQH_MSG_TYPE_CLAIM_ADDRESS: return "ClaimAddress";
|
case AQH_MSG_TYPE_CLAIM_ADDRESS: return "ClaimAddress";
|
||||||
case AQH_MSG_TYPE_DENY_ADDRESS: return "DenyAddress";
|
case AQH_MSG_TYPE_DENY_ADDRESS: return "DenyAddress";
|
||||||
case AQH_MSG_TYPE_ADDRESS_RANGE: return "Range";
|
case AQH_MSG_TYPE_ADDRESS_RANGE: return "Range";
|
||||||
|
case AQH_MSG_TYPE_REENUM: return "Reenum";
|
||||||
|
|
||||||
case AQH_MSG_TYPE_FLASH_START: return "FlashStart";
|
case AQH_MSG_TYPE_FLASH_START: return "FlashStart";
|
||||||
case AQH_MSG_TYPE_FLASH_END: return "FlashEnd";
|
case AQH_MSG_TYPE_FLASH_END: return "FlashEnd";
|
||||||
@@ -246,6 +248,8 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d
|
|||||||
case AQH_MSG_TYPE_HAVE_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
case AQH_MSG_TYPE_HAVE_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
case AQH_MSG_TYPE_CLAIM_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
case AQH_MSG_TYPE_CLAIM_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
case AQH_MSG_TYPE_DENY_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
case AQH_MSG_TYPE_DENY_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
|
case AQH_MSG_TYPE_ADDRESS_RANGE: AQH_RangeMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
|
case AQH_MSG_TYPE_REENUM: AQH_RangeMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
|
|
||||||
case AQH_MSG_TYPE_FLASH_START: AQH_FlashStartMessage_DumpToBuffer(msg, dbuf, sText); break;
|
case AQH_MSG_TYPE_FLASH_START: AQH_FlashStartMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
case AQH_MSG_TYPE_FLASH_END: AQH_FlashEndMessage_DumpToBuffer(msg, dbuf, sText); break;
|
case AQH_MSG_TYPE_FLASH_END: AQH_FlashEndMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
@@ -266,7 +270,6 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d
|
|||||||
|
|
||||||
case AQH_MSG_TYPE_DEBUG:
|
case AQH_MSG_TYPE_DEBUG:
|
||||||
case AQH_MSG_TYPE_TWIBUSMEMBER:
|
case AQH_MSG_TYPE_TWIBUSMEMBER:
|
||||||
case AQH_MSG_TYPE_ADDRESS_RANGE:
|
|
||||||
default: AQH_NodeMessage_DumpToBuffer(msg, dbuf, sText); break;
|
default: AQH_NodeMessage_DumpToBuffer(msg, dbuf, sText); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
#define AQH_MSG_TYPE_PING 10
|
#define AQH_MSG_TYPE_PING 10
|
||||||
#define AQH_MSG_TYPE_PONG 11
|
#define AQH_MSG_TYPE_PONG 11
|
||||||
#define AQH_MSG_TYPE_COMSENDSTATS 20
|
#define AQH_MSG_TYPE_COMSENDSTATS 22
|
||||||
#define AQH_MSG_TYPE_COMRECVSTATS 21
|
#define AQH_MSG_TYPE_COMRECVSTATS 23
|
||||||
#define AQH_MSG_TYPE_TWIBUSMEMBER 30
|
#define AQH_MSG_TYPE_TWIBUSMEMBER 30
|
||||||
#define AQH_MSG_TYPE_DEBUG 40
|
#define AQH_MSG_TYPE_DEBUG 40
|
||||||
#define AQH_MSG_TYPE_VALUE 50 /* deprecated */
|
#define AQH_MSG_TYPE_VALUE 50 /* deprecated */
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
#define AQH_MSG_TYPE_CLAIM_ADDRESS 62
|
#define AQH_MSG_TYPE_CLAIM_ADDRESS 62
|
||||||
#define AQH_MSG_TYPE_DENY_ADDRESS 63
|
#define AQH_MSG_TYPE_DENY_ADDRESS 63
|
||||||
#define AQH_MSG_TYPE_ADDRESS_RANGE 64
|
#define AQH_MSG_TYPE_ADDRESS_RANGE 64
|
||||||
|
#define AQH_MSG_TYPE_REENUM 65
|
||||||
|
|
||||||
#define AQH_MSG_TYPE_FLASH_START 70
|
#define AQH_MSG_TYPE_FLASH_START 70
|
||||||
#define AQH_MSG_TYPE_FLASH_END 71
|
#define AQH_MSG_TYPE_FLASH_END 71
|
||||||
|
|||||||
61
aqhome/msg/node/m_range.c
Normal file
61
aqhome/msg/node/m_range.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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/node/m_range.h"
|
||||||
|
#include "aqhome/msg/node/m_node.h"
|
||||||
|
|
||||||
|
#include <gwenhywfar/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define AQH_MSG_OFFS_RANGE_UID 0 /* 4 bytes */
|
||||||
|
#define AQH_MSG_OFFS_RANGE_BEGIN 4 /* 1 bytes */
|
||||||
|
#define AQH_MSG_OFFS_RANGE_END 5 /* 1 bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t AQH_RangeMessage_GetUid(const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
return AQH_Message_ReadUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_UID, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t AQH_RangeMessage_GetRangeBegin(const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_BEGIN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t AQH_RangeMessage_GetRangeEnd(const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_END, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AQH_RangeMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText)
|
||||||
|
{
|
||||||
|
GWEN_Buffer_AppendArgs(dbuf,
|
||||||
|
"0x%02x->0x%02x: RANGE(%s) %s (uid=0x%08x, begin=0x%x, end=0x%x)\n",
|
||||||
|
AQH_NodeMessage_GetSourceAddress(msg),
|
||||||
|
AQH_NodeMessage_GetDestAddress(msg),
|
||||||
|
AQH_NodeMessage_MsgTypeToChar(AQH_NodeMessage_GetMsgType(msg)),
|
||||||
|
sText,
|
||||||
|
(unsigned int) AQH_RangeMessage_GetUid(msg),
|
||||||
|
AQH_RangeMessage_GetRangeBegin(msg),
|
||||||
|
AQH_RangeMessage_GetRangeEnd(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
30
aqhome/msg/node/m_range.h
Normal file
30
aqhome/msg/node/m_range.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* 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_RANGE_H
|
||||||
|
#define AQH_M_RANGE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <aqhome/api.h>
|
||||||
|
#include <aqhome/ipc2/message.h>
|
||||||
|
|
||||||
|
#include <gwenhywfar/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* This message is used for message types ClaimAddr, DenyAddr, HaveAddr */
|
||||||
|
|
||||||
|
AQHOME_API uint32_t AQH_RangeMessage_GetUid(const AQH_MESSAGE *msg);
|
||||||
|
AQHOME_API uint8_t AQH_RangeMessage_GetAddr(const AQH_MESSAGE *msg);
|
||||||
|
AQHOME_API uint8_t AQH_RangeMessage_GetRangeBegin(const AQH_MESSAGE *msg);
|
||||||
|
AQHOME_API uint8_t AQH_RangeMessage_GetRangeEnd(const AQH_MESSAGE *msg);
|
||||||
|
|
||||||
|
AQHOME_API void AQH_RangeMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,13 +18,21 @@
|
|||||||
#include <gwenhywfar/debug.h>
|
#include <gwenhywfar/debug.h>
|
||||||
|
|
||||||
|
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_UID 0 /* 4 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_UID 0 /* 4 bytes */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_PACKETSIN 4 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_IFACE 4 /* 1 byte */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_CRCERRORS 6 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_PACKETSIN 5 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_IOERRORS 8 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_CRCERRORS 7 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_NOBUFFER 10 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_IOERRORS 9 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_HANDLED 12 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_NOBUFFER 11 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_RECVSTATS_MISSED 14 /* 2 bytes */
|
#define AQH_MSG_OFFS_RECVSTATS_MSGSIZEERRORS 13 /* 2 bytes */
|
||||||
|
#define AQH_MSG_OFFS_RECVSTATS_MISSED 15 /* 2 bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t AQH_RecvStatsMessage_GetInterface(const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RECVSTATS_IFACE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -63,9 +71,9 @@ uint16_t AQH_RecvStatsMessage_GetNoBufferErrors(const AQH_MESSAGE *msg)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t AQH_RecvStatsMessage_GetHandled(const AQH_MESSAGE *msg)
|
uint16_t AQH_RecvStatsMessage_GetMsgSizeErrors(const AQH_MESSAGE *msg)
|
||||||
{
|
{
|
||||||
return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RECVSTATS_HANDLED, 0);
|
return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RECVSTATS_MSGSIZEERRORS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,17 +88,18 @@ uint16_t AQH_RecvStatsMessage_GetMissed(const AQH_MESSAGE *msg)
|
|||||||
void AQH_RecvStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText)
|
void AQH_RecvStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText)
|
||||||
{
|
{
|
||||||
GWEN_Buffer_AppendArgs(dbuf,
|
GWEN_Buffer_AppendArgs(dbuf,
|
||||||
"0x%02x->0x%02x: RECVSTATS %s "
|
"0x%02x->0x%02x: RECVSTATS %s"
|
||||||
"(uid=0x%08x, in=%d, crc errs=%d, io errs=%d, nobuf errs=%d, handled=%d, missed=%d)\n",
|
"(uid=0x%08x, dev=%d, in=%d, eCrc=%d, eIo=%d, eNobuf=%d, eMsgSize=%d, eMissed=%d)\n",
|
||||||
AQH_NodeMessage_GetSourceAddress(msg),
|
AQH_NodeMessage_GetSourceAddress(msg),
|
||||||
AQH_NodeMessage_GetDestAddress(msg),
|
AQH_NodeMessage_GetDestAddress(msg),
|
||||||
sText,
|
sText,
|
||||||
(unsigned int) AQH_RecvStatsMessage_GetUid(msg),
|
(unsigned int) AQH_RecvStatsMessage_GetUid(msg),
|
||||||
|
AQH_RecvStatsMessage_GetInterface(msg),
|
||||||
AQH_RecvStatsMessage_GetPacketsIn(msg),
|
AQH_RecvStatsMessage_GetPacketsIn(msg),
|
||||||
AQH_RecvStatsMessage_GetCrcErrors(msg),
|
AQH_RecvStatsMessage_GetCrcErrors(msg),
|
||||||
AQH_RecvStatsMessage_GetIoErrors(msg),
|
AQH_RecvStatsMessage_GetIoErrors(msg),
|
||||||
AQH_RecvStatsMessage_GetNoBufferErrors(msg),
|
AQH_RecvStatsMessage_GetNoBufferErrors(msg),
|
||||||
AQH_RecvStatsMessage_GetHandled(msg),
|
AQH_RecvStatsMessage_GetMsgSizeErrors(msg),
|
||||||
AQH_RecvStatsMessage_GetMissed(msg));
|
AQH_RecvStatsMessage_GetMissed(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AQHOME_API uint8_t AQH_RecvStatsMessage_GetInterface(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint32_t AQH_RecvStatsMessage_GetUid(const AQH_MESSAGE *msg);
|
AQHOME_API uint32_t AQH_RecvStatsMessage_GetUid(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetPacketsIn(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetPacketsIn(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetCrcErrors(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetCrcErrors(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetIoErrors(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetIoErrors(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetNoBufferErrors(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetNoBufferErrors(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetHandled(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetMsgSizeErrors(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_RecvStatsMessage_GetMissed(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_RecvStatsMessage_GetMissed(const AQH_MESSAGE *msg);
|
||||||
|
|
||||||
AQHOME_API void AQH_RecvStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText);
|
AQHOME_API void AQH_RecvStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* This file is part of the project AqHome.
|
* 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
|
* The license for this file can be found in the file COPYING which you
|
||||||
* should have received along with this file.
|
* should have received along with this file.
|
||||||
@@ -19,9 +19,17 @@
|
|||||||
|
|
||||||
|
|
||||||
#define AQH_MSG_OFFS_SENDSTATS_UID 0 /* 4 bytes */
|
#define AQH_MSG_OFFS_SENDSTATS_UID 0 /* 4 bytes */
|
||||||
#define AQH_MSG_OFFS_SENDSTATS_PACKETSOUT 4 /* 2 bytes */
|
#define AQH_MSG_OFFS_SENDSTATS_IFACE 4 /* 1 byte */
|
||||||
#define AQH_MSG_OFFS_SENDSTATS_COLLISIONS 6 /* 2 bytes */
|
#define AQH_MSG_OFFS_SENDSTATS_PACKETSOUT 5 /* 2 bytes */
|
||||||
#define AQH_MSG_OFFS_SENDSTATS_BUSY 8 /* 2 bytes */
|
#define AQH_MSG_OFFS_SENDSTATS_COLLISIONS 7 /* 2 bytes */
|
||||||
|
#define AQH_MSG_OFFS_SENDSTATS_BUSY 9 /* 2 bytes */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t AQH_SendStatsMessage_GetInterface(const AQH_MESSAGE *msg)
|
||||||
|
{
|
||||||
|
return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_IFACE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -57,11 +65,12 @@ void AQH_SendStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf
|
|||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
GWEN_Buffer_AppendArgs(dbuf,
|
GWEN_Buffer_AppendArgs(dbuf,
|
||||||
"0x%02x->0x%02x: SENDSTATS %s (uid=0x%08x, out=%d, collisions=%d, busy line=%d)\n",
|
"0x%02x->0x%02x: SENDSTATS %s (uid=0x%08x, dev=%d, out=%d, collisions=%d, busy line=%d)\n",
|
||||||
AQH_NodeMessage_GetSourceAddress(msg),
|
AQH_NodeMessage_GetSourceAddress(msg),
|
||||||
AQH_NodeMessage_GetDestAddress(msg),
|
AQH_NodeMessage_GetDestAddress(msg),
|
||||||
sText,
|
sText,
|
||||||
(unsigned int) AQH_SendStatsMessage_GetUid(msg),
|
(unsigned int) AQH_SendStatsMessage_GetUid(msg),
|
||||||
|
AQH_SendStatsMessage_GetInterface(msg),
|
||||||
AQH_SendStatsMessage_GetPacketsOut(msg),
|
AQH_SendStatsMessage_GetPacketsOut(msg),
|
||||||
AQH_SendStatsMessage_GetCollisions(msg),
|
AQH_SendStatsMessage_GetCollisions(msg),
|
||||||
AQH_SendStatsMessage_GetBusyErrors(msg));
|
AQH_SendStatsMessage_GetBusyErrors(msg));
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AQHOME_API uint8_t AQH_SendStatsMessage_GetInterface(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint32_t AQH_SendStatsMessage_GetUid(const AQH_MESSAGE *msg);
|
AQHOME_API uint32_t AQH_SendStatsMessage_GetUid(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_SendStatsMessage_GetPacketsOut(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_SendStatsMessage_GetPacketsOut(const AQH_MESSAGE *msg);
|
||||||
AQHOME_API uint16_t AQH_SendStatsMessage_GetCollisions(const AQH_MESSAGE *msg);
|
AQHOME_API uint16_t AQH_SendStatsMessage_GetCollisions(const AQH_MESSAGE *msg);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "aqhome/aqhome.h"
|
||||||
#include "aqhome/msg/node/m_value.h"
|
#include "aqhome/msg/node/m_value.h"
|
||||||
#include "aqhome/msg/node/m_node.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)
|
const char *AQH_ValueMessage_GetValueTypeName(const AQH_MESSAGE *msg)
|
||||||
{
|
{
|
||||||
uint8_t t;
|
return AQH_ValueModality_toString(AQH_ValueMessage_GetValueType(msg));
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
network
|
network
|
||||||
reportsensors
|
reportsensors
|
||||||
stats
|
stats
|
||||||
|
router
|
||||||
|
hub
|
||||||
|
forwarder
|
||||||
</subdirs>
|
</subdirs>
|
||||||
|
|
||||||
<extradist>
|
<extradist>
|
||||||
|
|||||||
@@ -3,15 +3,13 @@
|
|||||||
<gwbuild>
|
<gwbuild>
|
||||||
|
|
||||||
<subdirs>
|
<subdirs>
|
||||||
boot
|
|
||||||
main
|
|
||||||
</subdirs>
|
</subdirs>
|
||||||
|
|
||||||
<extradist>
|
<extradist>
|
||||||
defs.asm
|
main.asm
|
||||||
README
|
|
||||||
</extradist>
|
</extradist>
|
||||||
|
|
||||||
|
|
||||||
</gwbuild>
|
</gwbuild>
|
||||||
|
|
||||||
|
|
||||||
359
avr/apps/forwarder/main.asm
Normal file
359
avr/apps/forwarder/main.asm
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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. *
|
||||||
|
; ***************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; defines
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; network interfaces
|
||||||
|
|
||||||
|
.equ NETDEV0_IFACENUM = 1
|
||||||
|
.equ NETDEV1_IFACENUM = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; data
|
||||||
|
|
||||||
|
.dseg
|
||||||
|
|
||||||
|
; nothing so far
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; code
|
||||||
|
|
||||||
|
.cseg
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppForwarder_Init @global
|
||||||
|
|
||||||
|
AppForwarder_Init:
|
||||||
|
; set interface number for NETDEV0
|
||||||
|
ldi r16, NETDEV0_IFACENUM
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_IFACENUM, r16
|
||||||
|
; set interface number for NETDEV1
|
||||||
|
ldi r16, NETDEV1_IFACENUM
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_IFACENUM, r16
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppForwarder_EveryDay @global
|
||||||
|
;
|
||||||
|
; @clobbers R16, R17, X
|
||||||
|
|
||||||
|
AppForwarder_EveryDay:
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppForwarder_Run @global
|
||||||
|
;
|
||||||
|
; Read messages from either interface and forward to the other one.
|
||||||
|
|
||||||
|
AppForwarder_Run:
|
||||||
|
rjmp appForwarderCheckRecvdMsg
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderCheckRecvdMsg
|
||||||
|
;
|
||||||
|
; Read messages from either interface and forward to the other one.
|
||||||
|
; @return CFLAG set if something done, cleared otherwise
|
||||||
|
; @clobbers any
|
||||||
|
|
||||||
|
appForwarderCheckRecvdMsg:
|
||||||
|
rcall NET_PeekNextIncomingMsgNum ; check read queue (bufNum->r16)
|
||||||
|
brcc appForwarderCheckRecvdMsg_ret ; no msg, jmp
|
||||||
|
rcall NET_Buffer_Locate ; (R17)
|
||||||
|
push r16
|
||||||
|
ld r16, X ; read buffer header
|
||||||
|
andi r16, 0x0f ; keep interface number (in low nibble)
|
||||||
|
rcall appForwarderGetDeviceByIfaceNum ; Y=src interface (R17)
|
||||||
|
pop r16
|
||||||
|
brcc appForwarderCheckRecvdMsg_ret ; interface not found
|
||||||
|
adiw xh:xl, 1 ; point to message begin
|
||||||
|
|
||||||
|
push r16
|
||||||
|
rcall appForwarderHandleMsgAnyDev ; check for message we should handle (ping etc)
|
||||||
|
pop r16
|
||||||
|
|
||||||
|
; let system handle incoming messages
|
||||||
|
push r16
|
||||||
|
rcall appForwarderLetSysHandleMsg
|
||||||
|
pop r16
|
||||||
|
|
||||||
|
; forward to other interface
|
||||||
|
ldd r17, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
rcall appForwarderSendToOtherDev
|
||||||
|
brcc appForwarderCheckRecvdMsg_ret ; could not add, jmp
|
||||||
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
||||||
|
sec
|
||||||
|
appForwarderCheckRecvdMsg_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderHandleMsgAnyDev @global
|
||||||
|
;
|
||||||
|
; @param Y pointer to source interface for the message
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @return CFLAG set if msg handled, cleared otherwise
|
||||||
|
; @clobbers any, !X
|
||||||
|
|
||||||
|
appForwarderHandleMsgAnyDev:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appForwarderHandleMsgAnyDev_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp appForwarderHandleMsgAnyDev_end
|
||||||
|
appForwarderHandleMsgAnyDev_savedX:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm?
|
||||||
|
ld r16, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
||||||
|
cpi r16, NETMSG_CMD_REBOOT_REQUEST
|
||||||
|
breq appForwarderHandleMsgAnyDev_handleRebootMsg
|
||||||
|
cpi r16, NETMSG_CMD_PING
|
||||||
|
breq appForwarderHandleMsgAnyDev_handlePingMsg
|
||||||
|
cpi r16, NETMSG_CMD_CLAIM_ADDRESS
|
||||||
|
breq appForwarderHandleMsgAnyDev_handleClaimAddr
|
||||||
|
rjmp appForwarderHandleMsgAnyDev_clcRet
|
||||||
|
appForwarderHandleMsgAnyDev_handleRebootMsg:
|
||||||
|
rcall appForwarderHandleRebootRequest
|
||||||
|
ret
|
||||||
|
appForwarderHandleMsgAnyDev_handlePingMsg:
|
||||||
|
rcall appForwarderHandlePingRequest
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
appForwarderHandleMsgAnyDev_handleClaimAddr:
|
||||||
|
rcall appForwarderHandleClaimAddrRequest
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
appForwarderHandleMsgAnyDev_clcRet:
|
||||||
|
clc
|
||||||
|
appForwarderHandleMsgAnyDev_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderHandleClaimAddrRequest
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @param Y pointer to source interface for the message
|
||||||
|
; @clobbers
|
||||||
|
|
||||||
|
appForwarderHandleClaimAddrRequest:
|
||||||
|
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
||||||
|
lds r16, netInterfaceData+NET_IFACE_OFFS_ADDRESS
|
||||||
|
cp r19, r16
|
||||||
|
brne appForwarderHandleClaimAddrRequest_ret
|
||||||
|
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr
|
||||||
|
rcall appForwarderSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
appForwarderHandleClaimAddrRequest_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderSendAddrMsg
|
||||||
|
;
|
||||||
|
; @param R18 command
|
||||||
|
; @param R19 address to send
|
||||||
|
; @param Y pointer to interface to send to
|
||||||
|
; @clobbers R16 (R17, R18, R19, R20, R21, X, Y)
|
||||||
|
|
||||||
|
appForwarderSendAddrMsg:
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
brcc appForwarderSendAddrMsg_end
|
||||||
|
push r16
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
appForwarderSendAddrMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderHandleRebootRequest
|
||||||
|
;
|
||||||
|
; Doesn't return if reboot msg is valid.
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
|
||||||
|
appForwarderHandleRebootRequest:
|
||||||
|
rcall NETMSG_RebootRequestRead
|
||||||
|
brcc appForwarderHandleRebootRequest_end
|
||||||
|
; reboot
|
||||||
|
cli
|
||||||
|
bigjmp BOOTLOADER_ADDR
|
||||||
|
appForwarderHandleRebootRequest_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderHandlePingRequest
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @param Y pointer to source interface for the message
|
||||||
|
|
||||||
|
appForwarderHandlePingRequest:
|
||||||
|
ld r17, X
|
||||||
|
lds r16, (netInterfaceData+NET_IFACE_OFFS_ADDRESS)
|
||||||
|
cp r16, r17
|
||||||
|
breq appForwarderHandlePingRequest_forMe
|
||||||
|
cpi r17, 0xff
|
||||||
|
breq appForwarderHandlePingRequest_forMe
|
||||||
|
clc
|
||||||
|
rjmp appForwarderHandlePingRequest_end
|
||||||
|
appForwarderHandlePingRequest_forMe:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||||
|
ld r17, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||||
|
push r17
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
pop r17
|
||||||
|
brcc appForwarderHandlePingRequest_end ; jmp on error
|
||||||
|
push r16 ; buffer num
|
||||||
|
mov r16, r17 ; DEST addr
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16 ; buffer num
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
appForwarderHandlePingRequest_end:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderLetSysHandleMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to msg to handle (point behind the buffer header!)
|
||||||
|
; @param Y pointer to source interface for the message
|
||||||
|
; @clobbers any, !X
|
||||||
|
|
||||||
|
appForwarderLetSysHandleMsg:
|
||||||
|
ld r16, X
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appForwarderLetSysHandleMsg_forMe
|
||||||
|
lds r17, netInterfaceData+NET_IFACE_OFFS_ADDRESS
|
||||||
|
cp r16, r17
|
||||||
|
brne appForwarderLetSysHandleMsg_end
|
||||||
|
appForwarderLetSysHandleMsg_forMe:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall onMessageReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall mainModulesOnPacketReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall mainAppsOnPacketReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
appForwarderLetSysHandleMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderSendToOtherDev
|
||||||
|
; @param r16 buffer num
|
||||||
|
; @param r17 src interface num
|
||||||
|
|
||||||
|
appForwarderSendToOtherDev:
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
ldd r18, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
andi r18, 0x0f
|
||||||
|
cp r18, r17
|
||||||
|
breq appForwarderSendToAllDevsBut_check2
|
||||||
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
|
rjmp appForwarderSendToOtherDev_ret
|
||||||
|
appForwarderSendToAllDevsBut_check2:
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
ldd r18, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
andi r18, 0x0f
|
||||||
|
cp r18, r17
|
||||||
|
breq appForwarderSendToOtherDev_ret
|
||||||
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
|
appForwarderSendToOtherDev_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appForwarderGetDeviceByIfaceNum
|
||||||
|
;
|
||||||
|
; @param r16 interface number
|
||||||
|
; @return CFLAG set if interface found (cleared otherwise)
|
||||||
|
; @return Y pointer to interface with given number
|
||||||
|
; @clobbers r17
|
||||||
|
|
||||||
|
appForwarderGetDeviceByIfaceNum:
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
ldd r17, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
cp r16, r17
|
||||||
|
breq appForwarderGetDeviceByIfaceNum_secRet
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
ldd r17, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
cp r16, r17
|
||||||
|
breq appForwarderGetDeviceByIfaceNum_secRet
|
||||||
|
clc
|
||||||
|
rjmp appForwarderGetDeviceByIfaceNum_ret
|
||||||
|
appForwarderGetDeviceByIfaceNum_secRet:
|
||||||
|
sec
|
||||||
|
appForwarderGetDeviceByIfaceNum_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
15
avr/apps/hub/0BUILD
Normal file
15
avr/apps/hub/0BUILD
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml?>
|
||||||
|
|
||||||
|
<gwbuild>
|
||||||
|
|
||||||
|
<subdirs>
|
||||||
|
</subdirs>
|
||||||
|
|
||||||
|
<extradist>
|
||||||
|
main.asm
|
||||||
|
</extradist>
|
||||||
|
|
||||||
|
|
||||||
|
</gwbuild>
|
||||||
|
|
||||||
|
|
||||||
715
avr/apps/hub/main.asm
Normal file
715
avr/apps/hub/main.asm
Normal file
@@ -0,0 +1,715 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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. *
|
||||||
|
; ***************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; defines
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; network interfaces
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; data
|
||||||
|
|
||||||
|
.dseg
|
||||||
|
|
||||||
|
appHubDataBegin:
|
||||||
|
appHubRangeBegin: .byte 1
|
||||||
|
appHubRangeEnd: .byte 1
|
||||||
|
appHubDataEnd:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; code
|
||||||
|
|
||||||
|
.cseg
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppHub_Init @global
|
||||||
|
|
||||||
|
AppHub_Init:
|
||||||
|
ldi xh, HIGH(appHubDataBegin)
|
||||||
|
ldi xl, LOW(appHubDataBegin)
|
||||||
|
clr r16
|
||||||
|
ldi r17, (appHubDataEnd-appHubDataBegin)
|
||||||
|
rcall Utils_FillSram
|
||||||
|
|
||||||
|
; set device address and interface number in all interfaces
|
||||||
|
ldi r16, 0xf0 ; hub address
|
||||||
|
ldi r17, 1 ; first interface number
|
||||||
|
rcall appHubAllSetAddrIfaceNumAndRange ; (R17, R19, R20, Y)
|
||||||
|
|
||||||
|
; TODO: read ranges from EEPROM
|
||||||
|
; TODO: send range msg to all interfaces
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppHub_Run @global
|
||||||
|
;
|
||||||
|
; Read messages from any interface, handle them and probably forward to the other
|
||||||
|
; interfaces.
|
||||||
|
; @return CFLAG set if something done, cleared otherwise
|
||||||
|
; @clobbers all
|
||||||
|
|
||||||
|
AppHub_Run:
|
||||||
|
rjmp appHubCheckRecvdMsg
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubGetDeviceByIfaceNum
|
||||||
|
;
|
||||||
|
; @param r16 interface number
|
||||||
|
; @clobbers r17, r19, r20, Y
|
||||||
|
|
||||||
|
appHubGetDeviceByIfaceNum:
|
||||||
|
ldi r19, COM_PORTS
|
||||||
|
ldi yl, LOW(com2w0_iface) ; first interface
|
||||||
|
ldi yh, HIGH(com2w0_iface)
|
||||||
|
appHubGetDeviceByIfaceNum_loop:
|
||||||
|
ldd r17, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
cp r16, r17
|
||||||
|
sec ; mark "found"
|
||||||
|
breq appHubGetDeviceByIfaceNum_ret
|
||||||
|
ldi r20, COM2W_IFACE_SIZE
|
||||||
|
add yl, r20
|
||||||
|
adc yh, r20
|
||||||
|
sub yh, r20
|
||||||
|
dec r19
|
||||||
|
brne appHubGetDeviceByIfaceNum_loop
|
||||||
|
clc ; mark "not found"
|
||||||
|
appHubGetDeviceByIfaceNum_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubAllSetAddrIfaceNumAndRange
|
||||||
|
;
|
||||||
|
; @clobbers R17, R18, R19, R20, Y
|
||||||
|
|
||||||
|
appHubAllSetAddrIfaceNumAndRange:
|
||||||
|
ldi r19, COM_PORTS
|
||||||
|
ldi yl, LOW(com2w0_iface) ; first interface
|
||||||
|
ldi yh, HIGH(com2w0_iface)
|
||||||
|
ldi r18, 0x10
|
||||||
|
appHubAllSetAddrIfaceNumAndRange_loop:
|
||||||
|
; set address
|
||||||
|
std Y+NET_IFACE_OFFS_ADDRESS, r16
|
||||||
|
; set interface number
|
||||||
|
std Y+NET_IFACE_OFFS_IFACENUM, r17
|
||||||
|
inc r17
|
||||||
|
; set default range (step of 16)
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r18
|
||||||
|
subi r18, -15
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_END, r18
|
||||||
|
inc r18
|
||||||
|
; next interface
|
||||||
|
ldi r20, COM2W_IFACE_SIZE
|
||||||
|
add yl, r20
|
||||||
|
adc yh, r20
|
||||||
|
sub yh, r20
|
||||||
|
dec r19
|
||||||
|
brne appHubAllSetAddrIfaceNumAndRange_loop
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendRangeMsg
|
||||||
|
;
|
||||||
|
; @param R18 msg code
|
||||||
|
; @param Y pointer to interface data
|
||||||
|
; @return CFLAG set if message enqueued, cleared on error
|
||||||
|
; @clobbers (R16, R17, R18, R19, R20, R21, R24, R25, X)
|
||||||
|
|
||||||
|
appHubSendRangeMsg:
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
brcc appHubSendRangeMsg_end
|
||||||
|
push r16
|
||||||
|
ldd r20, Y+NET_IFACE_OFFS_RANGE_BEGIN
|
||||||
|
ldd r21, Y+NET_IFACE_OFFS_RANGE_END
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Range_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16
|
||||||
|
rcall appHubSendMsg ; (R16, R17, R18, R24, R25, X)
|
||||||
|
appHubSendRangeMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendDenyAddrR19
|
||||||
|
;
|
||||||
|
; @param R19 address to send
|
||||||
|
; @clobbers R16, R17, R18, R19, R20, R21, X, Y
|
||||||
|
|
||||||
|
appHubSendDenyAddrR19:
|
||||||
|
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr
|
||||||
|
rjmp appHubSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendAddrMsg
|
||||||
|
;
|
||||||
|
; @param R18 command
|
||||||
|
; @param R19 address to send
|
||||||
|
; @clobbers R16 (R17, R18, R19, R20, R21, X, Y)
|
||||||
|
|
||||||
|
appHubSendAddrMsg:
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
brcc appHubSendAddrMsg_end
|
||||||
|
push r16
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16
|
||||||
|
rcall appHubSendMsg ; (R16, R17, R18, R24, R25, X)
|
||||||
|
appHubSendAddrMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendValueResponse
|
||||||
|
;
|
||||||
|
; @param R17 value id
|
||||||
|
; @param R19:R18 value
|
||||||
|
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
||||||
|
; @param R23 command
|
||||||
|
; @param R25:R24 ref msg id
|
||||||
|
; @return CFLAG on success, cleared on error
|
||||||
|
; @clobbers r22 (r16, r17, r18, r19, r20, r21, r23, r24, r25, X)
|
||||||
|
|
||||||
|
appHubSendValueResponse:
|
||||||
|
push r17
|
||||||
|
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
pop r17
|
||||||
|
brcc appHubSendValueResponse_end ; jmp on error
|
||||||
|
push r16 ; buffer num
|
||||||
|
ldi r16, 0xff ; DEST addr
|
||||||
|
clr r22 ; value type
|
||||||
|
adiw xh:xl, 1
|
||||||
|
rcall NETMSG_ValueWriteResponse ; (R16, R17, R18, R19, R20, R21, R23, R24, R25)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16 ; buffer num
|
||||||
|
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
appHubSendValueResponse_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendMsg
|
||||||
|
;
|
||||||
|
; @param R16 num of allocated buffer
|
||||||
|
; @param Y pointer to interface data
|
||||||
|
; @param X msg to send (points to start of allocated buffer, e.g. buffer header)
|
||||||
|
; @return CFLAG set if message enqueued, cleared on error
|
||||||
|
; @clobbers R16 (R17, R18, R24, R25, X)
|
||||||
|
|
||||||
|
appHubSendMsg:
|
||||||
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
|
brcs appHubSendMsg_end
|
||||||
|
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||||
|
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||||
|
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||||
|
clc
|
||||||
|
appHubSendMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubAllResetStats
|
||||||
|
;
|
||||||
|
; @clobbers r19, r20, Y (r16, r17, X)
|
||||||
|
|
||||||
|
appHubAllResetStats:
|
||||||
|
ldi r19, COM_PORTS
|
||||||
|
ldi yl, LOW(com2w0_iface) ; first interface
|
||||||
|
ldi yh, HIGH(com2w0_iface)
|
||||||
|
appHubAllResetStats_loop:
|
||||||
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
|
||||||
|
ldi r20, COM2W_IFACE_SIZE
|
||||||
|
add yl, r20
|
||||||
|
adc yh, r20
|
||||||
|
sub yh, r20
|
||||||
|
dec r19
|
||||||
|
brne appHubAllResetStats_loop
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppHub_EveryDay @global
|
||||||
|
;
|
||||||
|
; @clobbers R16, R17, X
|
||||||
|
|
||||||
|
AppHub_EveryDay:
|
||||||
|
rcall appHubAllResetStats
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubSendMsgToAllOthers
|
||||||
|
;
|
||||||
|
; @param R16 buffer number
|
||||||
|
; @param X buffer pointer
|
||||||
|
; @clobbers r17, r19, r20, r24, r25 (r16, r18, X)
|
||||||
|
|
||||||
|
appHubSendMsgToAllOthers:
|
||||||
|
ld r24, X
|
||||||
|
andi r24, 0x0f ; get sender interface num
|
||||||
|
ldi r19, COM_PORTS ; number of ports
|
||||||
|
ldi yl, LOW(com2w0_iface) ; first interface
|
||||||
|
ldi yh, HIGH(com2w0_iface)
|
||||||
|
appHubSendMsgToAllOthers_loop:
|
||||||
|
ldd r25, Y+NET_IFACE_OFFS_IFACENUM
|
||||||
|
cp r24, r25 ; same interface?
|
||||||
|
breq appHubSendMsgToAllOthers_next
|
||||||
|
; current iface is not source, send and inc ref counter
|
||||||
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
|
brcs appHubSendMsgToAllOthers_added
|
||||||
|
; inc error counter
|
||||||
|
push r24
|
||||||
|
mov r17, r16 ; save r16
|
||||||
|
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||||
|
bigcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||||
|
mov r16, r17 ; restore r16
|
||||||
|
pop r24
|
||||||
|
rjmp appHubSendMsgToAllOthers_next
|
||||||
|
appHubSendMsgToAllOthers_added:
|
||||||
|
mov r17, r16 ; save r16
|
||||||
|
bigcall NET_Buffer_IncRef ; (r16)
|
||||||
|
mov r16, r17 ; restore r16
|
||||||
|
appHubSendMsgToAllOthers_next:
|
||||||
|
ldi r20, COM2W_IFACE_SIZE
|
||||||
|
add yl, r20
|
||||||
|
adc yh, r20
|
||||||
|
sub yh, r20
|
||||||
|
dec r19
|
||||||
|
brne appHubSendMsgToAllOthers_loop
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleMsgLocally
|
||||||
|
;
|
||||||
|
; @param X pointer to received buffer (points to header byte)
|
||||||
|
; @param Y pointer to IFACE data from which msg was received
|
||||||
|
; @clobbers all, !X
|
||||||
|
|
||||||
|
appHubHandleMsgLocally:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appHubHandleMsgLocally_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp appHubHandleMsgLocally_ret
|
||||||
|
appHubHandleMsgLocally_savedX:
|
||||||
|
; get message type
|
||||||
|
adiw xh:xl, NETMSG_OFFS_CMD+1 ; account for header byte
|
||||||
|
ld r16, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_CMD+1
|
||||||
|
cpi r16, NETMSG_CMD_PING
|
||||||
|
breq appHubHandleMsgLocally_handlePingMsg
|
||||||
|
cpi r16, NETMSG_CMD_REBOOT_REQUEST
|
||||||
|
breq appHubHandleMsgLocally_handleRebootMsg
|
||||||
|
cpi r16, NETMSG_CMD_VALUE_SET
|
||||||
|
breq appHubHandleMsgLocally_handleSetValue
|
||||||
|
rjmp appHubHandleMsgLocally_ret
|
||||||
|
appHubHandleMsgLocally_handlePingMsg:
|
||||||
|
rjmp appHubHandlePingMsg
|
||||||
|
appHubHandleMsgLocally_handleRebootMsg:
|
||||||
|
rjmp appHubHandleRebootMsg
|
||||||
|
appHubHandleMsgLocally_handleSetValue:
|
||||||
|
rjmp appHubHandleSetValueMsg
|
||||||
|
appHubHandleMsgLocally_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandlePingMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @clobbers any, !X, !Y
|
||||||
|
|
||||||
|
appHubHandlePingMsg:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_DESTADDR+1
|
||||||
|
ld r17, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_DESTADDR+1
|
||||||
|
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
|
cp r16, r17
|
||||||
|
breq appHubHandlePingMsg_forMe
|
||||||
|
cpi r17, 0xff
|
||||||
|
breq appHubHandlePingMsg_forMe
|
||||||
|
clc
|
||||||
|
rjmp appHubHandlePingMsg_end
|
||||||
|
appHubHandlePingMsg_forMe:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_SRCADDR+1
|
||||||
|
ld r17, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_SRCADDR+1
|
||||||
|
push r17
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
pop r17
|
||||||
|
brcc appHubHandlePingMsg_end ; jmp on error
|
||||||
|
push r16 ; buffer num
|
||||||
|
mov r16, r17 ; DEST addr
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16 ; buffer num
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
appHubHandlePingMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleRebootMsg
|
||||||
|
;
|
||||||
|
; Doesn't return if reboot msg is valid.
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
|
||||||
|
appHubHandleRebootMsg:
|
||||||
|
rcall NETMSG_RebootRequestRead
|
||||||
|
brcc appHubHandleRebootMsg_end
|
||||||
|
; reboot
|
||||||
|
cli
|
||||||
|
bigjmp BOOTLOADER_ADDR
|
||||||
|
appHubHandleRebootMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleSetValueMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @param Y pointer to IFACE data from which msg was received
|
||||||
|
; @clobbers all, !Y
|
||||||
|
|
||||||
|
appHubHandleSetValueMsg:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_DESTADDR+1
|
||||||
|
ld r17, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_DESTADDR+1
|
||||||
|
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
|
cp r16, r17
|
||||||
|
breq appHubHandleSetValueMsg_forMe
|
||||||
|
cpi r17, 0xff
|
||||||
|
breq appHubHandleSetValueMsg_forMe
|
||||||
|
rjmp appHubHandleSetValueMsg_ret
|
||||||
|
appHubHandleSetValueMsg_forMe:
|
||||||
|
rcall NETMSG_ValueRead ; (none)
|
||||||
|
cpi r17, VALUE_ID_HUB_SETRANGE1
|
||||||
|
brcs appHubHandleSetValueMsg_ret
|
||||||
|
cpi r17, VALUE_ID_HUB_SETRANGE8+1
|
||||||
|
brcc appHubHandleSetValueMsg_ret
|
||||||
|
appHubHandleSetValueMsg_setRange:
|
||||||
|
push yl
|
||||||
|
push yh
|
||||||
|
subi r17, (VALUE_ID_HUB_SETRANGE1-1)
|
||||||
|
push r18
|
||||||
|
push r19
|
||||||
|
; send ACK back the same interface the request came from
|
||||||
|
push r17 ; interface number
|
||||||
|
ldi r23, NETMSG_CMD_VALUE_SET_ACK
|
||||||
|
rcall appHubSendValueResponse ; r22 (r16, r17, r18, r19, r20, r21, r23, r24, r25, X)
|
||||||
|
pop r16 ; pop interface number to r16 (from r17)
|
||||||
|
rcall appHubGetDeviceByIfaceNum ; Y=interface to modify (r17, r19, r20)
|
||||||
|
pop r19
|
||||||
|
pop r18
|
||||||
|
; modify interface
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r18
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_END, r19
|
||||||
|
; TODO: store new config
|
||||||
|
|
||||||
|
; let subnodes of modified interface re-eunumerate
|
||||||
|
ldi r18, NETMSG_CMD_REENUM
|
||||||
|
rcall appHubSendRangeMsg ; (R16, R17, R18, R19, R20, R21, X)
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
|
|
||||||
|
appHubHandleSetValueMsg_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleRoutingMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to received buffer (points to header byte)
|
||||||
|
; @param Y pointer to IFACE data from which msg was received
|
||||||
|
; @clobbers all, !X
|
||||||
|
|
||||||
|
appHubHandleRoutingMsg:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appHubHandleRoutingMsg_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp appHubHandleRoutingMsg_ret
|
||||||
|
appHubHandleRoutingMsg_savedX:
|
||||||
|
; get message type
|
||||||
|
adiw xh:xl, NETMSG_OFFS_CMD+1 ; account for header byte
|
||||||
|
ld r16, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_CMD+1
|
||||||
|
cpi r16, NETMSG_CMD_NEED_ADDRESS
|
||||||
|
breq appHubHandleRoutingMsg_handleNeedAddress
|
||||||
|
cpi r16, NETMSG_CMD_CLAIM_ADDRESS
|
||||||
|
breq appHubHandleRoutingMsg_handleClaimAddress
|
||||||
|
clc
|
||||||
|
rjmp appHubHandleRoutingMsg_ret
|
||||||
|
appHubHandleRoutingMsg_handleNeedAddress:
|
||||||
|
rcall appHubHandleNeedAddressMsg
|
||||||
|
rjmp appHubHandleRoutingMsg_secRet
|
||||||
|
appHubHandleRoutingMsg_handleClaimAddress:
|
||||||
|
rcall appHubHandleClaimAddressMsg
|
||||||
|
appHubHandleRoutingMsg_secRet:
|
||||||
|
sec
|
||||||
|
appHubHandleRoutingMsg_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleNeedAddressMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @param Y pointer to IFACE data from which msg was received
|
||||||
|
; @clobbers all, !Y
|
||||||
|
|
||||||
|
appHubHandleNeedAddressMsg:
|
||||||
|
ldi r18, NETMSG_CMD_ADDRESS_RANGE
|
||||||
|
rcall appHubSendRangeMsg ; (R16, R17, R18, R19, R20, R21, X)
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleClaimAddressMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @param Y pointer to IFACE data from which msg was received
|
||||||
|
; @clobbers all, !Y
|
||||||
|
|
||||||
|
appHubHandleClaimAddressMsg:
|
||||||
|
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
||||||
|
rcall appHubIsR19InRange
|
||||||
|
brcs appHubHandleClaimAddressMsg_end
|
||||||
|
; is not in subnet range, deny
|
||||||
|
rcall appHubSendDenyAddrR19 ; (R16, R17, R18, R19, R20, R21, X)
|
||||||
|
appHubHandleClaimAddressMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubIsR19InRange
|
||||||
|
;
|
||||||
|
; @param R19 address to check against range
|
||||||
|
; @param Y pointer to IFACE data
|
||||||
|
; @clobbers R16
|
||||||
|
|
||||||
|
appHubIsR19InRange:
|
||||||
|
ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN
|
||||||
|
cp r19, r16
|
||||||
|
brcs appHubIsR19InRangeClcRet
|
||||||
|
ldd r16, Y+NET_IFACE_OFFS_RANGE_END
|
||||||
|
cp r16, r19
|
||||||
|
brcs appHubIsR19InRangeClcRet
|
||||||
|
sec
|
||||||
|
rjmp appHubIsR19InRange_end
|
||||||
|
appHubIsR19InRangeClcRet:
|
||||||
|
clc
|
||||||
|
appHubIsR19InRange_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubCheckRecvdMsg
|
||||||
|
;
|
||||||
|
; Read messages from any interface and forward to the other ones.
|
||||||
|
;
|
||||||
|
; @return CFLAG set if something done, cleared otherwise
|
||||||
|
|
||||||
|
appHubCheckRecvdMsg:
|
||||||
|
rcall NET_PeekNextIncomingMsgNum ; check read queue (R16=bufNum)
|
||||||
|
brcc appHubCheckRecvdMsg_end ; no msg, jmp
|
||||||
|
rcall NET_Buffer_Locate ; (R17)
|
||||||
|
rcall appHubHandleRecvdMsg ; (all, !X)
|
||||||
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
||||||
|
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||||
|
sec ; we had a message, so something was done
|
||||||
|
appHubCheckRecvdMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubHandleRecvdMsg
|
||||||
|
;
|
||||||
|
; @param R16 buffer number
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @clobbers all, !X
|
||||||
|
|
||||||
|
appHubHandleRecvdMsg:
|
||||||
|
mov r18, r16
|
||||||
|
ld r16, X
|
||||||
|
andi r16, 0x0f
|
||||||
|
rcall appHubGetDeviceByIfaceNum ; Y=source iface (r17, r19, r20)
|
||||||
|
brcc appHubHandleRecvdMsg_ret
|
||||||
|
; filter out routing msgs
|
||||||
|
push yl
|
||||||
|
push yh
|
||||||
|
push r18
|
||||||
|
rcall appHubHandleRoutingMsg ; (all, !X)
|
||||||
|
pop r18
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
|
brcs appHubHandleRecvdMsg_ret
|
||||||
|
; check for PING, SETVALUE etc
|
||||||
|
push r18
|
||||||
|
push yl
|
||||||
|
push yh
|
||||||
|
rcall appHubHandleMsgLocally ; (all, !X)
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
|
; let other apps and modules handle message
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
bigcall mainHandleMessages
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
pop r18
|
||||||
|
; forward message to all other interfaces
|
||||||
|
mov r16, r18 ; buffer number
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appHubSendMsgToAllOthers ; (r17, r19, r20, r24, r25 (r16, r18, X)
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
appHubHandleRecvdMsg_ret:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubWriteConfToEeprom
|
||||||
|
;
|
||||||
|
; @clobbers R16, X (R17)
|
||||||
|
|
||||||
|
appHubWriteConfToEeprom:
|
||||||
|
; write range begin
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
lds r16, appHubRangeBegin
|
||||||
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
||||||
|
brcc appHubWriteConfToEeprom_end
|
||||||
|
|
||||||
|
; write range end
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
lds r16, appHubRangeEnd
|
||||||
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
||||||
|
appHubWriteConfToEeprom_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appHubReadConfFromEeprom
|
||||||
|
;
|
||||||
|
; @clobbers R16, X (R17)
|
||||||
|
|
||||||
|
appHubReadConfFromEeprom:
|
||||||
|
; read range begin
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
rcall Eeprom_ReadByte
|
||||||
|
brcc appHubReadConfFromEeprom_end
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appHubReadConfFromEeprom_okay ; not set, jmp
|
||||||
|
cpi r16, 2 ; range should at least start at 2 to assign 1 to router
|
||||||
|
brcs appHubReadConfFromEeprom_okay
|
||||||
|
sts appHubRangeBegin, r16
|
||||||
|
dec r16
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use addr rangeBegin-1 for router itself
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses
|
||||||
|
|
||||||
|
; read range end
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
rcall Eeprom_ReadByte
|
||||||
|
brcc appHubReadConfFromEeprom_end
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appHubReadConfFromEeprom_okay
|
||||||
|
sts appHubRangeEnd, r16
|
||||||
|
appHubReadConfFromEeprom_okay:
|
||||||
|
sec
|
||||||
|
appHubReadConfFromEeprom_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -100,12 +100,30 @@ AppNetwork_Every100ms_jump:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppNetwork_EveryDay @global
|
||||||
|
;
|
||||||
|
; @clobbers R16, R17, X
|
||||||
|
|
||||||
|
AppNetwork_EveryDay:
|
||||||
|
bigjmp NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; @routine AppNetwork_HandleMsg @global
|
; @routine AppNetwork_HandleMsg @global
|
||||||
;
|
;
|
||||||
; @param X pointer to received message
|
; @param X pointer to received message
|
||||||
|
|
||||||
AppNetwork_HandleMsg:
|
AppNetwork_HandleMsg:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall AppNetwork_HandleMsg_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp AppNetwork_HandleMsg_end
|
||||||
|
AppNetwork_HandleMsg_savedX:
|
||||||
adiw xh:xl, NETMSG_OFFS_CMD
|
adiw xh:xl, NETMSG_OFFS_CMD
|
||||||
ld r16, X
|
ld r16, X
|
||||||
sbiw xh:xl, NETMSG_OFFS_CMD
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
||||||
@@ -113,18 +131,25 @@ AppNetwork_HandleMsg:
|
|||||||
breq AppNetwork_HandleMsg_handleRebootMsg
|
breq AppNetwork_HandleMsg_handleRebootMsg
|
||||||
cpi r16, NETMSG_CMD_PING
|
cpi r16, NETMSG_CMD_PING
|
||||||
breq AppNetwork_HandleMsg_handlePingMsg
|
breq AppNetwork_HandleMsg_handlePingMsg
|
||||||
|
cpi r16, NETMSG_CMD_REENUM
|
||||||
|
breq AppNetwork_HandleMsg_handleReenumMsg
|
||||||
cpi r16, NETMSG_CMD_NEED_ADDRESS
|
cpi r16, NETMSG_CMD_NEED_ADDRESS
|
||||||
brcs AppNetwork_HandleMsg_clcRet ; lower than "HAVE_NEED"
|
brcs AppNetwork_HandleMsg_clcRet ; lower than "HAVE_NEED"
|
||||||
cpi r16, NETMSG_CMD_ADDRESS_RANGE
|
cpi r16, NETMSG_CMD_ADDRESS_RANGE
|
||||||
breq AppNetwork_HandleMsg_handleRangeMsg
|
breq AppNetwork_HandleMsg_handleRangeMsg
|
||||||
brcc AppNetwork_HandleMsg_clcRet ; higher or equal to "ADDR_RANGE"
|
brcc AppNetwork_HandleMsg_clcRet ; higher or equal to "ADDR_RANGE"
|
||||||
rjmp AppNetwork_HandleMsg_handleAddrMsg
|
rjmp AppNetwork_HandleMsg_handleAddrMsg
|
||||||
|
AppNetwork_HandleMsg_handleReenumMsg:
|
||||||
|
rjmp appNetworkHandleReeunumRequest
|
||||||
AppNetwork_HandleMsg_handleRangeMsg:
|
AppNetwork_HandleMsg_handleRangeMsg:
|
||||||
; TODO
|
bigcall NETMSG_Range_Read
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_END, r21
|
||||||
|
std Y+NET_IFACE_OFFS_ADDRESS, r20
|
||||||
rjmp AppNetwork_HandleMsg_clcRet
|
rjmp AppNetwork_HandleMsg_clcRet
|
||||||
|
|
||||||
AppNetwork_HandleMsg_handleAddrMsg:
|
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
|
mov r16, r18
|
||||||
subi r16, NETMSG_CMD_NEED_ADDRESS
|
subi r16, NETMSG_CMD_NEED_ADDRESS
|
||||||
ldi zl, LOW(appNetworkMsgTable)
|
ldi zl, LOW(appNetworkMsgTable)
|
||||||
@@ -134,21 +159,13 @@ AppNetwork_HandleMsg_handleAddrMsg:
|
|||||||
sub zh, r16
|
sub zh, r16
|
||||||
ijmp
|
ijmp
|
||||||
AppNetwork_HandleMsg_handleRebootMsg:
|
AppNetwork_HandleMsg_handleRebootMsg:
|
||||||
push xl
|
rcall appNetworkHandleRebootRequest
|
||||||
push xh
|
|
||||||
rcall appNetworkHandleRebootRequest
|
|
||||||
pop xh
|
|
||||||
pop xl
|
|
||||||
ret
|
ret
|
||||||
AppNetwork_HandleMsg_handlePingMsg:
|
AppNetwork_HandleMsg_handlePingMsg:
|
||||||
push xl
|
rjmp appNetworkHandlePingRequest
|
||||||
push xh
|
|
||||||
rcall appNetworkHandlePingRequest
|
|
||||||
pop xh
|
|
||||||
pop xl
|
|
||||||
ret
|
|
||||||
AppNetwork_HandleMsg_clcRet:
|
AppNetwork_HandleMsg_clcRet:
|
||||||
clc
|
clc
|
||||||
|
AppNetwork_HandleMsg_end:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
@@ -161,7 +178,7 @@ AppNetwork_HandleMsg_clcRet:
|
|||||||
|
|
||||||
appNetworkHandleRebootRequest:
|
appNetworkHandleRebootRequest:
|
||||||
rcall NETMSG_RebootRequestRead
|
rcall NETMSG_RebootRequestRead
|
||||||
brcc appNetworkHandleRebootRequest_end
|
brcc appNetworkHandleRebootRequest_end ; uid doesn't match
|
||||||
; reboot
|
; reboot
|
||||||
cli
|
cli
|
||||||
bigjmp BOOTLOADER_ADDR
|
bigjmp BOOTLOADER_ADDR
|
||||||
@@ -172,26 +189,56 @@ appNetworkHandleRebootRequest_end:
|
|||||||
|
|
||||||
|
|
||||||
appNetworkHandlePingRequest:
|
appNetworkHandlePingRequest:
|
||||||
|
ld r17, X
|
||||||
|
lds r16, (netInterfaceData+NET_IFACE_OFFS_ADDRESS)
|
||||||
|
cp r16, r17
|
||||||
|
breq appNetworkHandlePingRequest_forMe
|
||||||
|
cpi r17, 0xff
|
||||||
|
breq appNetworkHandlePingRequest_forMe
|
||||||
|
clc
|
||||||
|
rjmp appNetworkHandlePingRequest_end
|
||||||
|
appNetworkHandlePingRequest_forMe:
|
||||||
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||||
ld r17, X
|
ld r17, X
|
||||||
push r17
|
push r17
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
pop r17
|
pop r17
|
||||||
brcc appNetworkHandlePingRequest_end ; jmp on error
|
brcc appNetworkHandlePingRequest_end ; jmp on error
|
||||||
push r16 ; buffer num
|
push r16 ; buffer num
|
||||||
mov r16, r17 ; DEST addr
|
mov r16, r17 ; DEST addr
|
||||||
adiw xh:xl, 1
|
adiw xh:xl, 1
|
||||||
ldi yl, LOW(netInterfaceData)
|
ldi yl, LOW(netInterfaceData)
|
||||||
ldi yh, HIGH(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
|
sbiw xh:xl, 1
|
||||||
pop r16 ; buffer num
|
pop r16 ; buffer num
|
||||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
appNetworkHandlePingRequest_end:
|
appNetworkHandlePingRequest_end:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
appNetworkHandleReeunumRequest:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall Utils_ReadUid ; r21:r20:r19:r18=uid (r16, X)
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rcall NETMSG_Range_Read ; r20=range begin, r21=range end (none)
|
||||||
|
ldi r16, APP_NETWORK_STATE_INITIALWAIT
|
||||||
|
std Y+NET_IFACE_OFFS_STATUS, r16
|
||||||
|
cpi r18, 20
|
||||||
|
brcc appNetworkHandleReeunumRequest_setWait
|
||||||
|
subi r18, -20 ; minimum 2s
|
||||||
|
appNetworkHandleReeunumRequest_setWait:
|
||||||
|
std Y+NET_IFACE_OFFS_STATETIMER, r18 ; use lowest byte of uid as wat time
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20
|
||||||
|
std Y+NET_IFACE_OFFS_RANGE_END, r21
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
appNetworkTimerTable:
|
appNetworkTimerTable:
|
||||||
rjmp appNetworkHandleStateInitialWait
|
rjmp appNetworkHandleStateInitialWait
|
||||||
rjmp appNetworkHandleStateNeedAddress
|
rjmp appNetworkHandleStateNeedAddress
|
||||||
@@ -238,20 +285,11 @@ appNetworkHandleStateHaveAddress2:
|
|||||||
std Y+NET_IFACE_OFFS_STATUS, r16
|
std Y+NET_IFACE_OFFS_STATUS, r16
|
||||||
ldi r16, APP_NETWORK_TIMER_100MS
|
ldi r16, APP_NETWORK_TIMER_100MS
|
||||||
std Y+NET_IFACE_OFFS_STATETIMER, r16
|
std Y+NET_IFACE_OFFS_STATETIMER, r16
|
||||||
ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN ; set interface address
|
|
||||||
ldd r17, Y+NET_IFACE_OFFS_ADDRESS
|
|
||||||
cp r16, r17
|
|
||||||
breq appNetworkHandleStateHaveAddress2_end
|
|
||||||
; store new address in IFACE and in EEPROM
|
; store new address in IFACE and in EEPROM
|
||||||
std Y+NET_IFACE_OFFS_ADDRESS, r16
|
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
push r15
|
ldi xl, LOW(EEPROM_OFFS_COMADDR)
|
||||||
in r15, SREG
|
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
|
||||||
cli
|
bigcall Eeprom_WriteByteIfChanged ; write address to EEPROM (R17)
|
||||||
ldi xl, LOW(EEPROM_OFFS_COMADDR)
|
|
||||||
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
|
|
||||||
bigcall Utils_WriteEepromIncr ; write address to EEPROM
|
|
||||||
out SREG, r15
|
|
||||||
pop r15
|
|
||||||
appNetworkHandleStateHaveAddress2_end:
|
appNetworkHandleStateHaveAddress2_end:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -269,7 +307,7 @@ appNetworkHandleStateUp:
|
|||||||
; @clobbers R16, R19 (R17, R18, R20, R21, X)
|
; @clobbers R16, R19 (R17, R18, R20, R21, X)
|
||||||
|
|
||||||
appNetworkSendMsgNextState:
|
appNetworkSendMsgNextState:
|
||||||
ldd r19, Y+NET_IFACE_OFFS_RANGE_BEGIN
|
ldd r19, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
rcall appNetworkSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X)
|
rcall appNetworkSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X)
|
||||||
brcc appNetworkSendMsgNextState_retry
|
brcc appNetworkSendMsgNextState_retry
|
||||||
ldd r16, Y+NET_IFACE_OFFS_STATUS
|
ldd r16, Y+NET_IFACE_OFFS_STATUS
|
||||||
@@ -334,9 +372,9 @@ appNetworkHandleMsgClaimAddr:
|
|||||||
cp r19, r16
|
cp r19, r16
|
||||||
brne appNetworkHandleMsgClaimAddr_end ; not our address
|
brne appNetworkHandleMsgClaimAddr_end ; not our address
|
||||||
ldd r16, Y+NET_IFACE_OFFS_STATUS
|
ldd r16, Y+NET_IFACE_OFFS_STATUS
|
||||||
cpi r16, APP_NETWORK_STATE_UP ; up?
|
cpi r16, APP_NETWORK_STATE_CLAIMADDRESS1
|
||||||
brne appNetworkHandleMsgClaimAddr_end ; nope, ignore
|
brcs appNetworkHandleMsgClaimAddr_end ; nope, ignore
|
||||||
; network is up, someone claimed our address, deny it
|
; network is somewhat up, someone claimed our address, deny it
|
||||||
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny our addr
|
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny our addr
|
||||||
ldd r19, Y+NET_IFACE_OFFS_ADDRESS
|
ldd r19, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
rjmp appNetworkSendAddrMsg
|
rjmp appNetworkSendAddrMsg
|
||||||
@@ -358,12 +396,12 @@ appNetworkHandleMsgDenyAddr:
|
|||||||
cpi r16, APP_NETWORK_STATE_UP
|
cpi r16, APP_NETWORK_STATE_UP
|
||||||
breq appNetworkHandleMsgDenyAddr_end ; ignore (our network stack is up)
|
breq appNetworkHandleMsgDenyAddr_end ; ignore (our network stack is up)
|
||||||
; still setting up address, check whether the last one is denied now
|
; still setting up address, check whether the last one is denied now
|
||||||
ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN
|
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
|
||||||
cp r19, r16 ; our claimed address?
|
cp r19, r16 ; our claimed address?
|
||||||
brne appNetworkHandleMsgDenyAddr_end ; nope, jump
|
brne appNetworkHandleMsgDenyAddr_end ; nope, jump
|
||||||
; try next address (if any left)
|
; try next address (if any left)
|
||||||
ldd r17, Y+NET_IFACE_OFFS_RANGE_END
|
ldd r17, Y+NET_IFACE_OFFS_RANGE_END
|
||||||
inc r16 ; RANGE_BEGIN+1
|
inc r16 ; next address
|
||||||
cp r17, r16 ; smaller than or equal to RANGE_END?
|
cp r17, r16 ; smaller than or equal to RANGE_END?
|
||||||
brcc appNetworkHandleMsgDenyAddr_claimNext
|
brcc appNetworkHandleMsgDenyAddr_claimNext
|
||||||
; out of addresses, start completely new after some waiting time
|
; out of addresses, start completely new after some waiting time
|
||||||
@@ -373,7 +411,7 @@ appNetworkHandleMsgDenyAddr:
|
|||||||
rjmp appNetworkHandleMsgDenyAddr_end
|
rjmp appNetworkHandleMsgDenyAddr_end
|
||||||
appNetworkHandleMsgDenyAddr_claimNext:
|
appNetworkHandleMsgDenyAddr_claimNext:
|
||||||
; send CLAIM_ADDR for next address (new state: APP_NETWORK_STATE_NEEDADDRESS+1)
|
; send CLAIM_ADDR for next address (new state: APP_NETWORK_STATE_NEEDADDRESS+1)
|
||||||
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16
|
std Y+NET_IFACE_OFFS_ADDRESS, r16
|
||||||
ldi r16, APP_NETWORK_STATE_NEEDADDRESS
|
ldi r16, APP_NETWORK_STATE_NEEDADDRESS
|
||||||
std Y+NET_IFACE_OFFS_STATUS, r16
|
std Y+NET_IFACE_OFFS_STATUS, r16
|
||||||
ldi r18, NETMSG_CMD_CLAIM_ADDRESS
|
ldi r18, NETMSG_CMD_CLAIM_ADDRESS
|
||||||
@@ -393,16 +431,16 @@ appNetworkHandleMsgDenyAddr_end:
|
|||||||
; @clobbers R16 (R17, R18, R19, R20, R21, X)
|
; @clobbers R16 (R17, R18, R19, R20, R21, X)
|
||||||
|
|
||||||
appNetworkSendAddrMsg:
|
appNetworkSendAddrMsg:
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
brcc appNetworkSendAddrMsg_end
|
brcc appNetworkSendAddrMsg_end
|
||||||
adiw xh:xl, 1
|
adiw xh:xl, 1
|
||||||
push r16
|
push r16
|
||||||
rcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
pop r16
|
pop r16
|
||||||
sbiw xh:xl, 1
|
sbiw xh:xl, 1
|
||||||
rcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
brcs appNetworkSendAddrMsg_end
|
brcs appNetworkSendAddrMsg_end
|
||||||
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||||
clc
|
clc
|
||||||
appNetworkSendAddrMsg_end:
|
appNetworkSendAddrMsg_end:
|
||||||
ret
|
ret
|
||||||
@@ -424,6 +462,7 @@ appNetworkResetState:
|
|||||||
std Y+NET_IFACE_OFFS_STATETIMER, r16
|
std Y+NET_IFACE_OFFS_STATETIMER, r16
|
||||||
ldi r16, APP_NETWORK_ADDRESS_RANGE_BEGIN
|
ldi r16, APP_NETWORK_ADDRESS_RANGE_BEGIN
|
||||||
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16
|
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16
|
||||||
|
std Y+NET_IFACE_OFFS_ADDRESS, r16
|
||||||
rcall appNetworkGetAddressFromEeprom ; R16=addr (R15, X)
|
rcall appNetworkGetAddressFromEeprom ; R16=addr (R15, X)
|
||||||
tst r16
|
tst r16
|
||||||
breq appNetworkResetState_setRangeEnd
|
breq appNetworkResetState_setRangeEnd
|
||||||
|
|||||||
@@ -18,14 +18,20 @@
|
|||||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||||
|
|
||||||
AppNetwork_SendTxdStats:
|
AppNetwork_SendTxdStats:
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
brcc AppNetwork_SendTxdStats_end
|
brcc AppNetwork_SendTxdStats_end
|
||||||
push r16
|
push r16
|
||||||
adiw xh:xl, 1
|
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
|
sbiw xh:xl, 1
|
||||||
pop r16
|
pop r16
|
||||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
push yl
|
||||||
|
push yh
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
AppNetwork_SendTxdStats_end:
|
AppNetwork_SendTxdStats_end:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -35,18 +41,24 @@ AppNetwork_SendTxdStats_end:
|
|||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; @routine AppNetwork_SendRxdStats
|
; @routine AppNetwork_SendRxdStats
|
||||||
|
|
||||||
; @param Y network interface to work with
|
; @param Y network interface whose stats to send
|
||||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||||
|
|
||||||
AppNetwork_SendRxdStats:
|
AppNetwork_SendRxdStats:
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
brcc AppNetwork_SendRxdStats_end
|
brcc AppNetwork_SendRxdStats_end
|
||||||
push r16
|
push r16
|
||||||
adiw xh:xl, 1
|
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
|
sbiw xh:xl, 1
|
||||||
pop r16
|
pop r16
|
||||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
push yl
|
||||||
|
push yh
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
AppNetwork_SendRxdStats_end:
|
AppNetwork_SendRxdStats_end:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -54,20 +66,25 @@ AppNetwork_SendRxdStats_end:
|
|||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; @routine AppNetwork_SendRxdStats
|
; @routine AppNetwork_SendMemStats
|
||||||
|
|
||||||
; @param Y network interface to work with
|
|
||||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||||
|
|
||||||
AppNetwork_SendMemStats:
|
AppNetwork_SendMemStats:
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
brcc AppNetwork_SendMemStats_end
|
brcc AppNetwork_SendMemStats_end
|
||||||
push r16
|
push r16
|
||||||
adiw xh:xl, 1
|
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
|
sbiw xh:xl, 1
|
||||||
pop r16
|
pop r16
|
||||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
push yl
|
||||||
|
push yh
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
AppNetwork_SendMemStats_end:
|
AppNetwork_SendMemStats_end:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -81,14 +98,14 @@ AppNetwork_SendMemStats_end:
|
|||||||
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
|
||||||
|
|
||||||
AppNetwork_SendDevice:
|
AppNetwork_SendDevice:
|
||||||
rcall NET_Buffer_Alloc ; (R16, R17, X)
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
brcc AppNetwork_SendDevice_end
|
brcc AppNetwork_SendDevice_end
|
||||||
push r16
|
push r16
|
||||||
adiw xh:xl, 1
|
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
|
sbiw xh:xl, 1
|
||||||
pop r16
|
pop r16
|
||||||
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
AppNetwork_SendDevice_end:
|
AppNetwork_SendDevice_end:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
; ***************************************************************************
|
; ***************************************************************************
|
||||||
; defines
|
; 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
|
#ifdef MODULES_SI7021
|
||||||
cpi r16, 1
|
cpi r16, 1
|
||||||
breq AppReportSensors_OnEverySecond_measureValue1
|
breq AppReportSensors_OnEverySecond_measureValue1
|
||||||
cpi r16, 19
|
cpi r16, 11
|
||||||
breq AppReportSensors_OnEverySecond_measureValue2
|
breq AppReportSensors_OnEverySecond_measureValue2
|
||||||
cpi r16, 39
|
cpi r16, 16
|
||||||
breq AppReportSensors_OnEverySecond_sendValue1
|
breq AppReportSensors_OnEverySecond_sendValue1
|
||||||
cpi r16, 49
|
cpi r16, 21
|
||||||
breq AppReportSensors_OnEverySecond_sendValue2
|
breq AppReportSensors_OnEverySecond_sendValue2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_SGP40
|
#ifdef MODULES_SGP40
|
||||||
cpi r16, 27
|
cpi r16, 32
|
||||||
breq AppReportSensors_OnEverySecond_measureValue4
|
breq AppReportSensors_OnEverySecond_measureValue4
|
||||||
cpi r16, 55
|
cpi r16, 42
|
||||||
breq AppReportSensors_OnEverySecond_sendValue4
|
breq AppReportSensors_OnEverySecond_sendValue4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_SGP30
|
#ifdef MODULES_SGP30
|
||||||
cpi r16, 29
|
cpi r16, 53
|
||||||
breq AppReportSensors_OnEverySecond_measureValue5
|
|
||||||
cpi r16, 57
|
|
||||||
breq AppReportSensors_OnEverySecond_sendValue5
|
breq AppReportSensors_OnEverySecond_sendValue5
|
||||||
cpi r16, 59
|
cpi r16, 63
|
||||||
breq AppReportSensors_OnEverySecond_sendValue6
|
breq AppReportSensors_OnEverySecond_sendValue6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_DS18B20
|
#ifdef MODULES_DS18B20
|
||||||
cpi r16, 9
|
cpi r16, 84
|
||||||
breq AppReportSensors_OnEverySecond_sendValue3
|
breq AppReportSensors_OnEverySecond_sendValue3
|
||||||
#endif
|
#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
|
ret
|
||||||
|
|
||||||
#ifdef MODULES_SI7021
|
#ifdef MODULES_SI7021
|
||||||
@@ -133,13 +143,23 @@ AppReportSensors_OnEverySecond_sendValue3:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_SGP30
|
#ifdef MODULES_SGP30
|
||||||
AppReportSensors_OnEverySecond_measureValue5:
|
AppReportSensors_OnEverySecond_sendValue5:
|
||||||
rjmp SGP30_Measure
|
rjmp SGP30_SendTVOC
|
||||||
AppReportSensors_OnEverySecond_sendValue5:
|
ret
|
||||||
rjmp SGP30_SendTVOC
|
AppReportSensors_OnEverySecond_sendValue6:
|
||||||
ret
|
rjmp SGP30_SendCO2
|
||||||
AppReportSensors_OnEverySecond_sendValue6:
|
#endif
|
||||||
rjmp SGP30_SendCO2
|
|
||||||
|
#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
|
#endif
|
||||||
|
|
||||||
; @end
|
; @end
|
||||||
|
|||||||
15
avr/apps/router/0BUILD
Normal file
15
avr/apps/router/0BUILD
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml?>
|
||||||
|
|
||||||
|
<gwbuild>
|
||||||
|
|
||||||
|
<subdirs>
|
||||||
|
</subdirs>
|
||||||
|
|
||||||
|
<extradist>
|
||||||
|
main.asm
|
||||||
|
</extradist>
|
||||||
|
|
||||||
|
|
||||||
|
</gwbuild>
|
||||||
|
|
||||||
|
|
||||||
579
avr/apps/router/main.asm
Normal file
579
avr/apps/router/main.asm
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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. *
|
||||||
|
; ***************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; defines
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; network interfaces
|
||||||
|
|
||||||
|
.equ NETDEV0_IFACENUM = 1
|
||||||
|
.equ NETDEV1_IFACENUM = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; data
|
||||||
|
|
||||||
|
.dseg
|
||||||
|
|
||||||
|
appRouterDataBegin:
|
||||||
|
appRouterRangeBegin: .byte 1
|
||||||
|
appRouterRangeEnd: .byte 1
|
||||||
|
appRouterDataEnd:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ***************************************************************************
|
||||||
|
; code
|
||||||
|
|
||||||
|
.cseg
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppRouter_Init @global
|
||||||
|
|
||||||
|
AppRouter_Init:
|
||||||
|
ldi xh, HIGH(appRouterDataBegin)
|
||||||
|
ldi xl, LOW(appRouterDataBegin)
|
||||||
|
clr r16
|
||||||
|
ldi r17, (appRouterDataEnd-appRouterDataBegin)
|
||||||
|
rcall Utils_FillSram
|
||||||
|
|
||||||
|
#ifndef APP_ROUTER_NO_ADDR_MGR
|
||||||
|
ldi r16, 0xe0 ; default range from 0xe0-0xef (will be changed later)
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use first address for router itself
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses
|
||||||
|
inc r16
|
||||||
|
sts appRouterRangeBegin, r16 ; range from router+1
|
||||||
|
ldi r16, 0xef
|
||||||
|
sts appRouterRangeEnd, r16
|
||||||
|
|
||||||
|
rcall appRouterReadConfFromEeprom ; try to read config from EEPROM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
; set interface number for NETDEV0
|
||||||
|
ldi r16, NETDEV0_IFACENUM
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_IFACENUM, r16
|
||||||
|
; set interface number for NETDEV1
|
||||||
|
ldi r16, NETDEV1_IFACENUM
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_IFACENUM, r16
|
||||||
|
|
||||||
|
#ifndef APP_ROUTER_NO_ADDR_MGR
|
||||||
|
ldi r18, NETMSG_CMD_ADDRESS_RANGE
|
||||||
|
rcall appRouterSendRangeMsgToDev1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppRouter_EveryDay @global
|
||||||
|
;
|
||||||
|
; @clobbers R16, R17, X
|
||||||
|
|
||||||
|
AppRouter_EveryDay:
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
bigcall NET_Interface_ResetStats ; (R16, R17, X)
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine AppRouter_Run @global
|
||||||
|
;
|
||||||
|
; Read messages from either interface and forward to the other one.
|
||||||
|
|
||||||
|
AppRouter_Run:
|
||||||
|
rjmp appRouterCheckRecvdMsg
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterHandleMsgAnyDev @global
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @return CFLAG set if msg handled, cleared otherwise
|
||||||
|
; @clobbers any, !X
|
||||||
|
|
||||||
|
appRouterHandleMsgAnyDev:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appRouterHandleMsgAnyDev_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp appRouterHandleMsgAnyDev_end
|
||||||
|
appRouterHandleMsgAnyDev_savedX:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm?
|
||||||
|
ld r16, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
||||||
|
cpi r16, NETMSG_CMD_REBOOT_REQUEST
|
||||||
|
breq appRouterHandleMsgAnyDev_handleRebootMsg
|
||||||
|
cpi r16, NETMSG_CMD_PING
|
||||||
|
breq appRouterHandleMsgAnyDev_handlePingMsg
|
||||||
|
cpi r16, NETMSG_CMD_VALUE_SET
|
||||||
|
breq appRouterHandleMsgAnyDev_handleSetValue
|
||||||
|
rjmp appRouterHandleMsgAnyDev_clcRet
|
||||||
|
appRouterHandleMsgAnyDev_handleRebootMsg:
|
||||||
|
rcall appRouterHandleRebootRequest
|
||||||
|
ret
|
||||||
|
appRouterHandleMsgAnyDev_handlePingMsg:
|
||||||
|
rcall appRouterHandlePingRequest
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
appRouterHandleMsgAnyDev_handleSetValue:
|
||||||
|
rcall NETMSG_ValueRead ; (none)
|
||||||
|
cpi r17, VALUE_ID_ROUTER_SETRANGE
|
||||||
|
breq appRouterHandleMsgAnyDev_handleSetRange
|
||||||
|
rjmp appRouterHandleMsgAnyDev_clcRet
|
||||||
|
appRouterHandleMsgAnyDev_handleSetRange:
|
||||||
|
#ifndef APP_ROUTER_NO_ADDR_MGR
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r18 ; use first address for router itself
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r18 ; use same address for both interfaces to save on addresses
|
||||||
|
inc r18 ; start range after router
|
||||||
|
sts appRouterRangeBegin, r18
|
||||||
|
sts appRouterRangeEnd, r19
|
||||||
|
; send ACK
|
||||||
|
ldi r23, NETMSG_CMD_VALUE_SET_ACK
|
||||||
|
rcall Main_SendValueResponse ; (clobbers all, including Y)
|
||||||
|
; let subnodes re-eunumerate
|
||||||
|
ldi r18, NETMSG_CMD_REENUM
|
||||||
|
rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
rcall appRouterWriteConfToEeprom ; (r16, r17, X)
|
||||||
|
#endif
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
appRouterHandleMsgAnyDev_clcRet:
|
||||||
|
clc
|
||||||
|
appRouterHandleMsgAnyDev_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterHandleDev1Msg @global
|
||||||
|
;
|
||||||
|
; Handle messages from controlled subnet.
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
; @return CFLAG set if msg handled, cleared otherwise
|
||||||
|
; @clobbers any, !X
|
||||||
|
|
||||||
|
appRouterHandleDev1Msg:
|
||||||
|
#ifndef APP_ROUTER_NO_ADDR_MGR
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall appRouterHandleDev1Msg_savedX
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
rjmp appRouterHandleDev1Msg_end
|
||||||
|
appRouterHandleDev1Msg_savedX:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_CMD
|
||||||
|
ld r16, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_CMD
|
||||||
|
cpi r16, NETMSG_CMD_NEED_ADDRESS
|
||||||
|
breq appRouterHandleDev1Msg_handleNeedAddr
|
||||||
|
cpi r16, NETMSG_CMD_CLAIM_ADDRESS
|
||||||
|
breq appRouterHandleDev1Msg_handleClaimAddr
|
||||||
|
; add more here
|
||||||
|
ldi r16, 0
|
||||||
|
rjmp appRouterHandleDev1Msg_clcRet
|
||||||
|
appRouterHandleDev1Msg_handleNeedAddr:
|
||||||
|
ldi r18, NETMSG_CMD_ADDRESS_RANGE
|
||||||
|
rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
sec
|
||||||
|
rjmp appRouterHandleDev1Msg_end
|
||||||
|
appRouterHandleDev1Msg_handleClaimAddr:
|
||||||
|
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
|
||||||
|
rcall appRouterIsR19InRange
|
||||||
|
brcs appRouterHandleDev1Msg_end
|
||||||
|
; is not in subnet range, deny
|
||||||
|
rcall appRouterSendDenyAddrR19ToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
sec
|
||||||
|
rjmp appRouterHandleDev1Msg_end
|
||||||
|
#endif
|
||||||
|
appRouterHandleDev1Msg_clcRet:
|
||||||
|
clc
|
||||||
|
appRouterHandleDev1Msg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterIsR19InRange
|
||||||
|
;
|
||||||
|
; @param R19 address to check against range
|
||||||
|
; @clobbers R16
|
||||||
|
|
||||||
|
appRouterIsR19InRange:
|
||||||
|
lds r16, appRouterRangeBegin
|
||||||
|
cp r19, r16
|
||||||
|
brcs appRouterIsR19InRangeClcRet
|
||||||
|
lds r16, appRouterRangeEnd
|
||||||
|
cp r16, r19
|
||||||
|
brcs appRouterIsR19InRangeClcRet
|
||||||
|
sec
|
||||||
|
rjmp appRouterIsR19InRange_end
|
||||||
|
appRouterIsR19InRangeClcRet:
|
||||||
|
clc
|
||||||
|
appRouterIsR19InRange_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterSendDenyAddrR19ToDev1
|
||||||
|
;
|
||||||
|
; @param R19 address to send
|
||||||
|
; @clobbers R16, R17, R18, R19, R20, R21, X, Y
|
||||||
|
|
||||||
|
appRouterSendDenyAddrR19ToDev1:
|
||||||
|
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr
|
||||||
|
rjmp appRouterSendAddrMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y)
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterSendAddrMsgToDev1
|
||||||
|
;
|
||||||
|
; @param R18 command
|
||||||
|
; @param R19 address to send
|
||||||
|
; @clobbers R16 (R17, R18, R19, R20, R21, X, Y)
|
||||||
|
|
||||||
|
appRouterSendAddrMsgToDev1:
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
brcc appRouterSendAddrMsgToDev1_end
|
||||||
|
push r16
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16
|
||||||
|
rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y)
|
||||||
|
appRouterSendAddrMsgToDev1_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterSendRangeMsgToDev1
|
||||||
|
;
|
||||||
|
; @param R18 msg code
|
||||||
|
; @return CFLAG set if message enqueued, cleared on error
|
||||||
|
; @clobbers (R16, R17, R18, R19, R20, R21, R24, R25, X, Y)
|
||||||
|
|
||||||
|
appRouterSendRangeMsgToDev1:
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
brcc appRouterSendRangeMsgToDev1_end
|
||||||
|
push r16
|
||||||
|
lds r20, appRouterRangeBegin
|
||||||
|
lds r21, appRouterRangeEnd
|
||||||
|
adiw xh:xl, 1
|
||||||
|
bigcall NETMSG_Range_Write ; (R16, R17, R18, R19, R20, R21)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16
|
||||||
|
rcall appRouterSendMsgToDev1 ; (R16, R17, R18, R24, R25, X, Y)
|
||||||
|
appRouterSendRangeMsgToDev1_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterSendMsgToDev1
|
||||||
|
;
|
||||||
|
; @param R16 num of allocated buffer
|
||||||
|
; @param X msg to send (points to start of allocated buffer, e.g. buffer header)
|
||||||
|
; @return CFLAG set if message enqueued, cleared on error
|
||||||
|
; @clobbers Y (R16, R17, R18, R24, R25, X)
|
||||||
|
|
||||||
|
appRouterSendMsgToDev1:
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
|
||||||
|
brcs appRouterSendMsgToDev1_end
|
||||||
|
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||||
|
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||||
|
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||||
|
clc
|
||||||
|
appRouterSendMsgToDev1_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterHandleRebootRequest
|
||||||
|
;
|
||||||
|
; Doesn't return if reboot msg is valid.
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
|
||||||
|
appRouterHandleRebootRequest:
|
||||||
|
rcall NETMSG_RebootRequestRead
|
||||||
|
brcc appRouterHandleRebootRequest_end
|
||||||
|
; reboot
|
||||||
|
cli
|
||||||
|
bigjmp BOOTLOADER_ADDR
|
||||||
|
appRouterHandleRebootRequest_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterHandlePingRequest
|
||||||
|
;
|
||||||
|
; @param X pointer to received message
|
||||||
|
|
||||||
|
appRouterHandlePingRequest:
|
||||||
|
ld r17, X
|
||||||
|
lds r16, (netInterfaceData+NET_IFACE_OFFS_ADDRESS)
|
||||||
|
cp r16, r17
|
||||||
|
breq appRouterHandlePingRequest_forMe
|
||||||
|
cpi r17, 0xff
|
||||||
|
breq appRouterHandlePingRequest_forMe
|
||||||
|
clc
|
||||||
|
rjmp appRouterHandlePingRequest_end
|
||||||
|
appRouterHandlePingRequest_forMe:
|
||||||
|
adiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||||
|
ld r17, X
|
||||||
|
sbiw xh:xl, NETMSG_OFFS_SRCADDR
|
||||||
|
push r17
|
||||||
|
bigcall NET_Buffer_Alloc ; (R16, R17, X)
|
||||||
|
pop r17
|
||||||
|
brcc appRouterHandlePingRequest_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)
|
||||||
|
bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X)
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
pop r16 ; buffer num
|
||||||
|
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
|
||||||
|
appRouterHandlePingRequest_end:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterCheckRecvdMsg
|
||||||
|
;
|
||||||
|
; Read messages from either interface and forward to the other one.
|
||||||
|
;
|
||||||
|
; @return CFLAG set if something done, cleared otherwise
|
||||||
|
|
||||||
|
appRouterCheckRecvdMsg:
|
||||||
|
rcall NET_PeekNextIncomingMsgNum ; check read queue (bufNum->r16)
|
||||||
|
brcc appRouterCheckRecvdMsg_end ; no msg, jmp
|
||||||
|
rcall NET_Buffer_Locate ; (R17)
|
||||||
|
rcall appRouterHandleRouterMsgWithHdr ; filter out router msgs
|
||||||
|
brcs appRouterCheckRecvdMsg_removeMsg ; handled by router code, don't forward
|
||||||
|
; let system handle incoming messages
|
||||||
|
adiw xh:xl, 1
|
||||||
|
rcall appRouterLetSysHandleMsg
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
|
||||||
|
; forward to other interface
|
||||||
|
ld r17, X
|
||||||
|
andi r17, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
||||||
|
rcall appRouterReverseInterfaceNum ; (R16, R17)
|
||||||
|
rcall appRouterAddMsgToInterface
|
||||||
|
brcc appRouterCheckRecvdMsg_end ; could not add, jmp
|
||||||
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
appRouterCheckRecvdMsg_removeMsg:
|
||||||
|
rcall NET_GetNextIncomingMsgNum ; take off the queue
|
||||||
|
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||||
|
sec
|
||||||
|
appRouterCheckRecvdMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterHandleRouterMsgWithHdr
|
||||||
|
;
|
||||||
|
; @param X pointer to msg
|
||||||
|
; @return CFLAG set if msg handled, cleared otherwise
|
||||||
|
|
||||||
|
appRouterHandleRouterMsgWithHdr:
|
||||||
|
ld r17, X
|
||||||
|
adiw xh:xl, 1
|
||||||
|
andi r17, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
||||||
|
cpi r17, NETDEV1_IFACENUM
|
||||||
|
brne appRouterHandleRouterMsgWithHdr_any
|
||||||
|
#ifndef APP_ROUTER_NO_ADDR_MGR
|
||||||
|
rcall appRouterHandleDev1Msg ; handle messages from controlled subnet
|
||||||
|
brcs appRouterHandleRouterMsgWithHdr_msgHandled
|
||||||
|
#endif
|
||||||
|
appRouterHandleRouterMsgWithHdr_any:
|
||||||
|
rcall appRouterHandleMsgAnyDev ; handle any msg
|
||||||
|
brcs appRouterHandleRouterMsgWithHdr_msgHandled
|
||||||
|
sbiw xh:xl, 1 ; CFLAG cleared
|
||||||
|
rjmp appRouterHandleRouterMsgWithHdr_end
|
||||||
|
appRouterHandleRouterMsgWithHdr_msgHandled:
|
||||||
|
sbiw xh:xl, 1
|
||||||
|
sec
|
||||||
|
appRouterHandleRouterMsgWithHdr_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterLetSysHandleMsg
|
||||||
|
;
|
||||||
|
; @param X pointer to msg to handle (point behind the buffer header!)
|
||||||
|
; @clobbers any, !X
|
||||||
|
|
||||||
|
appRouterLetSysHandleMsg:
|
||||||
|
ld r16, X
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appRouterLetSysHandleMsg_forMe
|
||||||
|
lds r17, netInterfaceData+NET_IFACE_OFFS_ADDRESS
|
||||||
|
cp r16, r17
|
||||||
|
brne appRouterLetSysHandleMsg_end
|
||||||
|
appRouterLetSysHandleMsg_forMe:
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall onMessageReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall mainModulesOnPacketReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
push xl
|
||||||
|
push xh
|
||||||
|
rcall mainAppsOnPacketReceived
|
||||||
|
pop xh
|
||||||
|
pop xl
|
||||||
|
appRouterLetSysHandleMsg_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterReverseInterfaceNum
|
||||||
|
;
|
||||||
|
; @param r17 buffer num
|
||||||
|
; @return r17 reversed interface number
|
||||||
|
; @clobbers r16, r17
|
||||||
|
|
||||||
|
appRouterReverseInterfaceNum:
|
||||||
|
ldi r16, (1<<NET_IFACE_BUFFER_IFACENUM1_BIT) | (1<<NET_IFACE_BUFFER_IFACENUM0_BIT)
|
||||||
|
eor r17, r16
|
||||||
|
and r17, r16
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterAddMsgToInterface
|
||||||
|
; @param r16 buffer num
|
||||||
|
; @param r17 interface num
|
||||||
|
|
||||||
|
appRouterAddMsgToInterface:
|
||||||
|
cpi r17, NETDEV0_IFACENUM
|
||||||
|
brne appRouterAddMsgToInterface_notNetDev0
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
rjmp NET_Interface_AddOutgoingMsgNum ; try to add msg to interface
|
||||||
|
appRouterAddMsgToInterface_notNetDev0:
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
rjmp NET_Interface_AddOutgoingMsgNum ; try to add msg to interface
|
||||||
|
appRouterAddMsgToInterface_end:
|
||||||
|
clc
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterWriteConfToEeprom
|
||||||
|
;
|
||||||
|
; @clobbers R16, X (R17)
|
||||||
|
|
||||||
|
appRouterWriteConfToEeprom:
|
||||||
|
; write range begin
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
lds r16, appRouterRangeBegin
|
||||||
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
||||||
|
brcc appRouterWriteConfToEeprom_end
|
||||||
|
|
||||||
|
; write range end
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
lds r16, appRouterRangeEnd
|
||||||
|
rcall Eeprom_WriteByteIfChanged ; (R17)
|
||||||
|
appRouterWriteConfToEeprom_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine appRouterReadConfFromEeprom
|
||||||
|
;
|
||||||
|
; @clobbers R16, X (R17)
|
||||||
|
|
||||||
|
appRouterReadConfFromEeprom:
|
||||||
|
; read range begin
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_BEGIN)
|
||||||
|
rcall Eeprom_ReadByte
|
||||||
|
brcc appRouterReadConfFromEeprom_end
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appRouterReadConfFromEeprom_okay ; not set, jmp
|
||||||
|
cpi r16, 2 ; range should at least start at 2 to assign 1 to router
|
||||||
|
brcs appRouterReadConfFromEeprom_okay
|
||||||
|
sts appRouterRangeBegin, r16
|
||||||
|
dec r16
|
||||||
|
sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 ; use addr rangeBegin-1 for router itself
|
||||||
|
sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 ; use same address for both interfaces to save on addresses
|
||||||
|
|
||||||
|
; read range end
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_ROUTER_RANGE_END)
|
||||||
|
rcall Eeprom_ReadByte
|
||||||
|
brcc appRouterReadConfFromEeprom_end
|
||||||
|
cpi r16, 0xff
|
||||||
|
breq appRouterReadConfFromEeprom_okay
|
||||||
|
sts appRouterRangeEnd, r16
|
||||||
|
appRouterReadConfFromEeprom_okay:
|
||||||
|
sec
|
||||||
|
appRouterReadConfFromEeprom_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
; ***************************************************************************
|
; ***************************************************************************
|
||||||
; defines
|
; defines
|
||||||
|
|
||||||
.equ APP_STATS_INTERVAL_MINS = 11
|
.equ APP_STATS_INTERVAL_MINS = 30
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -62,10 +62,6 @@ AppStats_OnEveryMinute:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
AppStats_OnEveryMinute_noIrq:
|
AppStats_OnEveryMinute_noIrq:
|
||||||
; ldi yl, LOW(netInterfaceData)
|
|
||||||
; ldi yh, HIGH(netInterfaceData)
|
|
||||||
; rcall AppNetwork_SendRxdStats ; debug
|
|
||||||
|
|
||||||
lds r16, appStatsTimer
|
lds r16, appStatsTimer
|
||||||
inc r16
|
inc r16
|
||||||
cpi r16, APP_STATS_INTERVAL_MINS
|
cpi r16, APP_STATS_INTERVAL_MINS
|
||||||
@@ -73,97 +69,68 @@ AppStats_OnEveryMinute_noIrq:
|
|||||||
clr r16
|
clr r16
|
||||||
AppStats_OnEveryMinute_store:
|
AppStats_OnEveryMinute_store:
|
||||||
sts appStatsTimer, r16
|
sts appStatsTimer, r16
|
||||||
|
|
||||||
|
mov r17, r16
|
||||||
|
andi r17, 3
|
||||||
|
brne AppStats_OnEveryMinute_sendStats
|
||||||
|
; send device announcement
|
||||||
|
push yl
|
||||||
|
push yh
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
rcall AppNetwork_SendDevice
|
||||||
|
#ifdef APP_STATS_NETDEV2
|
||||||
|
ldi yl, LOW(netInterfaceData2)
|
||||||
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
|
rcall AppNetwork_SendDevice
|
||||||
|
#endif
|
||||||
|
pop yh
|
||||||
|
pop yl
|
||||||
|
AppStats_OnEveryMinute_sendStats:
|
||||||
|
cpi r16, 2
|
||||||
|
breq AppStats_OnEveryMinute_sendMemStats
|
||||||
|
|
||||||
|
cpi r16, 3
|
||||||
|
breq AppStats_OnEveryMinute_sendRecvStats1
|
||||||
|
|
||||||
|
cpi r16, 5
|
||||||
|
breq AppStats_OnEveryMinute_sendSendStats1
|
||||||
|
|
||||||
|
#ifdef APP_STATS_NETDEV2
|
||||||
|
cpi r16, 6
|
||||||
|
breq AppStats_OnEveryMinute_sendRecvStats2
|
||||||
|
|
||||||
|
cpi r16, 7
|
||||||
|
breq AppStats_OnEveryMinute_sendSendStats2
|
||||||
|
#endif
|
||||||
|
; add more here
|
||||||
|
ret
|
||||||
|
AppStats_OnEveryMinute_sendMemStats:
|
||||||
|
rjmp AppNetwork_SendMemStats
|
||||||
|
|
||||||
|
AppStats_OnEveryMinute_sendRecvStats1:
|
||||||
ldi yl, LOW(netInterfaceData)
|
ldi yl, LOW(netInterfaceData)
|
||||||
ldi yh, HIGH(netInterfaceData)
|
ldi yh, HIGH(netInterfaceData)
|
||||||
cpi r16, 1
|
rjmp AppNetwork_SendRxdStats
|
||||||
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
|
|
||||||
cpi r16, 5
|
|
||||||
breq AppStats_OnEveryMinute_sendIoErrs
|
|
||||||
cpi r16, 6
|
|
||||||
breq AppStats_OnEveryMinute_sendNoBufErrs
|
|
||||||
cpi r16, 7
|
|
||||||
breq AppStats_OnEveryMinute_sendCollisionErrs
|
|
||||||
cpi r16, 8
|
|
||||||
breq AppStats_OnEveryMinute_sendBusyErrs
|
|
||||||
#ifdef MODULES_HEAP
|
|
||||||
cpi r16, 9
|
|
||||||
breq AppStats_OnEveryMinute_sendHeapUsed
|
|
||||||
cpi r16, 10
|
|
||||||
breq AppStats_OnEveryMinute_sendHeapfree
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AppStats_OnEveryMinute_sendDevice:
|
AppStats_OnEveryMinute_sendSendStats1:
|
||||||
rjmp AppNetwork_SendDevice
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
rjmp AppNetwork_SendTxdStats
|
||||||
|
|
||||||
AppStats_OnEveryMinute_sendPacketsIn:
|
#ifdef APP_STATS_NETDEV2
|
||||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
|
AppStats_OnEveryMinute_sendRecvStats2:
|
||||||
ldd r18, Y+NET_IFACE_OFFS_PACKETSIN_LOW
|
ldi yl, LOW(netInterfaceData2)
|
||||||
ldd r19, Y+NET_IFACE_OFFS_PACKETSIN_HIGH
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
rjmp appStatsSend16BitValue
|
rjmp AppNetwork_SendRxdStats
|
||||||
AppStats_OnEveryMinute_sendPacketsOut:
|
|
||||||
ldi r17, AQHOME_VALUEID_STATS_PACKETS_OUT
|
AppStats_OnEveryMinute_sendSendStats2:
|
||||||
ldd r18, Y+NET_IFACE_OFFS_PACKETSOUT_LOW
|
ldi yl, LOW(netInterfaceData2)
|
||||||
ldd r19, Y+NET_IFACE_OFFS_PACKETSOUT_HIGH
|
ldi yh, HIGH(netInterfaceData2)
|
||||||
rjmp appStatsSend16BitValue
|
rjmp AppNetwork_SendTxdStats
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
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
|
|
||||||
#ifdef MODULES_HEAP
|
|
||||||
AppStats_OnEveryMinute_sendHeapUsed:
|
|
||||||
ldi r17, AQHOME_VALUEID_STATS_HEAP_USED
|
|
||||||
lds r18, heapUsed
|
|
||||||
lds r19, heapUsed+1
|
|
||||||
rjmp appStatsSend16BitValue
|
|
||||||
AppStats_OnEveryMinute_sendHeapfree:
|
|
||||||
ldi r17, AQHOME_VALUEID_STATS_HEAP_FREE
|
|
||||||
lds r18, heapFree
|
|
||||||
lds r19, heapFree+1
|
|
||||||
rjmp appStatsSend16BitValue
|
|
||||||
#endif
|
#endif
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
|
||||||
; @routine AppStats_OnEveryMinute @global
|
|
||||||
;
|
|
||||||
; @param R17 value id
|
|
||||||
; @param R19:R18 value
|
|
||||||
|
|
||||||
appStatsSend16BitValue:
|
|
||||||
ldi r20, 1
|
|
||||||
clr r21
|
|
||||||
ldi r22, AQHOME_VALUETYPE_STATS
|
|
||||||
bigjmp Main_SendValueReport
|
|
||||||
; @end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,11 @@
|
|||||||
wait_50us.asm
|
wait_50us.asm
|
||||||
watchdog.asm
|
watchdog.asm
|
||||||
list.asm
|
list.asm
|
||||||
|
list_t.asm
|
||||||
tree.asm
|
tree.asm
|
||||||
|
tree_t.asm
|
||||||
|
eeprom-r.asm
|
||||||
|
eeprom-w.asm
|
||||||
</extradist>
|
</extradist>
|
||||||
|
|
||||||
</gwbuild>
|
</gwbuild>
|
||||||
|
|||||||
80
avr/common/eeprom-r.asm
Normal file
80
avr/common/eeprom-r.asm
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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_EEPROM_R_H
|
||||||
|
#define AQH_AVR_COMMON_EEPROM_R_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine Eeprom_ReadByte
|
||||||
|
;
|
||||||
|
; Read a byte from EEPROM (see example in ATtiny24/44/84 manual p.19).
|
||||||
|
;
|
||||||
|
; @param X EEPROM Address to read from
|
||||||
|
; @return CFLAG set if address okay, cleared if out of range
|
||||||
|
; @return R16 byte read
|
||||||
|
; @return X EEPROM Address incremented
|
||||||
|
; @clobbers none
|
||||||
|
|
||||||
|
Eeprom_ReadByte:
|
||||||
|
rcall Eeprom_CheckAddr
|
||||||
|
brcs Eeprom_ReadByte_addrOk
|
||||||
|
ret
|
||||||
|
Eeprom_ReadByte_addrOk:
|
||||||
|
; call routine with IRQs disabled
|
||||||
|
push r15
|
||||||
|
inr r15, SREG
|
||||||
|
cli
|
||||||
|
rcall Eeprom_ReadByte_noirq
|
||||||
|
outr SREG, r15
|
||||||
|
pop r15
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
Eeprom_ReadByte_noirq:
|
||||||
|
; wait until EEPROM ready
|
||||||
|
Eeprom_ReadByte_waitLoop:
|
||||||
|
.ifdef EEPE
|
||||||
|
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
||||||
|
.else
|
||||||
|
sbic EECR, EEWE ; wait for previous write to complete (if any)
|
||||||
|
.endif
|
||||||
|
rjmp Eeprom_ReadByte_waitLoop
|
||||||
|
; read from EEPROM
|
||||||
|
out EEARH, xh ; set EEPROM address
|
||||||
|
out EEARL, xl
|
||||||
|
sbi EECR, EERE ; start EEPROM read by writing EERE
|
||||||
|
in r16, EEDR ; read data from data register
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine Eeprom_CheckAddr
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; @param X EEPROM Address to validate
|
||||||
|
; @return CFLAG set if address okay, cleared if out of range
|
||||||
|
; @clobbers r16
|
||||||
|
|
||||||
|
Eeprom_CheckAddr:
|
||||||
|
mov r16, xl
|
||||||
|
subi r16, LOW(EEPROMEND)
|
||||||
|
mov r16, xh
|
||||||
|
sbci r16, HIGH(EEPROMEND)
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif ; AQH_AVR_COMMON_EEPROM_R_H
|
||||||
|
|
||||||
|
|
||||||
100
avr/common/eeprom-w.asm
Normal file
100
avr/common/eeprom-w.asm
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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_EEPROM_W_H
|
||||||
|
#define AQH_AVR_COMMON_EEPROM_W_H
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; Utils_WriteEepromIncr
|
||||||
|
;
|
||||||
|
; Write a byte to EEPROM (see example in ATtiny24/44/84 manual p.18).
|
||||||
|
;
|
||||||
|
; @param R16 byte to write
|
||||||
|
; @param X EEPROM Address to write to
|
||||||
|
; @return CFLAG set if data written, cleared on error
|
||||||
|
; @clobbers R17
|
||||||
|
|
||||||
|
Eeprom_WriteByte:
|
||||||
|
mov r17, r16
|
||||||
|
rcall Eeprom_CheckAddr ; (r16)
|
||||||
|
mov r16, r17
|
||||||
|
brcs Eeprom_WriteByte_addrOk
|
||||||
|
ret
|
||||||
|
Eeprom_WriteByte_addrOk:
|
||||||
|
; call routine with IRQs disabled
|
||||||
|
push r15
|
||||||
|
inr r15, SREG
|
||||||
|
cli
|
||||||
|
rcall Eeprom_WriteByte_noirq
|
||||||
|
outr SREG, r15
|
||||||
|
pop r15
|
||||||
|
sec
|
||||||
|
ret
|
||||||
|
Eeprom_WriteByte_noirq:
|
||||||
|
; wait for EEPROM to be ready
|
||||||
|
Eeprom_WriteByte_waitLoop:
|
||||||
|
.ifdef EEPE
|
||||||
|
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
||||||
|
.else
|
||||||
|
sbic EECR, EEWE ; wait for previous write to complete (if any)
|
||||||
|
.endif
|
||||||
|
rjmp Eeprom_WriteByte_waitLoop
|
||||||
|
; write data
|
||||||
|
.ifdef EEPM1
|
||||||
|
ldi r17, (0<<EEPM1) | (0<<EEPM0) ; set programming mode
|
||||||
|
.endif
|
||||||
|
out EECR, r17
|
||||||
|
out EEARH, xh ; set EEPROM address
|
||||||
|
out EEARL, xl
|
||||||
|
out EEDR, r16 ; write data to data register
|
||||||
|
.ifdef EEMPE
|
||||||
|
sbi EECR, EEMPE ; write logical one to EEMPE
|
||||||
|
.else
|
||||||
|
sbi EECR, EEMWE ; write logical one to EEMWE
|
||||||
|
.endif
|
||||||
|
.ifdef EEPE
|
||||||
|
sbi EECR, EEPE ; start EEPROM write by setting EEPE
|
||||||
|
.else
|
||||||
|
sbi EECR, EEWE ; start EEPROM write by setting EEWE
|
||||||
|
.endif
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine Eeprom_WriteByteIfChanged @global
|
||||||
|
;
|
||||||
|
; Only write EEPROM byte if changed from current value (save on write cycles)
|
||||||
|
;
|
||||||
|
; @param r16 byte to write
|
||||||
|
; @param X eeprom address to write to
|
||||||
|
; @clobbers r17
|
||||||
|
|
||||||
|
Eeprom_WriteByteIfChanged:
|
||||||
|
mov r17, r16
|
||||||
|
rcall Eeprom_ReadByte
|
||||||
|
brcc Eeprom_WriteByteIfChanged_end
|
||||||
|
cp r16, r17
|
||||||
|
sec
|
||||||
|
breq Eeprom_WriteByteIfChanged_end
|
||||||
|
mov r16, r17
|
||||||
|
rcall Eeprom_WriteByte ; (R17)
|
||||||
|
Eeprom_WriteByteIfChanged_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif ; AQH_AVR_COMMON_EEPROM_W_H
|
||||||
|
|
||||||
|
|
||||||
135
avr/common/eeprom_tlv.asm
Normal file
135
avr/common/eeprom_tlv.asm
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
; ***************************************************************************
|
||||||
|
; 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_EEPROM_TLV_H
|
||||||
|
#define AQH_AVR_COMMON_EEPROM_TLV_H
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine EepromTlv_AddTlv @global
|
||||||
|
;
|
||||||
|
; @param r16 type (must not be 0xff!)
|
||||||
|
; @param r17 length
|
||||||
|
; @return CFLAG set if free bytes found, cleared on error
|
||||||
|
; @return X EEPROM address of data for TLV (behind TLV header)
|
||||||
|
; @clobbers R16, R20, R21, X (R18)
|
||||||
|
|
||||||
|
EepromTlv_AddTlv:
|
||||||
|
mov r20, r16
|
||||||
|
mov r21, r17
|
||||||
|
ldi r16, 0xff
|
||||||
|
rcall EepromTlv_FindFirst ; (R18)
|
||||||
|
brcc EepromTlv_AddTlv_end
|
||||||
|
cpi r17, 0xff
|
||||||
|
brne EepromTlv_AddTlv_clcEnd
|
||||||
|
add xl, r21 ; wanted size
|
||||||
|
adc xh, r21
|
||||||
|
sub xh, r21
|
||||||
|
rcall Eeprom_CheckAddr ; check end address
|
||||||
|
brcc EepromTlv_AddTlv_end
|
||||||
|
sub xl, r21
|
||||||
|
sbc xh, r21
|
||||||
|
add xh, r21
|
||||||
|
sbiw xh:xl, 2
|
||||||
|
mov r16, r20 ; type
|
||||||
|
rcall Eeprom_WriteByte
|
||||||
|
adiw xh:xl, 1
|
||||||
|
mov r16, r21 ; length
|
||||||
|
rcall Eeprom_WriteByte
|
||||||
|
adiw xh:xl, 1
|
||||||
|
sec
|
||||||
|
rjmp EepromTlv_AddTlv_end
|
||||||
|
EepromTlv_AddTlv_clcEnd:
|
||||||
|
clc
|
||||||
|
EepromTlv_AddTlv_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine EepromTlv_FindFirst @global
|
||||||
|
;
|
||||||
|
; Find first matching TLV
|
||||||
|
;
|
||||||
|
; @param r16 TLV type to find
|
||||||
|
; @return CFLAG set if TLV found, cleared otherwise
|
||||||
|
; @return r16 type
|
||||||
|
; @return r17 length
|
||||||
|
; @return X points to begin of TLV data
|
||||||
|
; @clobbers r18
|
||||||
|
|
||||||
|
EepromTlv_FindFirst:
|
||||||
|
ldi xl, LOW(EEPROM_OFFS_TLV)
|
||||||
|
ldi xh, HIGH(EEPROM_OFFS_TLV)
|
||||||
|
rjmp EepromTlv_Find
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine EepromTlv_Find @global
|
||||||
|
;
|
||||||
|
; @param r16 TLV type to find
|
||||||
|
; @param X EEPROM address to start search
|
||||||
|
; @return CFLAG set if TLV found, cleared otherwise
|
||||||
|
; @return r16 type
|
||||||
|
; @return r17 length
|
||||||
|
; @return X points to begin of TLV data
|
||||||
|
; @clobbers r18
|
||||||
|
|
||||||
|
EepromTlv_Find:
|
||||||
|
mov r18, r16
|
||||||
|
EepromTlv_Find_loop:
|
||||||
|
rcall EepromTlv_ReadHeader
|
||||||
|
brcc EepromTlv_Find_notFound
|
||||||
|
cpi r16, r18 ; the one we wanted?
|
||||||
|
breq EepromTlv_Find_found
|
||||||
|
add xl, r17 ; skip TLV data
|
||||||
|
adc xh, r17
|
||||||
|
sub xh, r17
|
||||||
|
rjmp EepromTlv_Find_loop
|
||||||
|
EepromTlv_Find_notFound:
|
||||||
|
clc
|
||||||
|
rjmp EepromTlv_Find_end
|
||||||
|
EepromTlv_Find_found:
|
||||||
|
sec
|
||||||
|
EepromTlv_Find_end:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; ---------------------------------------------------------------------------
|
||||||
|
; @routine EepromTlv_ReadHeader
|
||||||
|
;
|
||||||
|
; @param X EEPROM address
|
||||||
|
; @return CFLAG set if address okay, cleared if out of range
|
||||||
|
; @return r16 type
|
||||||
|
; @return r17 length (only data length, can be 0)
|
||||||
|
; @return X EEPROM address behind TLV header
|
||||||
|
; @clobbers none
|
||||||
|
|
||||||
|
EepromTlv_ReadHeader:
|
||||||
|
rcall Eeprom_ReadByteIncr ; read type
|
||||||
|
brcc EepromTlv_ReadHeader
|
||||||
|
adiw xh:xl, 1
|
||||||
|
push r16
|
||||||
|
rcall Eeprom_ReadByteIncr ; read length
|
||||||
|
mov r17, r16
|
||||||
|
pop r16
|
||||||
|
brcc EepromTlv_ReadHeader
|
||||||
|
adiw xh:xl, 1
|
||||||
|
sec
|
||||||
|
EepromTlv_ReadHeader:
|
||||||
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
; @routine List_GetNextObject @global
|
||||||
|
|
||||||
; @param Y pointer to object
|
; @param Y pointer to object
|
||||||
; @return X pointer to parent object
|
; @return X pointer to successor object
|
||||||
; @clobbers none
|
; @clobbers none
|
||||||
|
|
||||||
List_GetNextObject:
|
List_GetNextObject:
|
||||||
@@ -101,13 +116,13 @@ List_GetPredecessorFor:
|
|||||||
cp r16, yl
|
cp r16, yl
|
||||||
brne List_GetPredecessorFor_next
|
brne List_GetPredecessorFor_next
|
||||||
cp r17, yh
|
cp r17, yh
|
||||||
breq List_GetLastObject_haveIt
|
breq List_GetPredecessorFor_haveIt
|
||||||
List_GetPredecessorFor_next:
|
List_GetPredecessorFor_next:
|
||||||
mov xl, r16
|
mov xl, r16
|
||||||
mov xh, r17
|
mov xh, r17
|
||||||
rjmp List_GetPredecessorFor
|
rjmp List_GetPredecessorFor
|
||||||
List_GetPredecessorFor_haveIt:
|
List_GetPredecessorFor_haveIt:
|
||||||
sbiw xh:xl, 1
|
sbiw xh:xl, 2
|
||||||
List_GetPredecessorFor_ret:
|
List_GetPredecessorFor_ret:
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -127,8 +142,14 @@ List_AddObject:
|
|||||||
rcall List_GetLastObject ; (r16, r17, X, Y)
|
rcall List_GetLastObject ; (r16, r17, X, Y)
|
||||||
pop yh
|
pop yh
|
||||||
pop yl
|
pop yl
|
||||||
st X+, yl ; WID_OFFS_WNEXT_LO
|
mov r16, xl
|
||||||
st X+, yh ; WID_OFFS_WNEXT_HI
|
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
|
ret
|
||||||
; @end
|
; @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
|
#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
|
||||||
@@ -52,7 +52,7 @@ l_loop:
|
|||||||
brcs l_loop
|
brcs l_loop
|
||||||
rjmp l_end ; use cleared CFLAG
|
rjmp l_end ; use cleared CFLAG
|
||||||
l_foundfree:
|
l_foundfree:
|
||||||
ldi r16, 0x80 ; mark as used
|
ldi r16, 0x10 ; mark as used
|
||||||
st X, r16
|
st X, r16
|
||||||
mov r16, r17
|
mov r16, r17
|
||||||
sec ; set CFLAG, return bufnum in r16, pointre in X
|
sec ; set CFLAG, return bufnum in r16, pointre in X
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ RingBufferY_Reset:
|
|||||||
;
|
;
|
||||||
; @return CFLAG on success, cleared on error
|
; @return CFLAG on success, cleared on error
|
||||||
; @return r16 byte read
|
; @return r16 byte read
|
||||||
; @param Y pointer to start of interface data
|
; @param Y base address of ringbuffer struct
|
||||||
; @clobbers R17, R18, X
|
; @clobbers R17, R18, X
|
||||||
|
|
||||||
RingBufferY_ReadByteGuarded:
|
RingBufferY_ReadByteGuarded:
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
; defs
|
; defs
|
||||||
|
|
||||||
.equ TREE_OFFS_LIST = 0
|
.equ TREE_OFFS_LIST = 0
|
||||||
.equ TREE_OFFS_WPARENT_LO = TREE_OFFS_LIST+LIST_SIZE
|
.equ TREE_OFFS_PARENT_LO = TREE_OFFS_LIST+LIST_SIZE
|
||||||
.equ TREE_OFFS_WPARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
|
.equ TREE_OFFS_PARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
|
||||||
.equ TREE_OFFS_WCHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
|
.equ TREE_OFFS_CHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
|
||||||
.equ TREE_OFFS_WCHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
|
.equ TREE_OFFS_CHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
|
||||||
.equ TREE_SIZE = TREE_OFFS_LIST+LIST_SIZE+4
|
.equ TREE_SIZE = TREE_OFFS_LIST+LIST_SIZE+4
|
||||||
|
|
||||||
|
|
||||||
@@ -42,10 +42,10 @@
|
|||||||
Tree_InitObject:
|
Tree_InitObject:
|
||||||
rcall List_InitObject ; (R16)
|
rcall List_InitObject ; (R16)
|
||||||
clr r16 ; clear this->TREE data
|
clr r16 ; clear this->TREE data
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
|
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_LO, r16
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
|
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_HI, r16
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_LO, r16
|
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_LO, r16
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_HI, r16
|
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_HI, r16
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ Tree_InitObject:
|
|||||||
; @clobbers none
|
; @clobbers none
|
||||||
|
|
||||||
Tree_GetParentObject:
|
Tree_GetParentObject:
|
||||||
ldd xl, Y+TREE_OFFS_WPARENT_LO
|
ldd xl, Y+TREE_OFFS_PARENT_LO
|
||||||
ldd xh, Y+TREE_OFFS_WPARENT_HI
|
ldd xh, Y+TREE_OFFS_PARENT_HI
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
@@ -74,13 +74,46 @@ Tree_GetParentObject:
|
|||||||
; @clobbers none
|
; @clobbers none
|
||||||
|
|
||||||
Tree_GetFirstChildObject:
|
Tree_GetFirstChildObject:
|
||||||
ldd xl, Y+TREE_OFFS_WCHILD_LO
|
ldd xl, Y+TREE_OFFS_CHILD_LO
|
||||||
ldd xh, Y+TREE_OFFS_WCHILD_HI
|
ldd xh, Y+TREE_OFFS_CHILD_HI
|
||||||
ret
|
ret
|
||||||
; @end
|
; @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
|
; @routine Tree_GetObjectBelow @global
|
||||||
|
|
||||||
@@ -101,7 +134,7 @@ treeGetObjectBelow:
|
|||||||
mov r16, xl
|
mov r16, xl
|
||||||
or r16, xh
|
or r16, xh
|
||||||
brne treeGetObjectBelow_ret ; got one
|
brne treeGetObjectBelow_ret ; got one
|
||||||
rcall List_GetNextObject
|
rcall Tree_GetNextSibling
|
||||||
mov r16, xl
|
mov r16, xl
|
||||||
or r16, xh
|
or r16, xh
|
||||||
brne treeGetObjectBelow_ret ; got one
|
brne treeGetObjectBelow_ret ; got one
|
||||||
@@ -122,27 +155,27 @@ treeGetObjectBelow_ret:
|
|||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; @routine Tree_AddChildObject @global
|
; @routine Tree_AddChildObject @global
|
||||||
|
|
||||||
; @param X pointer to parent to add to
|
|
||||||
; @param Y pointer to object to add
|
; @param Y pointer to object to add
|
||||||
|
; @param X pointer to parent to add to
|
||||||
; @clobbers r16, r17, r18, x
|
; @clobbers r16, r17, r18, x
|
||||||
|
|
||||||
Tree_AddChildObject:
|
Tree_AddChildObject:
|
||||||
std Y+TREE_OFFS_WPARENT_LO, xl ; immediately store parent pointer
|
std Y+TREE_OFFS_PARENT_LO, xl ; immediately store parent pointer
|
||||||
std Y+TREE_OFFS_WPARENT_HI, xh
|
std Y+TREE_OFFS_PARENT_HI, xh
|
||||||
adiw xh:xl, TREE_OFFS_WCHILD_LO
|
adiw xh:xl, TREE_OFFS_CHILD_LO ; read pointer to first child
|
||||||
ld r16, X+
|
ld r16, X+
|
||||||
ld r17, X
|
ld r17, X
|
||||||
mov r18, r16
|
mov r18, r16
|
||||||
or r18, r17
|
or r18, r17
|
||||||
brne Tree_AddChildObject_addToChildList
|
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
|
st -X, yl
|
||||||
sbiw xh:xl, WID_OFFS_TREE+TREE_OFFS_WCHILD_LO
|
sbiw xh:xl, TREE_OFFS_CHILD_LO
|
||||||
ret
|
ret
|
||||||
Tree_AddChildObject_addToChildList:
|
Tree_AddChildObject_addToChildList:
|
||||||
mov xl, r16
|
mov xl, r16 ; X=first child
|
||||||
mov xh, r17
|
mov xh, r17
|
||||||
rjmp List_AddObject
|
rjmp List_AddObject ; add Y as new object
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|
||||||
@@ -154,17 +187,17 @@ Tree_AddChildObject_addToChildList:
|
|||||||
; @clobbers r16, r17, x
|
; @clobbers r16, r17, x
|
||||||
|
|
||||||
Tree_UnlinkObject:
|
Tree_UnlinkObject:
|
||||||
ldd xl, Y+TREE_OFFS_WPARENT_LO
|
ldd xl, Y+TREE_OFFS_PARENT_LO
|
||||||
ldd xh, Y+TREE_OFFS_WPARENT_HI
|
ldd xh, Y+TREE_OFFS_PARENT_HI
|
||||||
mov r16, xl
|
mov r16, xl
|
||||||
or r16, xh
|
or r16, xh
|
||||||
breq Tree_UnlinkObject_ret ; not part of a tree
|
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 r16, X+
|
||||||
ld r17, X
|
ld r17, X
|
||||||
cp r16, yl ; same as THIS?
|
cp r16, yl ; same as THIS?
|
||||||
brne Tree_UnlinkObject_inList ; nope, need to check childList
|
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
|
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
|
ldd r16, Y+TREE_OFFS_LIST+LIST_OFFS_NEXT_HI ; is first child, set this->NEXT as new first child
|
||||||
st X, r16
|
st X, r16
|
||||||
@@ -177,8 +210,8 @@ Tree_UnlinkObject_inList:
|
|||||||
rcall List_UnlinkObject ; (R16, R17, X)
|
rcall List_UnlinkObject ; (R16, R17, X)
|
||||||
Tree_UnlinkObject_clrParentAndSibling:
|
Tree_UnlinkObject_clrParentAndSibling:
|
||||||
clr r16 ; clear this->PARENT
|
clr r16 ; clear this->PARENT
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
|
std Y+TREE_OFFS_PARENT_LO, r16
|
||||||
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
|
std Y+TREE_OFFS_PARENT_HI, r16
|
||||||
std Y+LIST_OFFS_NEXT_LO, r16
|
std Y+LIST_OFFS_NEXT_LO, r16
|
||||||
std Y+LIST_OFFS_NEXT_HI, r16 ; clear this->NEXT
|
std Y+LIST_OFFS_NEXT_HI, r16 ; clear this->NEXT
|
||||||
Tree_UnlinkObject_ret:
|
Tree_UnlinkObject_ret:
|
||||||
@@ -188,5 +221,6 @@ Tree_UnlinkObject_ret:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif ; AQH_AVR_COMMON_TREE_H
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -7,29 +7,6 @@
|
|||||||
; * Please see toplevel file COPYING of that project for license details. *
|
; * Please see toplevel file COPYING of that project for license details. *
|
||||||
; ***************************************************************************
|
; ***************************************************************************
|
||||||
|
|
||||||
#if 0
|
|
||||||
; M_IO_READ DEST, SRC
|
|
||||||
.macro M_IO_READ
|
|
||||||
.if @1 < 64
|
|
||||||
in @0, @1
|
|
||||||
.else
|
|
||||||
lds @0, @1
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; M_IO_WRITE DEST, SRC
|
|
||||||
.macro M_IO_WRITE
|
|
||||||
.if @0 < 64
|
|
||||||
out @0, @1
|
|
||||||
.else
|
|
||||||
sts @0, @1
|
|
||||||
.endif
|
|
||||||
.endmacro
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
; inr DEST, SRC
|
; inr DEST, SRC
|
||||||
.macro inr
|
.macro inr
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
; @clobbers r22
|
; @clobbers r22
|
||||||
|
|
||||||
Utils_WaitFor50MicroSecs:
|
Utils_WaitFor50MicroSecs:
|
||||||
Utils_WaitNanoSecs 50000, 7, r22 ; wait for 50us (minus RCALL and RET)
|
Utils_WaitNanoSecs 25000, 0, r22 ; wait for 25us
|
||||||
|
Utils_WaitNanoSecs 25000, 7, r22 ; wait for 25us (minus RCALL and RET)
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|||||||
@@ -26,14 +26,19 @@
|
|||||||
all
|
all
|
||||||
c01
|
c01
|
||||||
c02
|
c02
|
||||||
|
n14
|
||||||
n16
|
n16
|
||||||
n20
|
|
||||||
n21
|
n21
|
||||||
n22
|
|
||||||
n23
|
|
||||||
n24
|
n24
|
||||||
n25
|
n25
|
||||||
|
n26
|
||||||
|
n27
|
||||||
|
n28
|
||||||
|
r05
|
||||||
|
r06
|
||||||
|
s03
|
||||||
t03
|
t03
|
||||||
|
t04
|
||||||
</subdirs>
|
</subdirs>
|
||||||
|
|
||||||
</gwbuild>
|
</gwbuild>
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ initApps:
|
|||||||
bigcall AppNetwork_Init
|
bigcall AppNetwork_Init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_ROUTER
|
||||||
|
bigcall AppRouter_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_HUB
|
||||||
|
bigcall AppHub_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_FORWARDER
|
||||||
|
bigcall AppForwarder_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef APPS_MOTION
|
#ifdef APPS_MOTION
|
||||||
bigcall AppMotion_Init
|
bigcall AppMotion_Init
|
||||||
#endif
|
#endif
|
||||||
@@ -62,9 +74,37 @@ initApps:
|
|||||||
;
|
;
|
||||||
|
|
||||||
runApps:
|
runApps:
|
||||||
|
clr r16
|
||||||
|
#ifdef APPS_ROUTER
|
||||||
|
push r16
|
||||||
|
bigcall AppRouter_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0 ; decrease r16 only if CFLAG set
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_HUB
|
||||||
|
push r16
|
||||||
|
bigcall AppHub_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0 ; decrease r16 only if CFLAG set
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_FORWARDER
|
||||||
|
push r16
|
||||||
|
bigcall AppForwarder_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0 ; decrease r16 only if CFLAG set
|
||||||
|
#endif
|
||||||
|
|
||||||
; add more modules here
|
; add more modules here
|
||||||
|
|
||||||
|
tst r16
|
||||||
|
clc
|
||||||
|
breq runApps_end
|
||||||
|
sec
|
||||||
|
runApps_end:
|
||||||
ret
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
.equ AQHOME_VALUETYPE_CO2 = 7
|
.equ AQHOME_VALUETYPE_CO2 = 7
|
||||||
.equ AQHOME_VALUETYPE_TVOC = 8
|
.equ AQHOME_VALUETYPE_TVOC = 8
|
||||||
.equ AQHOME_VALUETYPE_STATS = 9
|
.equ AQHOME_VALUETYPE_STATS = 9
|
||||||
|
.equ AQHOME_VALUETYPE_LIGHT = 10
|
||||||
|
|
||||||
|
|
||||||
; Value Ids
|
; Value Ids
|
||||||
@@ -31,11 +32,21 @@
|
|||||||
.equ AQHOME_VALUEID_STATS_ERRS_NOBUF = 0xe4
|
.equ AQHOME_VALUEID_STATS_ERRS_NOBUF = 0xe4
|
||||||
.equ AQHOME_VALUEID_STATS_ERRS_COLLISIONS = 0xe5
|
.equ AQHOME_VALUEID_STATS_ERRS_COLLISIONS = 0xe5
|
||||||
.equ AQHOME_VALUEID_STATS_ERRS_BUSY = 0xe6
|
.equ AQHOME_VALUEID_STATS_ERRS_BUSY = 0xe6
|
||||||
.equ AQHOME_VALUEID_STATS_HEAP_USED = 0xe7
|
.equ AQHOME_VALUEID_STATS_ERRS_MSGSIZE = 0xe7
|
||||||
.equ AQHOME_VALUEID_STATS_HEAP_FREE = 0xe8
|
.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
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
@@ -46,6 +57,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.equ TLV_OFFS_LEN = 0
|
||||||
|
.equ TLV_OFFS_TYPE = 1
|
||||||
|
.equ TLV_OFFS_VALUE = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; ---------------------------------------------------------------------------
|
; ---------------------------------------------------------------------------
|
||||||
; EEPROM positions
|
; EEPROM positions
|
||||||
|
|
||||||
@@ -65,5 +82,18 @@
|
|||||||
.equ EEPROM_OFFS_MAL_CONF_SRC2_VALUEID = 19 ; 1 byte
|
.equ EEPROM_OFFS_MAL_CONF_SRC2_VALUEID = 19 ; 1 byte
|
||||||
.equ EEPROM_OFFS_MAL_CONF_RGBWVALUE = 20 ; 4 bytes
|
.equ EEPROM_OFFS_MAL_CONF_RGBWVALUE = 20 ; 4 bytes
|
||||||
|
|
||||||
; next is 24
|
.equ EEPROM_OFFS_ROUTER_RANGE_BEGIN = 24 ; 1 byte
|
||||||
|
.equ EEPROM_OFFS_ROUTER_RANGE_END = 25 ; 1 byte
|
||||||
|
; next is 26
|
||||||
|
|
||||||
|
|
||||||
|
.equ EEPROM_OFFS_TLV = 32 ; begin TLV area here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.equ EEPROM_TLV_ROUTER_RANGE = 0x10 ; 2 bytes (range begin, range end)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -103,13 +103,11 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
|
|||||||
ldi r16, 1
|
ldi r16, 1
|
||||||
sts baseTimerModuleReloadValue, r16
|
sts baseTimerModuleReloadValue, r16
|
||||||
sts baseTimerModuleTickCounter, r16
|
sts baseTimerModuleTickCounter, r16
|
||||||
.endif
|
|
||||||
|
|
||||||
;
|
|
||||||
; Settings for clock 8Mhz
|
; Settings for clock 8Mhz
|
||||||
; use timer0 with OCR0=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
|
; use timer0 with OCR0=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
|
||||||
;
|
;
|
||||||
.if clock == 8000000
|
.elif clock == 8000000
|
||||||
; CMP interrupt about every 10ms
|
; CMP interrupt about every 10ms
|
||||||
ldi r16, 78-1
|
ldi r16, 78-1
|
||||||
outr OCR0A, r16
|
outr OCR0A, r16
|
||||||
@@ -117,6 +115,24 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
|
|||||||
ldi r16, 10
|
ldi r16, 10
|
||||||
sts baseTimerModuleReloadValue, r16
|
sts baseTimerModuleReloadValue, r16
|
||||||
sts baseTimerModuleTickCounter, r16
|
sts baseTimerModuleTickCounter, r16
|
||||||
|
.elif clock == 10000000
|
||||||
|
; CMP-A interrupt about every 10ms
|
||||||
|
ldi r16, 98-1 ; (10,000,000/1024)/10 = 97.65625
|
||||||
|
outr OCR0A, r16
|
||||||
|
|
||||||
|
ldi r16, 10
|
||||||
|
sts baseTimerModuleReloadValue, r16
|
||||||
|
sts baseTimerModuleTickCounter, r16
|
||||||
|
.elif clock == 20000000
|
||||||
|
; CMP-A interrupt about every 5ms
|
||||||
|
ldi r16, 98-1
|
||||||
|
outr OCR0A, r16
|
||||||
|
|
||||||
|
ldi r16, 20
|
||||||
|
sts baseTimerModuleReloadValue, r16
|
||||||
|
sts baseTimerModuleTickCounter, r16
|
||||||
|
.else
|
||||||
|
.error "Unhandled clock frequency"
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
||||||
|
|||||||
@@ -19,14 +19,14 @@
|
|||||||
|
|
||||||
systemInitHardware:
|
systemInitHardware:
|
||||||
; set all ports as inputs and enable internal pull-up resistors
|
; set all ports as inputs and enable internal pull-up resistors
|
||||||
ldi r16, 0xff
|
; ldi r16, 0xff
|
||||||
clr r17
|
clr r17
|
||||||
|
|
||||||
out DDRA, r17 ; all input
|
outr DDRA, r17 ; all input
|
||||||
sts PUEA, r16 ; enable pull-up on all
|
outr PUEA, r17 ; disable pull-up on all
|
||||||
|
|
||||||
out DDRB, r17 ; all input
|
outr DDRB, r17 ; all input
|
||||||
sts PUEB, r16 ; enable pull-up on all
|
outr PUEB, r17 ; disable pull-up on all
|
||||||
|
|
||||||
ret
|
ret
|
||||||
; @end
|
; @end
|
||||||
@@ -50,6 +50,22 @@ systemSetSpeed:
|
|||||||
clr r16 ; SUT=0, CLKPS=0
|
clr r16 ; SUT=0, CLKPS=0
|
||||||
sts CCP, r17
|
sts CCP, r17
|
||||||
sts CLKPR, r16
|
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
|
.endif
|
||||||
|
|
||||||
ret
|
ret
|
||||||
@@ -118,16 +134,16 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
|
|||||||
|
|
||||||
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
||||||
.ifdef TIFR0
|
.ifdef TIFR0
|
||||||
out TIFR0, r16
|
outr TIFR0, r16
|
||||||
.else
|
.else
|
||||||
out TIFR, r16
|
outr TIFR, r16
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
ldi r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
|
ldi r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
|
||||||
.ifdef TIMSK0
|
.ifdef TIMSK0
|
||||||
out TIMSK0, r16
|
outr TIMSK0, r16
|
||||||
.else
|
.else
|
||||||
out TIMSK, r16
|
outr TIMSK, r16
|
||||||
.endif
|
.endif
|
||||||
sec
|
sec
|
||||||
ret
|
ret
|
||||||
|
|||||||
@@ -68,23 +68,88 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_COMONUART0
|
#ifdef MODULES_COMONUART0
|
||||||
.include "modules/uart_hw/defs.asm"
|
;.include "modules/uart_hw/defs.asm"
|
||||||
.include "modules/uart_hw/lowlevel.asm"
|
;.include "modules/uart_hw/lowlevel.asm"
|
||||||
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
;.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||||
.include "modules/uart_hw/comonuart0.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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_TTYONUART1
|
#ifdef MODULES_TTYONUART1
|
||||||
#ifndef MODULES_COMONUART0
|
|
||||||
.include "modules/uart_hw/defs.asm"
|
.include "modules/uart_hw/defs.asm"
|
||||||
.include "modules/uart_hw/lowlevel.asm"
|
.include "modules/uart_hw/lowlevel.asm"
|
||||||
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
.include "modules/uart_hw/m_lowlevel_uart.asm"
|
||||||
#endif
|
|
||||||
.include "modules/uart_hw/ttyonuart1.asm"
|
.include "modules/uart_hw/ttyonuart1.asm"
|
||||||
|
;.include "modules/uart_hw2/defs.asm"
|
||||||
|
;.include "modules/uart_hw2/ttyonuart1.asm"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W
|
||||||
|
.include "modules/com2w/defs.asm"
|
||||||
|
.include "modules/com2w/com2w.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W0
|
||||||
|
.include "modules/com2w/defs.asm"
|
||||||
|
.include "modules/com2w/common.asm"
|
||||||
|
.include "modules/com2w/com2w0.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W1
|
||||||
|
.include "modules/com2w/defs.asm"
|
||||||
|
.include "modules/com2w/common.asm"
|
||||||
|
.include "modules/com2w/com2w1.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2WN
|
||||||
|
.include "modules/com2w/defs.asm"
|
||||||
|
.include "modules/com2w/com2wn_init.asm"
|
||||||
|
.include "modules/com2w/com2wn_io.asm"
|
||||||
|
.include "modules/com2w/com2wn_irq.asm"
|
||||||
|
.include "modules/com2w/com2wn_recv.asm"
|
||||||
|
.include "modules/com2w/com2wn_run.asm"
|
||||||
|
.include "modules/com2w/com2wn_send.asm"
|
||||||
|
.include "modules/com2w/com2wn_wait.asm"
|
||||||
|
.include "modules/com2w/com2wn_data.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD0
|
||||||
|
.include "modules/uart_fd/defs.asm"
|
||||||
|
.include "modules/uart_fd/macros.asm"
|
||||||
|
.include "modules/uart_fd/uartfd0.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD1
|
||||||
|
.include "modules/uart_fd/defs.asm"
|
||||||
|
.include "modules/uart_fd/macros.asm"
|
||||||
|
.include "modules/uart_fd/uartfd1.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_CLOCK
|
#ifdef MODULES_CLOCK
|
||||||
.include "modules/clock/main.asm"
|
.include "modules/clock/main.asm"
|
||||||
#endif
|
#endif
|
||||||
@@ -96,6 +161,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_SIGNAL
|
||||||
|
.include "modules/led_signal/main.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_ACTIVITY
|
||||||
|
.include "modules/led_activity/main.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_TWI_MASTER
|
#ifdef MODULES_TWI_MASTER
|
||||||
.include "modules/twimaster/main.asm"
|
.include "modules/twimaster/main.asm"
|
||||||
#endif
|
#endif
|
||||||
@@ -144,6 +219,9 @@
|
|||||||
|
|
||||||
#ifdef MODULES_CCS811
|
#ifdef MODULES_CCS811
|
||||||
.include "modules/ccs811/main.asm"
|
.include "modules/ccs811/main.asm"
|
||||||
|
#ifdef MODULES_NETWORK
|
||||||
|
.include "modules/ccs811/send.asm"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_TCRT1000
|
#ifdef MODULES_TCRT1000
|
||||||
@@ -157,6 +235,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_LCD
|
||||||
|
.include "modules/lcd/main.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_ILI9341
|
#ifdef MODULES_ILI9341
|
||||||
.include "modules/lcd2/ili9341/defs.asm"
|
.include "modules/lcd2/ili9341/defs.asm"
|
||||||
.include "modules/lcd2/ili9341/main.asm"
|
.include "modules/lcd2/ili9341/main.asm"
|
||||||
@@ -165,6 +247,21 @@
|
|||||||
.include "modules/lcd2/ili9341/text.asm"
|
.include "modules/lcd2/ili9341/text.asm"
|
||||||
#endif
|
#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
|
#ifdef MODULES_FONT_8X8
|
||||||
.include "modules/lcd2/font/defs.asm"
|
.include "modules/lcd2/font/defs.asm"
|
||||||
.include "modules/lcd2/font/font8x8.asm"
|
.include "modules/lcd2/font/font8x8.asm"
|
||||||
@@ -177,6 +274,14 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_BRIGHTNESS
|
||||||
|
.include "modules/brightness/main.asm"
|
||||||
|
#ifdef MODULES_NETWORK
|
||||||
|
.include "modules/brightness/send.asm"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef APPS_MOTION
|
#ifdef APPS_MOTION
|
||||||
.include "modules/f_keepup/main.asm"
|
.include "modules/f_keepup/main.asm"
|
||||||
.include "modules/valsched/main.asm"
|
.include "modules/valsched/main.asm"
|
||||||
@@ -198,6 +303,44 @@
|
|||||||
.include "modules/network/msg/reboot-d.asm"
|
.include "modules/network/msg/reboot-d.asm"
|
||||||
.include "modules/network/msg/reboot-r.asm"
|
.include "modules/network/msg/reboot-r.asm"
|
||||||
.include "modules/network/msg/pong-w.asm"
|
.include "modules/network/msg/pong-w.asm"
|
||||||
|
.include "modules/network/msg/range-d.asm"
|
||||||
|
.include "modules/network/msg/range-r.asm"
|
||||||
|
.include "common/eeprom-r.asm"
|
||||||
|
.include "common/eeprom-w.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef APPS_ROUTER
|
||||||
|
.include "apps/router/main.asm"
|
||||||
|
.include "modules/network/msg/reboot-d.asm"
|
||||||
|
.include "modules/network/msg/reboot-r.asm"
|
||||||
|
.include "modules/network/msg/pong-w.asm"
|
||||||
|
.include "modules/network/msg/range-d.asm"
|
||||||
|
.include "modules/network/msg/range-r.asm"
|
||||||
|
.include "modules/network/msg/range-w.asm"
|
||||||
|
.include "common/eeprom-r.asm"
|
||||||
|
.include "common/eeprom-w.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef APPS_HUB
|
||||||
|
.include "apps/hub/main.asm"
|
||||||
|
.include "modules/network/msg/reboot-d.asm"
|
||||||
|
.include "modules/network/msg/reboot-r.asm"
|
||||||
|
.include "modules/network/msg/pong-w.asm"
|
||||||
|
.include "modules/network/msg/range-d.asm"
|
||||||
|
.include "modules/network/msg/range-r.asm"
|
||||||
|
.include "modules/network/msg/range-w.asm"
|
||||||
|
.include "common/eeprom-r.asm"
|
||||||
|
.include "common/eeprom-w.asm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef APPS_FORWARDER
|
||||||
|
.include "apps/forwarder/main.asm"
|
||||||
|
.include "modules/network/msg/reboot-r.asm"
|
||||||
|
.include "modules/network/msg/reboot-d.asm"
|
||||||
|
.include "modules/network/msg/pong-w.asm"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,11 +55,35 @@ main:
|
|||||||
|
|
||||||
main_loop:
|
main_loop:
|
||||||
bigcall systemSleep ; system-dependant
|
bigcall systemSleep ; system-dependant
|
||||||
bigcall runModules
|
|
||||||
bigcall runApps
|
; run loop as long as some run function returns with CFLAG set
|
||||||
|
clr r17
|
||||||
bigcall onEveryLoop ; call into main app
|
main_runLoop:
|
||||||
|
push r17
|
||||||
|
clr r16
|
||||||
|
push r16
|
||||||
|
bigcall runModules
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
|
||||||
|
push r16
|
||||||
|
bigcall runApps
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
|
||||||
|
push r16
|
||||||
|
bigcall onEveryLoop ; call into main app
|
||||||
|
pop r16
|
||||||
|
pop r17
|
||||||
|
|
||||||
|
tst r16
|
||||||
|
breq main_endRunLoop
|
||||||
|
inc r17
|
||||||
|
cpi r17, 10
|
||||||
|
brcc main_endRunLoop
|
||||||
|
brne main_runLoop
|
||||||
|
main_endRunLoop:
|
||||||
|
|
||||||
#ifdef MODULES_NETWORK
|
#ifdef MODULES_NETWORK
|
||||||
#ifndef MAIN_WITHOUT_MSG_HANDLING
|
#ifndef MAIN_WITHOUT_MSG_HANDLING
|
||||||
rcall mainHandleMessages
|
rcall mainHandleMessages
|
||||||
@@ -91,6 +115,16 @@ onSystemTimerTick:
|
|||||||
bigcall LedSimple_Every100ms
|
bigcall LedSimple_Every100ms
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_SIGNAL
|
||||||
|
bigcall LedSignal_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_ACTIVITY
|
||||||
|
bigcall LedActivity_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_UART_BITBANG
|
#ifdef MODULES_UART_BITBANG
|
||||||
bigcall UART_BitBang_Every100ms
|
bigcall UART_BitBang_Every100ms
|
||||||
#endif
|
#endif
|
||||||
@@ -103,14 +137,47 @@ onSystemTimerTick:
|
|||||||
bigcall TtyOnUart1_Periodically
|
bigcall TtyOnUart1_Periodically
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD0
|
||||||
|
bigcall UARTFD0_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD1
|
||||||
|
bigcall UARTFD1_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_COMONUART0
|
#ifdef MODULES_COMONUART0
|
||||||
bigcall ComOnUart0_Periodically
|
bigcall ComOnUart0_Periodically
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COMONUART1
|
||||||
|
bigcall ComOnUart1_Periodically
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W
|
||||||
|
bigcall COM2W_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W0
|
||||||
|
bigcall COM2W0_Periodically
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W1
|
||||||
|
bigcall COM2W1_Periodically
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2WN
|
||||||
|
bigcall COM2WN_Periodically
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_TCRT1000
|
#ifdef MODULES_TCRT1000
|
||||||
bigcall TCRT1K_Every100ms
|
bigcall TCRT1K_Every100ms
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_BRIGHTNESS
|
||||||
|
bigcall Brightness_Every100ms
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef APPS_NETWORK
|
#ifdef APPS_NETWORK
|
||||||
ldi yl, LOW(netInterfaceData)
|
ldi yl, LOW(netInterfaceData)
|
||||||
@@ -145,6 +212,11 @@ sysOnEverySecond:
|
|||||||
#ifdef APPS_REPORTSENSORS
|
#ifdef APPS_REPORTSENSORS
|
||||||
bigcall AppReportSensors_OnEverySecond
|
bigcall AppReportSensors_OnEverySecond
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_SGP30
|
||||||
|
bigcall SGP30_EverySecond
|
||||||
|
#endif
|
||||||
|
|
||||||
bigjmp onEverySecond
|
bigjmp onEverySecond
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
@@ -154,6 +226,10 @@ sysOnEveryMinute:
|
|||||||
bigcall AppStats_OnEveryMinute
|
bigcall AppStats_OnEveryMinute
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_CCS811
|
||||||
|
bigcall CCS811_OnEveryMinute
|
||||||
|
#endif
|
||||||
|
|
||||||
bigjmp onEveryMinute
|
bigjmp onEveryMinute
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
@@ -164,6 +240,20 @@ sysOnEveryHour:
|
|||||||
|
|
||||||
|
|
||||||
sysOnEveryDay:
|
sysOnEveryDay:
|
||||||
|
#ifdef APPS_NETWORK
|
||||||
|
ldi yl, LOW(netInterfaceData)
|
||||||
|
ldi yh, HIGH(netInterfaceData)
|
||||||
|
bigcall AppNetwork_EveryDay
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_ROUTER
|
||||||
|
bigcall AppRouter_EveryDay
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef APPS_FORWARDER
|
||||||
|
bigcall AppForwarder_EveryDay
|
||||||
|
#endif
|
||||||
|
|
||||||
bigjmp onEveryDay
|
bigjmp onEveryDay
|
||||||
; @end
|
; @end
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,19 @@ initModules:
|
|||||||
#ifdef MODULES_LED_SIMPLE
|
#ifdef MODULES_LED_SIMPLE
|
||||||
bigcall LedSimple_Init
|
bigcall LedSimple_Init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_SIGNAL
|
||||||
|
bigcall LedSignal_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_LED_ACTIVITY
|
||||||
|
bigcall LedActivity_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_COM
|
#ifdef MODULES_COM
|
||||||
bigcall Com2_Init ; init COM module
|
bigcall Com2_Init ; init COM module
|
||||||
bigcall CPRO_Init ; init COM protocol module
|
bigcall CPRO_Init ; init COM protocol module
|
||||||
@@ -73,10 +85,39 @@ initModules:
|
|||||||
bigcall TtyOnUart1_Init
|
bigcall TtyOnUart1_Init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD0
|
||||||
|
bigcall UARTFD0_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD1
|
||||||
|
bigcall UARTFD1_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_COMONUART0
|
#ifdef MODULES_COMONUART0
|
||||||
bigcall ComOnUart0_Init
|
bigcall ComOnUart0_Init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COMONUART1
|
||||||
|
bigcall ComOnUart1_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W
|
||||||
|
bigcall COM2W_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W0
|
||||||
|
bigcall COM2W0_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W1
|
||||||
|
bigcall COM2W1_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2WN
|
||||||
|
bigcall COM2WN_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_MOTION
|
#ifdef MODULES_MOTION
|
||||||
bigcall Motion_Init
|
bigcall Motion_Init
|
||||||
#endif
|
#endif
|
||||||
@@ -148,6 +189,10 @@ initModules:
|
|||||||
bigcall ILI9341_Init
|
bigcall ILI9341_Init
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_BRIGHTNESS
|
||||||
|
bigcall Brightness_Init
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
; done
|
; done
|
||||||
ret
|
ret
|
||||||
@@ -160,61 +205,92 @@ initModules:
|
|||||||
;
|
;
|
||||||
; Call run functions of the used modules. Add your routine calls here.
|
; Call run functions of the used modules. Add your routine calls here.
|
||||||
;
|
;
|
||||||
; IN:
|
; @return CFLAG set: at least one RUN routine returned CFLAG set
|
||||||
; - nothing
|
; @clobbers all
|
||||||
; OUT:
|
|
||||||
; - nothing
|
|
||||||
; USED: depending on called routines
|
|
||||||
|
|
||||||
runModules:
|
runModules:
|
||||||
bigcall BaseTimer_Run
|
clr r16
|
||||||
|
|
||||||
#ifdef MODULES_COM
|
push r16
|
||||||
; COM module (call until carry flag cleared but at most 10 times to not starve other modules)
|
bigcall BaseTimer_Run
|
||||||
ldi r16, 10
|
pop r16
|
||||||
runModules_Com:
|
sbci r16, 0
|
||||||
push r16
|
|
||||||
bigcall Com2_Run
|
#ifdef MODULES_TTYONUART1
|
||||||
pop r16
|
push r16
|
||||||
brcc runModules_ComEnd
|
bigcall TtyOnUart1_Run
|
||||||
dec r16
|
pop r16
|
||||||
brne runModules_Com
|
|
||||||
runModules_ComEnd:
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_TTYONUART1
|
|
||||||
bigcall TtyOnUart1_Run
|
#ifdef MODULES_UARTFD0
|
||||||
|
push r16
|
||||||
|
bigcall UARTFD0_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_UARTFD1
|
||||||
|
push r16
|
||||||
|
bigcall UARTFD1_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_COMONUART0
|
#ifdef MODULES_COMONUART0
|
||||||
bigcall ComOnUart0_Run
|
push r16
|
||||||
|
bigcall ComOnUart0_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MODULES_STATS
|
#ifdef MODULES_COMONUART1
|
||||||
bigcall Stats_Run
|
push r16
|
||||||
#endif
|
bigcall ComOnUart1_Run
|
||||||
|
pop r16
|
||||||
#ifdef MODULES_REED
|
sbci r16, 0
|
||||||
bigcall REED_Run
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODULES_CNY70
|
|
||||||
bigcall CNY70_Run
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODULES_MOTION_LIGHT
|
|
||||||
; rcall MotionLight_Run
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef MODULES_TCRT1000
|
#ifdef MODULES_COM2W
|
||||||
; rcall TCRT1K_Run
|
push r16
|
||||||
|
bigcall COM2W_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W0
|
||||||
|
push r16
|
||||||
|
bigcall COM2W0_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2W1
|
||||||
|
push r16
|
||||||
|
bigcall COM2W1_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODULES_COM2WN
|
||||||
|
push r16
|
||||||
|
bigcall COM2WN_Run
|
||||||
|
pop r16
|
||||||
|
sbci r16, 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
; add more modules here
|
; add more modules here
|
||||||
|
|
||||||
|
; check for repeat request
|
||||||
|
tst r16
|
||||||
|
clc
|
||||||
|
breq runModules_end
|
||||||
|
sec
|
||||||
|
runModules_end:
|
||||||
ret
|
ret
|
||||||
|
; @end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mainModulesOnPacketReceived:
|
mainModulesOnPacketReceived:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
; @param R19:R18 value
|
; @param R19:R18 value
|
||||||
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
||||||
; @param R22 value type
|
; @param R22 value type
|
||||||
|
; @return CFLAG on success, cleared on error
|
||||||
|
|
||||||
Main_SendValueReport:
|
Main_SendValueReport:
|
||||||
push r17
|
push r17
|
||||||
@@ -52,6 +53,7 @@ Main_SendValueReport_end:
|
|||||||
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
|
||||||
; @param R23 command
|
; @param R23 command
|
||||||
; @param R25:R24 ref msg id
|
; @param R25:R24 ref msg id
|
||||||
|
; @return CFLAG on success, cleared on error
|
||||||
|
|
||||||
Main_SendValueResponse:
|
Main_SendValueResponse:
|
||||||
push r17
|
push r17
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user