3 Commits

Author SHA1 Message Date
Martin Preuss
deddf42379 First try to unify ATTN handling. 2025-05-29 14:32:48 +02:00
Martin Preuss
e584245965 c01: added defs when using uart_bitbang2. 2025-05-29 14:32:29 +02:00
Martin Preuss
46720d791c avr: some ideas for autosync. 2025-05-29 12:47:41 +02:00
384 changed files with 11278 additions and 28814 deletions

5
0BUILD
View File

@@ -2,7 +2,7 @@
<gwbuild>
<project name="aqhome" version="0.0.14" so_current="0" so_age="0" so_revision="14" write_config_h="TRUE">
<project name="aqhome" version="0.0.10" so_current="0" so_age="0" so_revision="10" write_config_h="TRUE">
<setVar name="package">$(project_name)</setVar>
<setVar name="version">
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
@@ -51,8 +51,6 @@
<setVar name="pkgincludedir">$(includedir)/aqhome/$(package)</setVar>
<setVar name="pkgdatadir">$(datadir)/$(package)</setVar>
<setVar name="httpdatadir">/var/www</setVar>
<option id="enable_testcode" type="string">
<default>TRUE</default>
<choices>TRUE FALSE</choices>
@@ -128,7 +126,6 @@
</option>
<checkheaders>
signal.h
sys/stat.h

View File

@@ -3,7 +3,7 @@
<gwbuild>
<target type="Program" name="aqhome-cgi" install="$(libdir)/cgi-bin" >
<target type="Program" name="aqhome-cgi" install="$(sbindir)" >
<includes type="c" >
$(gwenhywfar_cflags)
@@ -55,7 +55,6 @@
<libraries>
$(gwenhywfar_libs)
-lm
$(aqcgi_libs)
</libraries>
<subdirs>
@@ -118,7 +117,6 @@
<useTargets>
aqhome
aqhcgi_service
aqhcgi_modules
</useTargets>
<libraries>
@@ -129,7 +127,6 @@
<subdirs>
service
modules
</subdirs>

View File

@@ -1,23 +0,0 @@
Modules:
- login
- signup
- main
- devices
- list
- show?name="nodes/12345678"
- add
- edit
- delete
- values
- rooms
- users
- list
- show?alias="admin"
- add
- edit
- delete
- dashboards

View File

@@ -1,181 +1,11 @@
#include "./service_file.h"
#include "aqhome-cgi/modules/mroot.h"
#include "aqhome/aqhome.h"
#include <aqcgi/cgi.h>
#include <aqcgi/request.h>
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/nogui.h>
#include <gwenhywfar/logger.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define AQHOME_CGI_LOGFILE "/var/www/aqhome-cgi/log/aqhome-cgi.log"
#define AQHOME_CGI_DEFAULT_STATIC_FILES "0-build/services/static"
#define AQHOME_CGI_DEFAULT_RUNTIME_FILES "0-build/services/runtime"
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles);
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles);
AQH_MODULE *_loadModule(AQH_SERVICE *sv, AQCGI_REQUEST *rq, AQH_MODULE *mParent, const char *sModuleName);
static void logStart(void);
int main(int argc, char **argv)
{
GWEN_GUI *gui;
AQCGI_REQUEST *rq;
GWEN_Init();
gui=GWEN_NoGui_new();
GWEN_Gui_SetGui(gui);
logStart();
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(AQCGI_LOGDOMAIN, "aqcgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_Open(NULL, "aqhome-cgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
DBG_ERROR(NULL, "Init CGI");
AQCGI_Init();
GWEN_Logger_Close(GWEN_LOGDOMAIN);
GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
rq=AQCGI_ReadRequest();
if (rq) {
const char *sPathStaticFiles;
const char *sPathRuntimeFiles;
sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
if (!(sPathStaticFiles && *sPathStaticFiles))
sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;
sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
if (!(sPathRuntimeFiles && *sPathRuntimeFiles))
sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES;
_handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles);
}
else {
fprintf(stdout, "Content-type: text/plain\n\n");
fprintf(stdout, "Error: No Request!\n");
return 0;
}
AQCGI_Fini();
return 0;
}
void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles)
{
AQH_SERVICE *sv;
int rv;
sv=AQH_ServiceFiles_new(sPathRuntimeFiles);
rv=_handlePath(sv, rq, sPathStaticFiles);
if (rv<0) {
}
AQH_Service_free(sv);
}
int _handlePath(AQH_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles)
{
AQH_MODULE *mRoot;
AQH_MODULE *mParent;
const GWEN_STRINGLIST *sl;
mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
mParent=mRoot;
sl=AQCGI_Request_GetStringlistPath(rq);
if (sl) {
GWEN_STRINGLISTENTRY *se;
se=GWEN_StringList_FirstEntry(sl);
while(se) {
GWEN_STRINGLISTENTRY *seNext;
const char *s;
seNext=GWEN_StringListEntry_Next(se);
s=GWEN_StringListEntry_Data(se);
if (s && *s) {
if (seNext) {
AQH_MODULE *m;
DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
m=AQH_ModService_LoadSubModule(mParent, rq, s);
if (m==NULL) {
AQH_Module_free(mRoot);
AQCGI_SendResponseWithStatus(rq, 404, "Not found");
return GWEN_ERROR_GENERIC;
}
mParent=m;
}
else {
int rv;
/* last, let module handle remaining part */
rv=AQH_ModService_HandleRequest(mParent, rq, s);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
AQH_Module_free(mRoot);
return rv;
}
break;
}
}
se=seNext;
}
AQH_Module_free(mRoot);
return 0;
}
else {
AQH_Module_free(mRoot);
return GWEN_ERROR_GENERIC;
}
}
void logStart()
{
FILE *f;
f=fopen(AQHOME_CGI_LOGFILE, "a+");
if (f!=NULL) {
fprintf(f, "Started.\n");
fclose(f);
}
}

View File

@@ -1,84 +0,0 @@
<?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>

View File

@@ -1,246 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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;
}
}

View File

@@ -1,27 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_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

View File

@@ -1,18 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MROOT_P_H
#define AQHOME_CGI_MROOT_P_H
#include "aqhome-cgi/modules/mroot.h"
#endif

View File

@@ -1,291 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./mservice_p.h"
#include "aqhome-cgi/service/module.h"
#include <gwenhywfar/debug.h>
/* ------------------------------------------------------------------------------------------------
* defs and enums
* ------------------------------------------------------------------------------------------------
*/
#define AQH_MOD_SERVICE_HEADERFILE "header.html"
#define AQH_MOD_SERVICE_FOOTERFILE "footer.html"
/* ------------------------------------------------------------------------------------------------
* global vars
* ------------------------------------------------------------------------------------------------
*/
GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE)
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
/* ------------------------------------------------------------------------------------------------
* code
* ------------------------------------------------------------------------------------------------
*/
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder)
{
AQH_MODULE *m;
AQH_MOD_SERVICE *xm;
m=AQH_Module_new();
GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm);
GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData);
xm->service=sv;
xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL;
return m;
}
void _freeData(GWEN_UNUSED void *bp, void *p)
{
AQH_MOD_SERVICE *xm;
xm=(AQH_MOD_SERVICE*) p;
free(xm->baseFolder);
GWEN_FREE_OBJECT(xm);
}
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
return xm->service;
}
}
return NULL;
}
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
return xm->baseFolder;
}
}
return NULL;
}
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
xm->handleRequestFn=fn;
}
}
}
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
xm->loadSubModuleFn=fn;
}
}
}
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
{
if (m && dbuf) {
AQH_MODULE *mParent;
mParent=AQH_Module_Tree2_GetParent(m);
if (mParent) {
int rv;
rv=AQH_ModService_AddHeader(mParent, lang, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
}
return AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf);
}
DBG_ERROR(NULL, "Argument missing");
return GWEN_ERROR_INVALID;
}
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf)
{
if (m && dbuf) {
AQH_MODULE *mParent;
int rv;
rv=AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
mParent=AQH_Module_Tree2_GetParent(m);
if (mParent) {
int rv;
rv=AQH_ModService_AddFooter(mParent, lang, dbuf);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
}
return 0;
}
else {
DBG_ERROR(NULL, "Argument missing");
return GWEN_ERROR_INVALID;
}
}
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename)
{
GWEN_BUFFER *buf;
int rv;
buf=GWEN_Buffer_new(0, 256, 0, 1);
rv=AQH_ModService_AddHeader(m, lang, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
rv=AQH_ModService_AddFooter(m, lang, buf);
if (rv<0) {
AQCGI_SendResponseWithStatus(rq, 500, "Internal error");
GWEN_Buffer_free(buf);
return GWEN_ERROR_INTERNAL;
}
AQCGI_Request_SetBufferResponseBody(rq, buf);
AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html");
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
return 0;
}
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm && xm->handleRequestFn)
return xm->handleRequestFn(m, rq, sLastPathElem);
}
return GWEN_ERROR_NOT_IMPLEMENTED;
}
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName)
{
if (m) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm && xm->loadSubModuleFn)
return xm->loadSubModuleFn(m, rq, sModuleName);
}
return NULL;
}
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf)
{
if (m && filename && dbuf) {
AQH_MOD_SERVICE *xm;
xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m);
if (xm) {
GWEN_BUFFER *fbuf;
int rv;
fbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(fbuf, xm->baseFolder);
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en");
GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S);
GWEN_Buffer_AppendString(fbuf, filename);
DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf));
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf);
if (rv<0) {
DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv);
GWEN_Buffer_free(fbuf);
return rv;
}
GWEN_Buffer_free(fbuf);
return 0;
}
}
DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)");
return GWEN_ERROR_INTERNAL;
}

View File

@@ -1,46 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MSERVICE_H
#define AQHOME_CGI_MSERVICE_H
#include <aqhome-cgi/service/module.h>
#include <aqhome-cgi/service/service.h>
#include <aqcgi/request.h>
#include <gwenhywfar/buffer.h>
typedef int (*AQH_MODSERVICE_HANDLEREQUEST_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
typedef AQH_MODULE* (*AQH_MODSERVICE_LOADSUBMODULE_FN)(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
AQH_MODULE *AQH_ModService_new(AQH_SERVICE *sv, const char *baseFolder);
AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m);
const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m);
int AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
int AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf);
AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename);
int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf);
void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn);
void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn);
#endif

View File

@@ -1,27 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_CGI_MSERVICE_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

View File

@@ -1,13 +0,0 @@
<?xml?>
<gwbuild>
<data dist="true" install="$(httpdatadir)/aqhome-cgi/static/en">
header.html
footer.html
login.html
</data>
</gwbuild>

View File

@@ -1,4 +0,0 @@
</body>
</html>

View File

@@ -1,17 +0,0 @@
<!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>

View File

@@ -1,25 +0,0 @@
<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>

View File

@@ -54,10 +54,6 @@
<descr>Waiting for approval by admin</descr>
</item>
<item name="active">
<descr>User active</descr>
</item>
</enum>
</enums>

View File

@@ -70,8 +70,6 @@ static int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *s
static int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName);
static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName);
//static void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db);
/* ------------------------------------------------------------------------------------------------
@@ -171,9 +169,6 @@ int _saveUser(AQH_SERVICE *sv, AQH_USER *user)
GWEN_DB_Group_free(db);
return rv;
}
//_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db);
rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db);
if (rv<0) {
DBG_ERROR(NULL, "here (%d)", rv);
@@ -419,7 +414,6 @@ GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv)
GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName)
{
DBG_ERROR(NULL, "Lock and load group %s/%s", groupName, subGroupName);
if (sv && groupName && subGroupName) {
AQH_SERVICE_FILE *xs;
@@ -428,20 +422,17 @@ GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const cha
GWEN_DB_NODE *db=NULL;
int rv;
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
return NULL;
}
DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db);
if (rv<0) {
DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv);
GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
return NULL;
}
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
@@ -451,9 +442,6 @@ GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const cha
return db;
}
}
else {
DBG_ERROR(NULL, "Missing argument");
}
return NULL;
}
@@ -466,26 +454,25 @@ int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGrou
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
GWEN_DB_NODE *db=NULL;
int rv;
DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db);
if (rv<0) {
DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv);
return rv;
}
DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName);
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
GWEN_DB_Group_free(db);
return rv;
}
@@ -504,6 +491,7 @@ int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroup
xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv);
if (xs) {
GWEN_DB_NODE *db=NULL;
int rv;
rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName);
@@ -527,6 +515,7 @@ int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroup
rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv);
GWEN_DB_Group_free(db);
return rv;
}
@@ -588,24 +577,3 @@ 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

View File

@@ -13,7 +13,6 @@
#include "aqhome-cgi/service/service.h"
AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder);

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -33,8 +33,8 @@
* ------------------------------------------------------------------------------------------------
*/
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 1024
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 512
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES 2048
#define AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS 1024
/* ------------------------------------------------------------------------------------------------
@@ -44,15 +44,13 @@
static int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value,
int mode,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num, uint32_t refMsgId);
static int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
static int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
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 int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint64_t num, uint32_t refMsgId);
static void _sendDataPointsResponse(AQH_OBJECT *ep, const AQH_VALUE *value, const uint64_t *tablePtr,
uint32_t refMsgId);
static void _getAndSendLastDatapoint(AQH_STORAGE *storage, AQH_OBJECT *ep, const AQH_VALUE *value, uint32_t refMsgId);
@@ -81,18 +79,16 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
uint64_t tsBegin;
uint64_t tsEnd;
uint64_t numRequested;
int mode;
tsBegin=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0);
tsEnd=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0);
numRequested=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_NUM, 0);
mode=AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, AQH_MSGDATA_GETDATA_MODE_FIRST);
value=AQH_Storage_GetValueByNameForSystem(xo->storage, valueName);
if (value) {
int resultCode;
resultCode=_getAndSendDataPoints(xo->storage, ep, value, mode, tsBegin, tsEnd, numRequested, refMsgId);
resultCode=_getAndSendDataPoints(xo->storage, ep, value, tsBegin, tsEnd, numRequested, refMsgId);
AqHomeDataServer_SendResponseResultToEndpoint(ep, refMsgId, resultCode);
}
else {
@@ -118,31 +114,30 @@ void AqHomeDataServer_HandleGetDataPoints(AQH_OBJECT *o, AQH_OBJECT *ep, const A
int _getAndSendDataPoints(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value,
int mode,
uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
uint32_t refMsgId)
{
switch(mode) {
case AQH_MSGDATA_GETDATA_MODE_FIRST: return _getAndSendDataPointsFirst(storage, ep, value, num, refMsgId);
case AQH_MSGDATA_GETDATA_MODE_PERIOD: return _getAndSendDataPointsPeriod(storage, ep, value, tsBegin, tsEnd, num, refMsgId);
default:
case AQH_MSGDATA_GETDATA_MODE_LAST: return _getAndSendDataPointsLast(storage, ep, value, num, refMsgId);
if (num==0)
return _getAndSendDataPointsNoNum(storage, ep, value, tsBegin, tsEnd, refMsgId);
else if (num==1) {
_getAndSendLastDatapoint(storage, ep, value, refMsgId);
return AQH_MSGDATA_RESULT_SUCCESS;
}
else
return _getAndSendDataPointsWithNum(storage, ep, value, num, refMsgId);
}
int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd, uint64_t num,
uint32_t refMsgId)
int _getAndSendDataPointsNoNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t tsBegin, uint64_t tsEnd,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
valueId=AQH_Value_GetId(value);
if (num==0 || num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES)
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES;
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, num);
tablePtr=AQH_Storage_GetDataPoints(storage, valueId, tsBegin, tsEnd, AQHOMEDATA_HANDLEGETDATAPOINTS_MAXTABLEENTRIES);
if (tablePtr) {
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
free(tablePtr);
@@ -156,9 +151,9 @@ int _getAndSendDataPointsPeriod(AQH_STORAGE *storage, AQH_OBJECT *ep,
int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
int _getAndSendDataPointsWithNum(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
@@ -180,30 +175,6 @@ int _getAndSendDataPointsLast(AQH_STORAGE *storage, AQH_OBJECT *ep,
int _getAndSendDataPointsFirst(AQH_STORAGE *storage, AQH_OBJECT *ep,
const AQH_VALUE *value, uint64_t num,
uint32_t refMsgId)
{
uint64_t valueId;
uint64_t *tablePtr;
if (num>AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS)
num=AQHOMEDATA_HANDLEGETDATAPOINTS_MAXDATAPOINTS;
valueId=AQH_Value_GetId(value);
tablePtr=AQH_Storage_GetFirstNDataPoints(storage, valueId, num);
if (tablePtr) {
_sendDataPointsResponse(ep, value, tablePtr, refMsgId);
free(tablePtr);
return AQH_MSGDATA_RESULT_SUCCESS;
}
else {
DBG_INFO(NULL, "No matching datapoints for value \"%s\"", AQH_Value_GetNameForSystem(value));
return AQH_MSGDATA_RESULT_ERROR_NODATA;
}
}
void _sendDataPointsResponse(AQH_OBJECT *ep,
const AQH_VALUE *value, const uint64_t *tablePtr,
uint32_t refMsgId)
@@ -222,3 +193,36 @@ 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), &timestamp, &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);
}
}

View File

@@ -13,16 +13,13 @@
#include "./s_getvalues.h"
#include "./server_p.h"
#include "aqhome/aqhome.h"
#include "aqhome/ipc2/endpoint.h"
#include "aqhome/msg/ipc/m_ipc.h"
#include "aqhome/msg/ipc/data/m_ipcd.h"
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
#include "aqhome/msg/ipc/data/m_ipcd_values.h"
#include "aqhome/msg/ipc/m_ipc_result.h"
#include "aqhome/msg/ipc/m_ipc_tag16.h"
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
@@ -41,10 +38,7 @@
* ------------------------------------------------------------------------------------------------
*/
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);
static void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId);
@@ -53,100 +47,64 @@ static int _valueMatches(const AQH_VALUE *v, const char *deviceName, int modalit
* ------------------------------------------------------------------------------------------------
*/
void AqHomeDataServer_HandleGetValues(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList)
void AqHomeDataServer_HandleGetValues(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESSAGE *msg, GWEN_UNUSED const GWEN_TAG16_LIST *tagList)
{
AQHOME_SERVER *xo;
xo=AqHomeDataServer_GetServerData(o);
if (xo) {
AQH_VALUE_LIST *valueList;
const AQH_VALUE_LIST *origValueList;
uint32_t refMsgId;
refMsgId=AQH_IpcMessage_GetMsgId(msg);
DBG_INFO(NULL, "HandleGetValues");
valueList=_getMatchingValueList(xo, tagList);
if (valueList) {
_sendValueList(ep, valueList, refMsgId);
AQH_Value_List_free(valueList);
origValueList=AQH_Storage_GetValueList(xo->storage);
if (origValueList) {
DBG_INFO(NULL, "Have a list of %d values", AQH_Value_List_GetCount(origValueList));
if (AQH_Value_List_GetCount(origValueList)<AQHOMEDATA_VALUESPERMSG) {
DBG_INFO(NULL, "Sending all entries in one message");
_sendValueList(ep, origValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
}
else {
AQH_VALUE_LIST *tmpValueList;
const AQH_VALUE *v;
DBG_INFO(NULL, "Sending entries in multiple messages");
tmpValueList=AQH_Value_List_new();
v=AQH_Value_List_First(origValueList);
while(v) {
const AQH_VALUE *next;
AQH_VALUE *copyOfValue;
next=AQH_Value_List_Next(v);
copyOfValue=AQH_Value_dup(v);
AQH_Value_List_Add(copyOfValue, tmpValueList);
if (AQH_Value_List_GetCount(tmpValueList)>=AQHOMEDATA_VALUESPERMSG) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueList(ep, tmpValueList, next?0:AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
AQH_Value_List_Clear(tmpValueList);
}
v=next;
}
if (AQH_Value_List_GetCount(tmpValueList)) {
DBG_INFO(NULL, "Sending %d values", AQH_Value_List_GetCount(tmpValueList));
_sendValueList(ep, tmpValueList, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId); /* send remaining */
}
AQH_Value_List_free(tmpValueList);
}
}
else {
/* empty list */
_sendValueListMsg(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, refMsgId);
_sendValueList(ep, NULL, AQH_MSGDATA_VALUES_FLAGS_LASTMSG, 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)
void _sendValueList(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags, uint32_t refMsgId)
{
AQH_MESSAGE *msg;
@@ -157,27 +115,3 @@ void _sendValueListMsg(AQH_OBJECT *ep, const AQH_VALUE_LIST *vl, uint32_t flags,
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;
}

View File

@@ -54,7 +54,7 @@ void AQH_NodeServer_HandleGetNodes(AQH_OBJECT *o, AQH_OBJECT *ep, const AQH_MESS
AQH_Endpoint_GetNextMessageId(ep), AQH_IpcMessage_GetMsgId(msg),
niNext?0:AQH_MSGNODE_GETDEVICES_RSP_FLAGS_LASTMSG, ni);
AQH_Endpoint_AddMsgOut(ep, outMsg);
DBG_DEBUG(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
DBG_ERROR(NULL, "Messages in clients out queue: %d", AQH_Message_List_GetCount(AQH_Endpoint_GetMsgOutList(ep)));
ni=niNext;
}
}

View File

@@ -41,7 +41,6 @@
#include <aqhome/msg/node/m_value.h>
#include <aqhome/msg/node/m_recvstats.h>
#include <aqhome/msg/node/m_sendstats.h>
#include <aqhome/msg/node/m_memstats.h>
#include <aqhome/data/value.h>
#include <gwenhywfar/args.h>
@@ -123,9 +122,7 @@ static void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH
static void _forwardValueMessageToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
static void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
static void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
static void _forwardDataFromMemStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
static void _forwardTtyMsgToClients(AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg);
static void _publishIntWithIdx(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int idx, int vModality, const char *vUnits, int v);
static void _publishInt(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, int v);
static void _publishDouble(AQH_NODE_SERVER *xo, uint32_t uid, const char *vPath, int vModality, const char *vUnits, double v);
static void _setDeviceName(AQH_VALUE *value, uint32_t uid);
@@ -830,11 +827,9 @@ void _forwardTtyMsgToBroker(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAG
code=AQH_NodeMessage_GetMsgType(msg);
switch(code) {
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
case AQH_MSG_TYPE_VALUE_REPORT: _forwardValueMessageToBroker(o, xo, msg); break;
case AQH_MSG_TYPE_COMSENDSTATS: _forwardDataFromSendStatsMsgToBroker(xo, msg); break;
case AQH_MSG_TYPE_COMRECVSTATS: _forwardDataFromRecvStatsMsgToBroker(xo, msg); break;
case AQH_MSG_TYPE_MEMSTATS: _forwardDataFromMemStatsMsgToBroker(xo, msg); break;
default: break;
}
}
@@ -903,21 +898,24 @@ void _forwardDataFromSendStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
packetsOutInt=AQH_SendStatsMessage_GetPacketsOut(msg);
if (packetsOutInt) {
uint32_t uid;
int devNum;
double packetsOut;
double collisions;
double busy;
double collisionsPercentage=0.0;
double busyPercentage=0.0;
uid=AQH_SendStatsMessage_GetUid(msg);
devNum=AQH_SendStatsMessage_GetInterface(msg);
packetsOut=/*(double)*/ packetsOutInt;
collisions=/*(double)*/ AQH_SendStatsMessage_GetCollisions(msg);
busy=/*(double)*/ AQH_SendStatsMessage_GetBusyErrors(msg);
if (devNum==0) {
_publishInt(xo, uid, "net/packetsOut", 0, NULL, packetsOutInt);
_publishInt(xo, uid, "net/collisions", 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
_publishInt(xo, uid, "net/busy", 0, NULL, (int) AQH_SendStatsMessage_GetBusyErrors(msg));
}
else {
_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));
}
collisionsPercentage=collisions*100.0/packetsOut;
busyPercentage=busy*100.0/packetsOut;
_publishInt( xo, uid, "net/packetsOut", 0, NULL, packetsOutInt);
_publishInt( xo, uid, "net/collisions", 0, NULL, (int) AQH_SendStatsMessage_GetCollisions(msg));
_publishDouble(xo, uid, "net/collisionsPercent", 0, "%", collisionsPercentage);
_publishDouble(xo, uid, "net/busyPercent", 0, "%", busyPercentage);
}
}
@@ -930,56 +928,30 @@ void _forwardDataFromRecvStatsMsgToBroker(AQH_NODE_SERVER *xo, const AQH_MESSAGE
packetsInInt=AQH_RecvStatsMessage_GetPacketsIn(msg);
if (packetsInInt) {
uint32_t uid;
int devNum;
double packetsIn;
double crcErrors;
double ioErrors;
double crcErrorsPercentage=0.0;
double ioErrorsPercentage=0.0;
uid=AQH_RecvStatsMessage_GetUid(msg);
devNum=AQH_RecvStatsMessage_GetInterface(msg);
uid=AQH_SendStatsMessage_GetUid(msg);
packetsIn=/*(double)*/ packetsInInt;
crcErrors=/*(double)*/AQH_RecvStatsMessage_GetCrcErrors(msg);
ioErrors=/*(double)*/AQH_RecvStatsMessage_GetIoErrors(msg);
if (devNum==0) {
_publishInt(xo, uid, "net/packetsIn", 0, NULL, packetsInInt);
_publishInt(xo, uid, "net/crcErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
_publishInt(xo, uid, "net/ioErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
_publishInt(xo, uid, "net/nobufferErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetNoBufferErrors(msg));
_publishInt(xo, uid, "net/msgSizeErrors", 0, NULL, (int) AQH_RecvStatsMessage_GetMsgSizeErrors(msg));
_publishInt(xo, uid, "net/missed", 0, NULL, (int) AQH_RecvStatsMessage_GetMissed(msg));
}
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));
}
crcErrorsPercentage=crcErrors*100.0/packetsIn;
ioErrorsPercentage=ioErrors*100.0/packetsIn;
_publishInt( xo, uid, "net/packetsIn", 0, NULL, packetsInInt);
_publishInt( xo, uid, "net/crcerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetCrcErrors(msg));
_publishInt( xo, uid, "net/ioerrors", 0, NULL, (int) AQH_RecvStatsMessage_GetIoErrors(msg));
_publishDouble(xo, uid, "net/crcerrorsPercent", 0, "%", crcErrorsPercentage);
_publishDouble(xo, uid, "net/ioerrorsPercent", 0, "%", ioErrorsPercentage);
}
}
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)
{
_publishDouble(xo, uid, vPath, vModality, vUnits, /*(double)*/ v);

View File

@@ -37,13 +37,9 @@
getdevices.h
adddata.h
getdatapoints.h
getfirstdata.h
getlastdata.h
getperioddata.h
setdata.h
moddevice.h
watch.h
devicestate.h
</headers>
<sources>
@@ -53,13 +49,9 @@
getdevices.c
adddata.c
getdatapoints.c
getfirstdata.c
getlastdata.c
getperioddata.c
setdata.c
moddevice.c
watch.c
devicestate.c
</sources>
<useTargets>

View File

@@ -1,265 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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);
}

View File

@@ -1,21 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -10,7 +10,7 @@
# include <config.h>
#endif
#include "./getdatapoints.h"
#include "./getvalues.h"
#include "../client.h"
#include "../utils.h"
@@ -52,6 +52,7 @@
static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId);
static int _handleResponseMessage(AQH_OBJECT *o, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, int first);
static void _handleDataResponse(const GWEN_TAG16_LIST *tagList, int printMean, int printDiff);
static uint64_t _getTimeStampFromString(const char *s);
@@ -109,23 +110,18 @@ AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
valueName=GWEN_DB_GetCharValue(dbArgs, "valueName", 0, NULL);
num=GWEN_DB_GetIntValue(dbArgs, "numOfLastDatapoints", 0, 0);
tsBegin=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
tsBegin=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsBegin", 0, NULL));
if (tsBegin==(uint64_t) (-1)) {
DBG_ERROR(NULL, "Bad begin timestamp");
return NULL;
}
tsEnd=Utils_GetTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
tsEnd=_getTimeStampFromString(GWEN_DB_GetCharValue(dbArgs, "tsEnd", 0, NULL));
if (tsEnd==(uint64_t) (-1)) {
DBG_ERROR(NULL, "Bad end timestamp");
return NULL;
}
// 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);
return AQH_IpcdMessageGetData_new(AQH_MSGTYPE_IPC_DATA_GETDATA_REQ, msgId, 0, valueName, tsBegin, tsEnd, num);
}
@@ -182,3 +178,45 @@ 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;
}

View File

@@ -1,153 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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;
}

View File

@@ -1,21 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -1,153 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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;
}

View File

@@ -1,21 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -1,167 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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;
}

View File

@@ -1,21 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -14,12 +14,10 @@
#include "../client.h"
#include "../utils.h"
#include "aqhome/aqhome.h"
#include "aqhome/msg/ipc/m_ipc.h"
#include "aqhome/msg/ipc/m_ipc_result.h"
#include "aqhome/msg/ipc/data/m_ipcd.h"
#include "aqhome/msg/ipc/data/m_ipcd_values.h"
#include "aqhome/msg/ipc/data/m_ipcd_getvalues.h"
#include <gwenhywfar/args.h>
#include <gwenhywfar/i18n.h>
@@ -69,8 +67,6 @@ int AQH_Tool_GetValues(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
{ A_ARG, A_INT, "timeout", 0, 1, "T", NULL, I18S("Specify timeout in seconds for response"), NULL},
{ A_ARG, A_CHAR, "brokerClientId", 0, 1, "c", "clientid", I18S("Specify CLIENTID"), NULL},
{ A_ARG, A_CHAR, "userId", 0, 1, "u", "userid", I18S("Specify user id"), NULL},
{ A_ARG, A_CHAR, "device", 0, 1, "d", "device", I18S("device name to match"), NULL},
{ A_ARG, A_CHAR, "modality", 0, 1, "m", NULL, I18S("Modality to match"), NULL},
{ A_ARG, A_CHAR, "password", 0, 1, "p", "password", I18S("Specify service password"), NULL},
{ 0, A_INT, "printHeader", 0, 1, "H", "printheader", I18S("Print header if given"), NULL},
{ A_END, A_INT, "help", 0, 0, "h", "help", I18S("Show this help screen"), NULL}
@@ -94,23 +90,11 @@ int AQH_Tool_GetValues(GWEN_DB_NODE *dbGlobalArgs, int argc, char **argv)
AQH_MESSAGE *_createRequestMessage(GWEN_UNUSED AQH_OBJECT *o, uint32_t msgId)
{
GWEN_DB_NODE *dbArgs;
const char *deviceName;
const char *s;
int modality;
dbArgs=AQH_ToolClient_GetDbLocalArgs(o);
deviceName=GWEN_DB_GetCharValue(dbArgs, "device", 0, NULL);
s=GWEN_DB_GetCharValue(dbArgs, "modality", 0, NULL);
if (s && *s) {
modality=AQH_ValueModality_fromString(s);
if (modality==AQH_ValueModality_Unknown) {
}
}
else
modality=AQH_ValueModality_Unknown;
return AQH_IpcdMessageGetValues_new(AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ, msgId, 0, deviceName, modality);
return AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID,
AQH_IPC_PROTOCOL_DATA_VERSION,
AQH_MSGTYPE_IPC_DATA_GETVALUES_REQ,
msgId, 0,
0, NULL);
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -17,13 +17,9 @@
#include "./data/getdevices.h"
#include "./data/adddata.h"
#include "./data/getdatapoints.h"
#include "./data/getfirstdata.h"
#include "./data/getlastdata.h"
#include "./data/getperioddata.h"
#include "./data/setdata.h"
#include "./data/moddevice.h"
#include "./data/watch.h"
#include "./data/devicestate.h"
#include <aqhome/api.h>
#include <aqhome/aqhome.h>
@@ -96,13 +92,9 @@ int main(int argc, char **argv)
GWEN_FE_DAH("adddata", AQH_Tool_AddDataPoint, I18N("Send a datapoint to the data server")),
GWEN_FE_DAH("addjsondata", AQH_Tool_AddDataPoint, I18N("(same as adddata)")),
GWEN_FE_DAH("getdata", AQH_Tool_GetDataPoints, I18N("Request list of datapoints for a value on the data server")),
GWEN_FE_DAH("getfirstdata", AQH_Tool_GetFirstData, I18N("Request first datapoints for a value on the data server")),
GWEN_FE_DAH("getlastdata", AQH_Tool_GetLastData, I18N("Request last datapoints for a value on the data server")),
GWEN_FE_DAH("getperioddata", AQH_Tool_GetPeriodData, I18N("Request datapoints from a date range for a value on the data server")),
GWEN_FE_DAH("setdata", AQH_Tool_SetData, I18N("Set data for a value on the data server (e.g. a switch or thermostat)")),
GWEN_FE_DAH("moddevice", AQH_Tool_ModDevice, I18N("Modify a device on the data server")),
GWEN_FE_DAH("watch", AQH_Tool_Watch, I18N("Watch and print changes of values on the data server")),
GWEN_FE_DAH("devicestate", AQH_Tool_DeviceState, I18N("Show state of devices")),
GWEN_FE_END(),
};
const GWEN_FUNCS *func;

View File

@@ -58,7 +58,6 @@ static AQH_MESSAGE *_createRequestMessage(AQH_OBJECT *o, uint32_t msgId);
static int _handleResponseMessage(AQH_OBJECT *o, const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList, int first);
static void _printNode(const AQH_NODE_INFO *ni, int printAll);
static void _printUintAsTextOrHex(uint32_t u, int bits);
static void _printDeviceIdAsTextOrHex(uint32_t u, int version);
@@ -164,7 +163,9 @@ void _printNode(const AQH_NODE_INFO *ni, int printAll)
_printUintAsTextOrHex(u, 32);
fprintf(stdout, ":");
u=AQH_NodeInfo_GetDeviceType(ni);
_printDeviceIdAsTextOrHex(u, AQH_NodeInfo_GetDeviceVersion(ni));
_printUintAsTextOrHex(u, 16);
u=AQH_NodeInfo_GetDeviceVersion(ni);
fprintf(stdout, " v%d.%d", (u>>8) & 0xff, u & 0xff);
u=AQH_NodeInfo_GetFirmwareVersion(ni);
fprintf(stdout, ", firmware=%d.%d.%d (%d), ",
(u>>16) & 0xff, (u>>8) & 0xff, u & 0xff, (u>>24) & 0xff);
@@ -188,36 +189,6 @@ void _printNode(const AQH_NODE_INFO *ni, int printAll)
void _printDeviceIdAsTextOrHex(uint32_t u, int version)
{
int i;
uint8_t d;
int hasNonPrintable=0;
int hasPrintable=0;
for (i=0; i<16; i+=8) {
d=((u>>i) & 0xff);
if (d==0) { /* undecided */
}
else if (isalnum(d))
hasPrintable=1;
else
hasNonPrintable=1;
}
if (hasNonPrintable || !hasPrintable)
fprintf(stdout, "%02x v%d.%d", u, (version>>8) & 0xff, version & 0xff);
else {
for (i=0; i<16; i+=8) {
d=((u>>i) & 0xff);
fprintf(stdout, "%c", d?d:' ');
}
fprintf(stdout, "%2d (%d)", (version>>8) & 0xff, version & 0xff);
}
}
void _printUintAsTextOrHex(uint32_t u, int bits)
{
int i;

View File

@@ -19,7 +19,6 @@
#include "aqhome/msg/ipc/nodes/m_ipcn_setaccmsggrps.h"
#include "aqhome/ipc2/tcp_object.h"
#include "aqhome/ipc2/ipc_client.h"
#include "aqhome/dataclient/client.h"
#include <gwenhywfar/debug.h>
@@ -28,7 +27,6 @@
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#define UTILS_IPC_ENDPOINT_DEFAULT_MSGSIZE 4096
@@ -363,47 +361,4 @@ 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;
}

View File

@@ -41,8 +41,6 @@ void Utils_PrintValue(const AQH_VALUE *value, int printHeader);
AQH_DEVICE *Utils_DeviceFromArgs(GWEN_DB_NODE *dbArgs);
uint64_t Utils_GetTimeStampFromString(const char *s);
#endif

View File

@@ -1,14 +0,0 @@
#!/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 "$@"

View File

@@ -69,7 +69,6 @@
hexfile
data
events2
dataclient
</subdirs>
@@ -80,7 +79,6 @@
aqhhexfile
aqhdata
aqhevents2
aqhdataclient
</useTargets>
<libraries>

View File

@@ -267,8 +267,6 @@ int AQH_ValueModality_fromString(const char *s)
return AQH_ValueModality_TVOC;
else if (strcasecmp(s, "stats")==0)
return AQH_ValueModality_Stats;
else if (strcasecmp(s, "light")==0)
return AQH_ValueModality_Light;
}
return AQH_ValueModality_Unknown;
}
@@ -287,7 +285,6 @@ const char *AQH_ValueModality_toString(int i)
case AQH_ValueModality_Co2: return "co2";
case AQH_ValueModality_TVOC: return "tvoc";
case AQH_ValueModality_Stats: return "stats";
case AQH_ValueModality_Light: return "light";
case AQH_ValueModality_Unknown:
default: return "unknown";
}

View File

@@ -45,8 +45,7 @@ enum {
AQH_ValueModality_Motion,
AQH_ValueModality_Co2,
AQH_ValueModality_TVOC,
AQH_ValueModality_Stats,
AQH_ValueModality_Light
AQH_ValueModality_Stats
};

View File

@@ -23,7 +23,7 @@
#define AQH_STORAGE_DATAPOINTS_STEPS 128
#define AQH_STORAGE_MAXOPENFILES 128
/* ------------------------------------------------------------------------------------------------
@@ -305,17 +305,6 @@ AQH_STORAGE_GETLASTDATAPOINT_FN AQH_Storage_SetGetLastDatapointFn(AQH_STORAGE *s
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN AQH_Storage_SetGetFirstNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTNDATAPOINTS_FN fn)
{
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN oldFn;
oldFn=sto->getFirstNDatapointsFn;
sto->getFirstNDatapointsFn=fn;
return oldFn;
}
AQH_STORAGE_GETLASTNDATAPOINTS_FN AQH_Storage_SetGetLastNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTNDATAPOINTS_FN fn)
{
AQH_STORAGE_GETLASTNDATAPOINTS_FN oldFn;
@@ -394,8 +383,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 maxDataPointsRequested)
uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t fromTime, uint64_t toTime, uint64_t maxArrayLen)
{
AQH_DATAFILE *df;
uint64_t numEntries;
@@ -410,9 +399,13 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
return NULL;
}
numEntries=AQH_DataFile_GetNumberOfEntries(df);
if (maxDataPointsRequested>numEntries)
maxDataPointsRequested=numEntries;
arrayLen=(maxDataPointsRequested*2)+1;
if (fromTime==0 && toTime==0)
arrayLen=(numEntries*2)+1;
else
arrayLen=(AQH_STORAGE_DATAPOINTS_STEPS*2)+1;
if (arrayLen>maxArrayLen+1)
arrayLen=maxArrayLen+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);
@@ -434,11 +427,30 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
}
if ((fromTime==0 || ts>=fromTime) && (toTime==0 || ts<=toTime)) {
if ((arrayPos+1)>arrayLen) {
if ((arrayPos+1)>maxArrayLen) {
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
break;
}
if (arrayPos+1>=arrayLen) {
uint64_t newArrayLen;
void *p;
newArrayLen=arrayLen+(AQH_STORAGE_DATAPOINTS_STEPS*2);
if (newArrayLen>maxArrayLen+1)
newArrayLen=maxArrayLen+1;
if (newArrayLen==arrayLen) {
DBG_INFO(AQH_LOGDOMAIN, "Limit for number of returned entries reached");
break;
}
p=realloc((void*) arrayPtr, newArrayLen*sizeof(uint64_t));
if (p==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen+AQH_STORAGE_DATAPOINTS_STEPS);
free(arrayPtr);
return NULL;
}
arrayPtr=(uint64_t*) p;
arrayLen=newArrayLen;
}
arrayPtr[arrayPos++]=ts;
arrayPtr[arrayPos++]=u.i;
}
@@ -456,67 +468,6 @@ uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t
uint64_t *AQH_Storage_GetFirstNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested)
{
AQH_DATAFILE *df;
uint64_t numEntries;
uint64_t numOfDataEntries;
uint64_t arrayLen;
uint64_t arrayPos;
uint64_t *arrayPtr;
uint64_t firstRecord;
uint64_t i;
df=_getDataFileByValueId(sto, valueId);
if (df==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "No file for value id %lu", (unsigned long int) valueId);
return NULL;
}
numEntries=AQH_DataFile_GetNumberOfEntries(df);
numOfDataEntries=numEntries-1; /* first entry is reserved, don't count it here */
if (numOfDataEntries<1) {
DBG_INFO(AQH_LOGDOMAIN, "No data records for value id %lu", (unsigned long int) valueId);
return NULL;
}
firstRecord=1;
if (numOfDataEntries>maxDataPointsRequested) /* more entries in file than requested */
arrayLen=(maxDataPointsRequested*2)+1; /* +1 because the first array entry contains the number of entries */
else
arrayLen=(numOfDataEntries*2)+1;
arrayPtr=(uint64_t*) malloc(arrayLen*sizeof(uint64_t));
if (arrayPtr==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not enough memory for %lu entries", (unsigned long int) arrayLen);
return NULL;
}
arrayPos=1;
for (i=firstRecord; i<numEntries; i++) {
union {double f; uint64_t i;} u;
uint64_t ts;
int rv;
rv=AQH_DataFile_ReadRecord(df, i, &ts, &(u.f));
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
free(arrayPtr);
return NULL;
}
if ((arrayPos+1)>=arrayLen) {
DBG_INFO(AQH_LOGDOMAIN, "Requested number of entries reached");
break;
}
arrayPtr[arrayPos++]=ts;
arrayPtr[arrayPos++]=u.i;
} /* for */
arrayPtr[0]=arrayPos-1;
return arrayPtr;
}
uint64_t *AQH_Storage_GetLastNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested)
{
AQH_DATAFILE *df;
@@ -650,16 +601,6 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
DBG_ERROR(AQH_LOGDOMAIN, "Error opening/creating datafile for valueId \"%lu\"", (unsigned long int) valueId);
return NULL;
}
if (AQH_DataFile_List_GetCount(sto->dataFileList)>=AQH_STORAGE_MAXOPENFILES) {
AQH_DATAFILE *dfLast;
dfLast=AQH_DataFile_List_Last(sto->dataFileList);
if (dfLast) {
AQH_DataFile_Close(dfLast);
AQH_DataFile_List_Del(dfLast);
AQH_DataFile_free(dfLast);
}
}
DBG_DEBUG(AQH_LOGDOMAIN, "Adding datafile for valueId \"%lu\" to list", (unsigned long int) valueId);
AQH_DataFile_List_Add(df, sto->dataFileList);
}
@@ -671,17 +612,8 @@ AQH_DATAFILE *_getDataFileByValueId(AQH_STORAGE *sto, uint64_t valueId)
AQH_DATAFILE *_findDataFileByValueId(const AQH_STORAGE *sto, uint64_t valueId)
{
if (sto && sto->dataFileList) {
AQH_DATAFILE *df;
df=AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
if (df) {
/* move to front of list */
AQH_DataFile_List_Del(df);
AQH_DataFile_List_Insert(df, sto->dataFileList);
return df;
}
}
if (sto && sto->dataFileList)
return AQH_DataFile_List_GetByValueId(sto->dataFileList, valueId);
return NULL;
}

View File

@@ -53,8 +53,6 @@ typedef uint64_t *(*AQH_STORAGE_GETDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t val
uint64_t maxArrayLen);
typedef int (*AQH_STORAGE_GETFIRSTDATAPOINT_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
typedef int (*AQH_STORAGE_GETLASTDATAPOINT_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
typedef uint64_t *(*AQH_STORAGE_GETFIRSTNDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
typedef uint64_t *(*AQH_STORAGE_GETLASTNDATAPOINTS_FN)(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
@@ -98,8 +96,6 @@ AQHOME_API uint64_t *AQH_Storage_GetDataPoints(AQH_STORAGE *sto, uint64_t valueI
uint64_t maxArrayLen);
AQHOME_API int AQH_Storage_GetFirstDataPoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
AQHOME_API int AQH_Storage_GetLastDataPoint(AQH_STORAGE *sto, uint64_t valueId, uint64_t *pTimestamp, double *pValue);
AQHOME_API uint64_t *AQH_Storage_GetFirstNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
AQHOME_API uint64_t *AQH_Storage_GetLastNDataPoints(AQH_STORAGE *sto, uint64_t valueId, uint64_t maxDataPointsRequested);
@@ -109,8 +105,6 @@ AQHOME_API AQH_STORAGE_ADDDATAPOINT_FN AQH_Storage_SetAddDatapointFn(AQH_STORAGE
AQHOME_API AQH_STORAGE_GETDATAPOINTS_FN AQH_Storage_SetGetDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETDATAPOINTS_FN fn);
AQHOME_API AQH_STORAGE_GETFIRSTDATAPOINT_FN AQH_Storage_SetGetFirstDatapointFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTDATAPOINT_FN fn);
AQHOME_API AQH_STORAGE_GETLASTDATAPOINT_FN AQH_Storage_SetGetLastDatapointFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTDATAPOINT_FN fn);
AQHOME_API AQH_STORAGE_GETFIRSTNDATAPOINTS_FN AQH_Storage_SetGetFirstNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETFIRSTNDATAPOINTS_FN fn);
AQHOME_API AQH_STORAGE_GETLASTNDATAPOINTS_FN AQH_Storage_SetGetLastNDatapointsFn(AQH_STORAGE *sto, AQH_STORAGE_GETLASTNDATAPOINTS_FN fn);

View File

@@ -47,7 +47,6 @@ struct AQH_STORAGE {
AQH_STORAGE_GETFIRSTDATAPOINT_FN getFirstDatapointFn;
AQH_STORAGE_GETLASTDATAPOINT_FN getLastDatapointFn;
AQH_STORAGE_GETLASTNDATAPOINTS_FN getLastNDatapointsFn;
AQH_STORAGE_GETFIRSTNDATAPOINTS_FN getFirstNDatapointsFn;
};

View File

@@ -1,81 +0,0 @@
<?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>

View File

@@ -1,555 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "./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;
}

View File

@@ -1,57 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -1,32 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQHOME_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

View File

@@ -14,7 +14,6 @@
#include <gwenhywfar/inherit.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
//#include <sys/socket.h>
#include <errno.h>
@@ -171,7 +170,6 @@ int AQH_FdObject_Read(AQH_OBJECT *o, uint8_t *ptrBuffer, uint32_t lenBuffer)
else if (rv>0) {
/* data received */
DBG_DEBUG(AQH_LOGDOMAIN, "Received %d bytes", (int) rv);
// GWEN_Text_LogString((const char*) ptrBuffer, rv, NULL, GWEN_LoggerLevel_Error);
return (int) rv;
}
else {

View File

@@ -79,7 +79,7 @@ AQH_MESSAGE *AQH_IpcEndpoint_WaitForResponseMsg(AQH_OBJECT *ipcEndpoint, uint32_
uint16_t code;
code=AQH_IpcMessage_GetCode(msg);
DBG_DEBUG(NULL, "Received unexpected message %d (%x), ignoring", code, code);
DBG_ERROR(NULL, "Received unexpected message %d (%x), ignoring", code, code);
AQH_Message_free(msg);
}
}

View File

@@ -24,7 +24,7 @@
#define AQH_MSG_READER_HEADER_SIZE 4
#define AQH_MSG_READER_MINMSGSIZE 12
#define AQH_MSG_READER_MAXMSGSIZE 20480
#define AQH_MSG_READER_MAXMSGSIZE 10240

View File

@@ -176,17 +176,17 @@ int _handleSocketReady(AQH_OBJECT *o)
{
AQH_TCPD_OBJECT *xo;
DBG_DEBUG(NULL, "Socket ready");
DBG_INFO(NULL, "Socket ready");
xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_TCPD_OBJECT, o);
if (xo) {
int clientSk;
clientSk=_acceptConnection(xo->fdSocket);
if (clientSk<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", clientSk);
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", clientSk);
}
else {
DBG_NOTICE(AQH_LOGDOMAIN, "New connection");
DBG_INFO(AQH_LOGDOMAIN, "New connection");
if (0==AQH_Object_EmitSignal(o, AQH_TCPD_OBJECT_SIGNAL_NEWCONN, clientSk, NULL)) {
DBG_ERROR(AQH_LOGDOMAIN, "New connection not handled");
close(clientSk);

View File

@@ -51,7 +51,6 @@
m_ipcd_values.h
m_ipcd_getdata.h
m_ipcd_setdata.h
m_ipcd_getvalues.h
</headers>
@@ -68,7 +67,6 @@
m_ipcd_values.c
m_ipcd_getdata.c
m_ipcd_setdata.c
m_ipcd_getvalues.c
</sources>

View File

@@ -28,8 +28,6 @@
* ------------------------------------------------------------------------------------------------
*/
static const char *_modeToChar(int mode);
/* ------------------------------------------------------------------------------------------------
@@ -39,7 +37,6 @@ static const char *_modeToChar(int mode);
AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
uint32_t msgId, uint32_t refMsgId,
int mode,
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num)
{
AQH_MESSAGE *msg;
@@ -52,7 +49,6 @@ AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_BEGIN, tsBegin, buf);
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_END, tsEnd, buf);
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_NUM, num, buf);
GWEN_Tag16_WriteUint64TagToBuffer(AQH_MSGDATA_GETDATA_TAGS_MODE, mode, buf);
msg=AQH_IpcMessage_new(AQH_IPC_PROTOCOL_DATA_ID, AQH_IPC_PROTOCOL_DATA_VERSION, code, msgId, refMsgId,
GWEN_Buffer_GetUsedBytes(buf), (const uint8_t*) GWEN_Buffer_GetStart(buf));
@@ -68,22 +64,19 @@ void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG1
char *valueName;
uint64_t tsBegin;
uint64_t tsEnd;
uint64_t mode;
valueName=tagList?AQH_Tag16_GetTagDataAsNewString(tagList, AQH_MSGDATA_GETDATA_TAGS_NAME, NULL):NULL;
tsBegin=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_BEGIN, 0):0;
tsEnd=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_END, 0):0;
mode=tagList?AQH_Tag16_GetTagDataAsUint64(tagList, AQH_MSGDATA_GETDATA_TAGS_MODE, 0):0;
GWEN_Buffer_AppendArgs(dbuf,
"GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, mode=%s, tsBegin=%lu, tsEnd=%lu)\n",
"GETDATA(%s) %s (code=%d, proto=%d, proto version=%d, name=%s, tsBegin=%lu, tsEnd=%lu)\n",
AQH_IpcdMessage_MsgTypeToChar(AQH_IpcMessage_GetCode(msg)),
sText?sText:"",
AQH_IpcMessage_GetCode(msg),
AQH_IpcMessage_GetProtoId(msg),
AQH_IpcMessage_GetProtoVersion(msg),
valueName?valueName:"<empty>",
_modeToChar(mode),
valueName?valueName:"<empty>",
(unsigned long int) tsBegin,
(unsigned long int) tsEnd);
free(valueName);
@@ -92,15 +85,3 @@ 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";
}
}

View File

@@ -24,20 +24,10 @@
#define AQH_MSGDATA_GETDATA_TAGS_BEGIN 0x0020
#define AQH_MSGDATA_GETDATA_TAGS_END 0x0021
#define AQH_MSGDATA_GETDATA_TAGS_NUM 0x0022
#define AQH_MSGDATA_GETDATA_TAGS_MODE 0x0023
enum {
AQH_MSGDATA_GETDATA_MODE_FIRST=0,
AQH_MSGDATA_GETDATA_MODE_LAST,
AQH_MSGDATA_GETDATA_MODE_PERIOD
};
AQHOME_API AQH_MESSAGE *AQH_IpcdMessageGetData_new(uint16_t code,
uint32_t msgId, uint32_t refMsgId,
int mode,
const char *valueName, uint64_t tsBegin, uint64_t tsEnd, uint64_t num);
AQHOME_API void AQH_IpcdMessageGetData_DumpToBuffer(const AQH_MESSAGE *msg, const GWEN_TAG16_LIST *tagList,

View File

@@ -1,81 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "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);
}

View File

@@ -1,36 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef 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

View File

@@ -62,7 +62,6 @@
m_flashend.h
m_flashready.h
m_flashresponse.h
m_range.h
</headers>
@@ -90,7 +89,6 @@
m_flashend.c
m_flashready.c
m_flashresponse.c
m_range.c
</sources>

View File

@@ -19,8 +19,8 @@
#define AQH_MSG_OFFS_MEMSTATS_UID 0 /* 4 bytes */
#define AQH_MSG_OFFS_MEMSTATS_SECONDS 4 /* 4 bytes */
#define AQH_MSG_OFFS_MEMSTATS_SECONDS 0 /* 4 bytes */
#define AQH_MSG_OFFS_MEMSTATS_UID 4 /* 4 bytes */
#define AQH_MSG_OFFS_MEMSTATS_STACKUSAGE 8 /* 2 bytes */
#define AQH_MSG_OFFS_MEMSTATS_BUFFERSUSED 10 /* 1 byte */
#define AQH_MSG_OFFS_MEMSTATS_MAXBUFFERSUSED 11 /* 1 byte */

View File

@@ -28,7 +28,6 @@
#include "aqhome/msg/node/m_flashend.h"
#include "aqhome/msg/node/m_flashready.h"
#include "aqhome/msg/node/m_flashresponse.h"
#include "aqhome/msg/node/m_range.h"
#include <gwenhywfar/text.h>
@@ -213,7 +212,6 @@ const char *AQH_NodeMessage_MsgTypeToChar(uint8_t i)
case AQH_MSG_TYPE_CLAIM_ADDRESS: return "ClaimAddress";
case AQH_MSG_TYPE_DENY_ADDRESS: return "DenyAddress";
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_END: return "FlashEnd";
@@ -248,8 +246,6 @@ 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_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_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_END: AQH_FlashEndMessage_DumpToBuffer(msg, dbuf, sText); break;
@@ -270,6 +266,7 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d
case AQH_MSG_TYPE_DEBUG:
case AQH_MSG_TYPE_TWIBUSMEMBER:
case AQH_MSG_TYPE_ADDRESS_RANGE:
default: AQH_NodeMessage_DumpToBuffer(msg, dbuf, sText); break;
}
}

View File

@@ -29,8 +29,8 @@
#define AQH_MSG_TYPE_PING 10
#define AQH_MSG_TYPE_PONG 11
#define AQH_MSG_TYPE_COMSENDSTATS 22
#define AQH_MSG_TYPE_COMRECVSTATS 23
#define AQH_MSG_TYPE_COMSENDSTATS 20
#define AQH_MSG_TYPE_COMRECVSTATS 21
#define AQH_MSG_TYPE_TWIBUSMEMBER 30
#define AQH_MSG_TYPE_DEBUG 40
#define AQH_MSG_TYPE_VALUE 50 /* deprecated */
@@ -40,7 +40,6 @@
#define AQH_MSG_TYPE_CLAIM_ADDRESS 62
#define AQH_MSG_TYPE_DENY_ADDRESS 63
#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_END 71

View File

@@ -1,61 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "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));
}

View File

@@ -1,30 +0,0 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef 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

View File

@@ -18,21 +18,13 @@
#include <gwenhywfar/debug.h>
#define AQH_MSG_OFFS_RECVSTATS_UID 0 /* 4 bytes */
#define AQH_MSG_OFFS_RECVSTATS_IFACE 4 /* 1 byte */
#define AQH_MSG_OFFS_RECVSTATS_PACKETSIN 5 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_CRCERRORS 7 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_IOERRORS 9 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_NOBUFFER 11 /* 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);
}
#define AQH_MSG_OFFS_RECVSTATS_UID 0 /* 4 bytes */
#define AQH_MSG_OFFS_RECVSTATS_PACKETSIN 4 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_CRCERRORS 6 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_IOERRORS 8 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_NOBUFFER 10 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_HANDLED 12 /* 2 bytes */
#define AQH_MSG_OFFS_RECVSTATS_MISSED 14 /* 2 bytes */
@@ -71,9 +63,9 @@ uint16_t AQH_RecvStatsMessage_GetNoBufferErrors(const AQH_MESSAGE *msg)
uint16_t AQH_RecvStatsMessage_GetMsgSizeErrors(const AQH_MESSAGE *msg)
uint16_t AQH_RecvStatsMessage_GetHandled(const AQH_MESSAGE *msg)
{
return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RECVSTATS_MSGSIZEERRORS, 0);
return AQH_Message_ReadUint16At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RECVSTATS_HANDLED, 0);
}
@@ -88,18 +80,17 @@ uint16_t AQH_RecvStatsMessage_GetMissed(const AQH_MESSAGE *msg)
void AQH_RecvStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText)
{
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: RECVSTATS %s"
"(uid=0x%08x, dev=%d, in=%d, eCrc=%d, eIo=%d, eNobuf=%d, eMsgSize=%d, eMissed=%d)\n",
"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",
AQH_NodeMessage_GetSourceAddress(msg),
AQH_NodeMessage_GetDestAddress(msg),
sText,
(unsigned int) AQH_RecvStatsMessage_GetUid(msg),
AQH_RecvStatsMessage_GetInterface(msg),
AQH_RecvStatsMessage_GetPacketsIn(msg),
AQH_RecvStatsMessage_GetCrcErrors(msg),
AQH_RecvStatsMessage_GetIoErrors(msg),
AQH_RecvStatsMessage_GetNoBufferErrors(msg),
AQH_RecvStatsMessage_GetMsgSizeErrors(msg),
AQH_RecvStatsMessage_GetHandled(msg),
AQH_RecvStatsMessage_GetMissed(msg));
}

View File

@@ -17,13 +17,12 @@
AQHOME_API uint8_t AQH_RecvStatsMessage_GetInterface(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_GetCrcErrors(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_GetMsgSizeErrors(const AQH_MESSAGE *msg);
AQHOME_API uint16_t AQH_RecvStatsMessage_GetHandled(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);

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqHome.
* AqHome (c) by 2025 Martin Preuss, all rights reserved.
* AqHome (c) by 2023 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.
@@ -19,17 +19,9 @@
#define AQH_MSG_OFFS_SENDSTATS_UID 0 /* 4 bytes */
#define AQH_MSG_OFFS_SENDSTATS_IFACE 4 /* 1 byte */
#define AQH_MSG_OFFS_SENDSTATS_PACKETSOUT 5 /* 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);
}
#define AQH_MSG_OFFS_SENDSTATS_PACKETSOUT 4 /* 2 bytes */
#define AQH_MSG_OFFS_SENDSTATS_COLLISIONS 6 /* 2 bytes */
#define AQH_MSG_OFFS_SENDSTATS_BUSY 8 /* 2 bytes */
@@ -65,12 +57,11 @@ void AQH_SendStatsMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf
{
if (msg)
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: SENDSTATS %s (uid=0x%08x, dev=%d, out=%d, collisions=%d, busy line=%d)\n",
"0x%02x->0x%02x: SENDSTATS %s (uid=0x%08x, out=%d, collisions=%d, busy line=%d)\n",
AQH_NodeMessage_GetSourceAddress(msg),
AQH_NodeMessage_GetDestAddress(msg),
sText,
(unsigned int) AQH_SendStatsMessage_GetUid(msg),
AQH_SendStatsMessage_GetInterface(msg),
AQH_SendStatsMessage_GetPacketsOut(msg),
AQH_SendStatsMessage_GetCollisions(msg),
AQH_SendStatsMessage_GetBusyErrors(msg));

View File

@@ -17,7 +17,6 @@
AQHOME_API uint8_t AQH_SendStatsMessage_GetInterface(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_GetCollisions(const AQH_MESSAGE *msg);

View File

@@ -12,7 +12,6 @@
#include "aqhome/aqhome.h"
#include "aqhome/msg/node/m_value.h"
#include "aqhome/msg/node/m_node.h"
@@ -103,7 +102,19 @@ uint16_t AQH_ValueMessage_GetValueDenom(const AQH_MESSAGE *msg)
const char *AQH_ValueMessage_GetValueTypeName(const AQH_MESSAGE *msg)
{
return AQH_ValueModality_toString(AQH_ValueMessage_GetValueType(msg));
uint8_t t;
t=AQH_ValueMessage_GetValueType(msg);
switch(t) {
case AQH_MSG_VALUE_TYPE_TEMP: return "temperature";
case AQH_MSG_VALUE_TYPE_HUMIDITY: return "humidity";
case AQH_MSG_VALUE_TYPE_DOOR: return "door_window";
case AQH_MSG_VALUE_TYPE_MOTION: return "motion";
case AQH_MSG_VALUE_TYPE_CO2: return "CO2";
case AQH_MSG_VALUE_TYPE_TVOC: return "TVOC";
default: break;
}
return "unknown";
}

View File

@@ -9,9 +9,6 @@
network
reportsensors
stats
router
hub
forwarder
</subdirs>
<extradist>

View File

@@ -1,15 +0,0 @@
<?xml?>
<gwbuild>
<subdirs>
</subdirs>
<extradist>
main.asm
</extradist>
</gwbuild>

View File

@@ -1,359 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -1,15 +0,0 @@
<?xml?>
<gwbuild>
<subdirs>
</subdirs>
<extradist>
main.asm
</extradist>
</gwbuild>

View File

@@ -1,715 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -100,56 +100,29 @@ 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
;
; @param X pointer to received message
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
ld r16, X
sbiw xh:xl, NETMSG_OFFS_CMD
cpi r16, NETMSG_CMD_REBOOT_REQUEST
breq AppNetwork_HandleMsg_handleRebootMsg
cpi r16, NETMSG_CMD_PING
breq AppNetwork_HandleMsg_handlePingMsg
cpi r16, NETMSG_CMD_REENUM
breq AppNetwork_HandleMsg_handleReenumMsg
cpi r16, NETMSG_CMD_NEED_ADDRESS
brcs AppNetwork_HandleMsg_clcRet ; lower than "HAVE_NEED"
cpi r16, NETMSG_CMD_ADDRESS_RANGE
breq AppNetwork_HandleMsg_handleRangeMsg
brcc AppNetwork_HandleMsg_clcRet ; higher or equal to "ADDR_RANGE"
rjmp AppNetwork_HandleMsg_handleAddrMsg
AppNetwork_HandleMsg_handleReenumMsg:
rjmp appNetworkHandleReeunumRequest
AppNetwork_HandleMsg_handleRangeMsg:
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
; TODO
rjmp AppNetwork_HandleMsg_clcRet
AppNetwork_HandleMsg_handleAddrMsg:
bigcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19)
mov r16, r18
subi r16, NETMSG_CMD_NEED_ADDRESS
ldi zl, LOW(appNetworkMsgTable)
@@ -159,13 +132,14 @@ AppNetwork_HandleMsg_handleAddrMsg:
sub zh, r16
ijmp
AppNetwork_HandleMsg_handleRebootMsg:
rcall appNetworkHandleRebootRequest
push xl
push xh
rcall appNetworkHandleRebootRequest
pop xh
pop xl
ret
AppNetwork_HandleMsg_handlePingMsg:
rjmp appNetworkHandlePingRequest
AppNetwork_HandleMsg_clcRet:
clc
AppNetwork_HandleMsg_end:
ret
; @end
@@ -178,66 +152,16 @@ AppNetwork_HandleMsg_end:
appNetworkHandleRebootRequest:
rcall NETMSG_RebootRequestRead
brcc appNetworkHandleRebootRequest_end ; uid doesn't match
brcc appNetworkHandleRebootRequest_end
; reboot
cli
bigjmp BOOTLOADER_ADDR
rjmp BOOTLOADER_ADDR
appNetworkHandleRebootRequest_end:
ret
; @end
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
ld r17, X
push r17
bigcall NET_Buffer_Alloc ; (R16, R17, X)
pop r17
brcc appNetworkHandlePingRequest_end ; jmp on error
push r16 ; buffer num
mov r16, r17 ; DEST addr
adiw xh:xl, 1
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
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)
appNetworkHandlePingRequest_end:
ret
appNetworkHandleReeunumRequest:
push xl
push xh
bigcall 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:
rjmp appNetworkHandleStateInitialWait
@@ -285,11 +209,20 @@ appNetworkHandleStateHaveAddress2:
std Y+NET_IFACE_OFFS_STATUS, r16
ldi r16, APP_NETWORK_TIMER_100MS
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
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
bigcall Eeprom_WriteByteIfChanged ; write address to EEPROM (R17)
std Y+NET_IFACE_OFFS_ADDRESS, r16
push r15
in r15, SREG
cli
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
rcall Utils_WriteEepromIncr ; write address to EEPROM
out SREG, r15
pop r15
appNetworkHandleStateHaveAddress2_end:
ret
@@ -300,6 +233,7 @@ appNetworkHandleStateUp:
ret
; ---------------------------------------------------------------------------
; @routine appNetworkSendMsgNextState
;
@@ -307,7 +241,7 @@ appNetworkHandleStateUp:
; @clobbers R16, R19 (R17, R18, R20, R21, X)
appNetworkSendMsgNextState:
ldd r19, Y+NET_IFACE_OFFS_ADDRESS
ldd r19, Y+NET_IFACE_OFFS_RANGE_BEGIN
rcall appNetworkSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X)
brcc appNetworkSendMsgNextState_retry
ldd r16, Y+NET_IFACE_OFFS_STATUS
@@ -372,9 +306,9 @@ appNetworkHandleMsgClaimAddr:
cp r19, r16
brne appNetworkHandleMsgClaimAddr_end ; not our address
ldd r16, Y+NET_IFACE_OFFS_STATUS
cpi r16, APP_NETWORK_STATE_CLAIMADDRESS1
brcs appNetworkHandleMsgClaimAddr_end ; nope, ignore
; network is somewhat up, someone claimed our address, deny it
cpi r16, APP_NETWORK_STATE_UP ; up?
brne appNetworkHandleMsgClaimAddr_end ; nope, ignore
; network is up, someone claimed our address, deny it
ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny our addr
ldd r19, Y+NET_IFACE_OFFS_ADDRESS
rjmp appNetworkSendAddrMsg
@@ -396,12 +330,12 @@ appNetworkHandleMsgDenyAddr:
cpi r16, APP_NETWORK_STATE_UP
breq appNetworkHandleMsgDenyAddr_end ; ignore (our network stack is up)
; still setting up address, check whether the last one is denied now
ldd r16, Y+NET_IFACE_OFFS_ADDRESS
ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN
cp r19, r16 ; our claimed address?
brne appNetworkHandleMsgDenyAddr_end ; nope, jump
; try next address (if any left)
ldd r17, Y+NET_IFACE_OFFS_RANGE_END
inc r16 ; next address
inc r16 ; RANGE_BEGIN+1
cp r17, r16 ; smaller than or equal to RANGE_END?
brcc appNetworkHandleMsgDenyAddr_claimNext
; out of addresses, start completely new after some waiting time
@@ -411,7 +345,7 @@ appNetworkHandleMsgDenyAddr:
rjmp appNetworkHandleMsgDenyAddr_end
appNetworkHandleMsgDenyAddr_claimNext:
; send CLAIM_ADDR for next address (new state: APP_NETWORK_STATE_NEEDADDRESS+1)
std Y+NET_IFACE_OFFS_ADDRESS, r16
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16
ldi r16, APP_NETWORK_STATE_NEEDADDRESS
std Y+NET_IFACE_OFFS_STATUS, r16
ldi r18, NETMSG_CMD_CLAIM_ADDRESS
@@ -431,16 +365,16 @@ appNetworkHandleMsgDenyAddr_end:
; @clobbers R16 (R17, R18, R19, R20, R21, X)
appNetworkSendAddrMsg:
bigcall NET_Buffer_Alloc ; (R16, R17, X)
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcc appNetworkSendAddrMsg_end
adiw xh:xl, 1
push r16
bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
rcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21)
pop r16
sbiw xh:xl, 1
bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
rcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X)
brcs appNetworkSendAddrMsg_end
bigcall NET_Buffer_ReleaseByNum ; (R16, X)
rcall NET_Buffer_ReleaseByNum ; (R16, X)
clc
appNetworkSendAddrMsg_end:
ret
@@ -462,7 +396,6 @@ appNetworkResetState:
std Y+NET_IFACE_OFFS_STATETIMER, r16
ldi r16, APP_NETWORK_ADDRESS_RANGE_BEGIN
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16
std Y+NET_IFACE_OFFS_ADDRESS, r16
rcall appNetworkGetAddressFromEeprom ; R16=addr (R15, X)
tst r16
breq appNetworkResetState_setRangeEnd
@@ -490,7 +423,7 @@ appNetworkGetAddressFromEeprom:
cli
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
bigcall Utils_ReadEepromIncr ; (R16)
rcall Utils_ReadEepromIncr ; (R16)
out SREG, r15
pop r15
ret

View File

@@ -18,20 +18,14 @@
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendTxdStats:
bigcall NET_Buffer_Alloc ; (R16, R17, X)
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcc AppNetwork_SendTxdStats_end
push r16
adiw xh:xl, 1
bigcall NETMSG_SendStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
rcall NETMSG_SendStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
sbiw xh:xl, 1
pop r16
push yl
push yh
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
pop yh
pop yl
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendTxdStats_end:
ret
; @end
@@ -41,24 +35,18 @@ AppNetwork_SendTxdStats_end:
; ---------------------------------------------------------------------------
; @routine AppNetwork_SendRxdStats
; @param Y network interface whose stats to send
; @param Y network interface to work with
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendRxdStats:
bigcall NET_Buffer_Alloc ; (R16, R17, X)
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcc AppNetwork_SendRxdStats_end
push r16
adiw xh:xl, 1
bigcall NETMSG_RecvStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
rcall NETMSG_RecvStats_Write ; (R16, R17, R18, R19, R20, R21, Z)
sbiw xh:xl, 1
pop r16
push yl
push yh
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
pop yh
pop yl
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendRxdStats_end:
ret
; @end
@@ -66,25 +54,20 @@ AppNetwork_SendRxdStats_end:
; ---------------------------------------------------------------------------
; @routine AppNetwork_SendMemStats
; @routine AppNetwork_SendRxdStats
; @param Y network interface to work with
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendMemStats:
bigcall NET_Buffer_Alloc ; (R16, R17, X)
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcc AppNetwork_SendMemStats_end
push r16
adiw xh:xl, 1
bigcall NETMSG_MemStats_Write ; (R16, R17, R18, R19, R20, R21)
rcall NETMSG_MemStats_Write ; (R16, R17, R18, R19, R20, R21)
sbiw xh:xl, 1
pop r16
push yl
push yh
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
pop yh
pop yl
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendMemStats_end:
ret
; @end
@@ -98,14 +81,14 @@ AppNetwork_SendMemStats_end:
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendDevice:
bigcall NET_Buffer_Alloc ; (R16, R17, X)
rcall NET_Buffer_Alloc ; (R16, R17, X)
brcc AppNetwork_SendDevice_end
push r16
adiw xh:xl, 1
bigcall NETMSG_Device_Write ; (R16, R17, R18, R19, R20, R21, Z)
rcall NETMSG_Device_Write ; (R16, R17, R18, R19, R20, R21, Z)
sbiw xh:xl, 1
pop r16
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendDevice_end:
ret
; @end

View File

@@ -11,7 +11,7 @@
; ***************************************************************************
; defines
.equ APP_REPORT_SENSORS_INTERVAL_SECS = 120
.equ APP_REPORT_SENSORS_INTERVAL_SECS = 60
@@ -78,45 +78,35 @@ AppReportSensors_OnEverySecond_store:
#ifdef MODULES_SI7021
cpi r16, 1
breq AppReportSensors_OnEverySecond_measureValue1
cpi r16, 11
cpi r16, 19
breq AppReportSensors_OnEverySecond_measureValue2
cpi r16, 16
cpi r16, 39
breq AppReportSensors_OnEverySecond_sendValue1
cpi r16, 21
cpi r16, 49
breq AppReportSensors_OnEverySecond_sendValue2
#endif
#ifdef MODULES_SGP40
cpi r16, 32
cpi r16, 27
breq AppReportSensors_OnEverySecond_measureValue4
cpi r16, 42
cpi r16, 55
breq AppReportSensors_OnEverySecond_sendValue4
#endif
#ifdef MODULES_SGP30
cpi r16, 53
cpi r16, 29
breq AppReportSensors_OnEverySecond_measureValue5
cpi r16, 57
breq AppReportSensors_OnEverySecond_sendValue5
cpi r16, 63
cpi r16, 59
breq AppReportSensors_OnEverySecond_sendValue6
#endif
#ifdef MODULES_DS18B20
cpi r16, 84
cpi r16, 9
breq AppReportSensors_OnEverySecond_sendValue3
#endif
#ifdef MODULES_CCS811
cpi r16, 94
breq AppReportSensors_OnEverySecond_sendCCS811_TVOC
cpi r16, 104
breq AppReportSensors_OnEverySecond_sendCCS811_CO2
#endif
#ifdef MODULES_BRIGHTNESS
cpi r16, 97
breq AppReportSensors_OnEverySecond_sendBrightness
#endif
ret
#ifdef MODULES_SI7021
@@ -143,23 +133,13 @@ AppReportSensors_OnEverySecond_sendValue3:
#endif
#ifdef MODULES_SGP30
AppReportSensors_OnEverySecond_sendValue5:
rjmp SGP30_SendTVOC
ret
AppReportSensors_OnEverySecond_sendValue6:
rjmp SGP30_SendCO2
#endif
#ifdef MODULES_CCS811
AppReportSensors_OnEverySecond_sendCCS811_TVOC:
rjmp CCS811_SendTVOC
AppReportSensors_OnEverySecond_sendCCS811_CO2:
rjmp CCS811_SendCO2
#endif
#ifdef MODULES_BRIGHTNESS
AppReportSensors_OnEverySecond_sendBrightness:
rjmp Brightness_Send
AppReportSensors_OnEverySecond_measureValue5:
rjmp SGP30_Measure
AppReportSensors_OnEverySecond_sendValue5:
rjmp SGP30_SendTVOC
ret
AppReportSensors_OnEverySecond_sendValue6:
rjmp SGP30_SendCO2
#endif
; @end

View File

@@ -1,579 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -11,7 +11,7 @@
; ***************************************************************************
; defines
.equ APP_STATS_INTERVAL_MINS = 30
.equ APP_STATS_INTERVAL_MINS = 11
@@ -53,15 +53,6 @@ AppStats_Fini:
;
AppStats_OnEveryMinute:
push r15
in r15, SREG
cli
rcall AppStats_OnEveryMinute_noIrq
out SREG, r15
pop r15
ret
AppStats_OnEveryMinute_noIrq:
lds r16, appStatsTimer
inc r16
cpi r16, APP_STATS_INTERVAL_MINS
@@ -69,68 +60,97 @@ AppStats_OnEveryMinute_noIrq:
clr r16
AppStats_OnEveryMinute_store:
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:
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
cpi r16, 1
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 2
breq AppStats_OnEveryMinute_sendMemStats
breq AppStats_OnEveryMinute_sendPacketsIn
cpi r16, 3
breq AppStats_OnEveryMinute_sendRecvStats1
breq AppStats_OnEveryMinute_sendPacketsOut
cpi r16, 4
breq AppStats_OnEveryMinute_sendContentErrs
cpi r16, 5
breq AppStats_OnEveryMinute_sendSendStats1
#ifdef APP_STATS_NETDEV2
breq AppStats_OnEveryMinute_sendIoErrs
cpi r16, 6
breq AppStats_OnEveryMinute_sendRecvStats2
breq AppStats_OnEveryMinute_sendNoBufErrs
cpi r16, 7
breq AppStats_OnEveryMinute_sendSendStats2
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
; add more here
ret
AppStats_OnEveryMinute_sendMemStats:
rjmp AppNetwork_SendMemStats
AppStats_OnEveryMinute_sendRecvStats1:
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
rjmp AppNetwork_SendRxdStats
AppStats_OnEveryMinute_sendDevice:
rjmp AppNetwork_SendDevice
AppStats_OnEveryMinute_sendSendStats1:
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
rjmp AppNetwork_SendTxdStats
#ifdef APP_STATS_NETDEV2
AppStats_OnEveryMinute_sendRecvStats2:
ldi yl, LOW(netInterfaceData2)
ldi yh, HIGH(netInterfaceData2)
rjmp AppNetwork_SendRxdStats
AppStats_OnEveryMinute_sendSendStats2:
ldi yl, LOW(netInterfaceData2)
ldi yh, HIGH(netInterfaceData2)
rjmp AppNetwork_SendTxdStats
AppStats_OnEveryMinute_sendPacketsIn:
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
ldd r18, Y+NET_IFACE_OFFS_PACKETSIN_LOW
ldd r19, Y+NET_IFACE_OFFS_PACKETSIN_HIGH
rjmp appStatsSend16BitValue
AppStats_OnEveryMinute_sendPacketsOut:
ldi r17, AQHOME_VALUEID_STATS_PACKETS_OUT
ldd r18, Y+NET_IFACE_OFFS_PACKETSOUT_LOW
ldd r19, Y+NET_IFACE_OFFS_PACKETSOUT_HIGH
rjmp appStatsSend16BitValue
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
; @end
; ---------------------------------------------------------------------------
; @routine AppStats_OnEveryMinute @global
;
; @param R17 value id
; @param R19:R18 value
appStatsSend16BitValue:
ldi r20, 1
clr r21
ldi r22, AQHOME_VALUETYPE_STATS
rjmp Main_SendValueReport
; @end

View File

@@ -27,11 +27,7 @@
wait_50us.asm
watchdog.asm
list.asm
list_t.asm
tree.asm
tree_t.asm
eeprom-r.asm
eeprom-w.asm
</extradist>
</gwbuild>

View File

@@ -1,30 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
.macro bigcall
.if FLASHEND >= 0x1000
call @0
.else
rcall @0
.endif
.endmacro
.macro bigjmp
.if FLASHEND >= 0x1000
jmp @0
.else
rjmp @0
.endif
.endmacro

View File

@@ -38,8 +38,6 @@ DEBUG2:
; @clobbers (R16, R18, R22, R24, R25)
blinkLed:
sbi LED_SIMPLE_DDR, LED_SIMPLE_PINNUM ; out
blinkLed_loop:
cbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; on
mov r22, r20
rcall waitForMultiple100ms ; (R252
@@ -47,7 +45,7 @@ blinkLed_loop:
mov r22, r21
rcall waitForMultiple100ms ; (R22)
dec r19
brne blinkLed_loop
brne blinkLed
ret
@@ -76,7 +74,7 @@ waitFor10ms:
ldi r22, 100
waitFor10ms_loop:
push r22
bigcall Utils_WaitFor100MicroSecs
rcall Utils_WaitFor100MicroSecs
pop r22
dec r22
brne waitFor10ms_loop

View File

@@ -1,80 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -1,100 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -1,135 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -54,26 +54,11 @@ List_InitObject:
; ---------------------------------------------------------------------------
; @routine List_FiniObject @global
;
; @param Y pointer to object
; @clobbers r16
List_FiniObject:
clr r16 ; set this->NEXT to NULL
std Y+LIST_OFFS_NEXT_LO, r16
std Y+LIST_OFFS_NEXT_HI, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine List_GetNextObject @global
; @param Y pointer to object
; @return X pointer to successor object
; @return X pointer to parent object
; @clobbers none
List_GetNextObject:
@@ -116,13 +101,13 @@ List_GetPredecessorFor:
cp r16, yl
brne List_GetPredecessorFor_next
cp r17, yh
breq List_GetPredecessorFor_haveIt
breq List_GetLastObject_haveIt
List_GetPredecessorFor_next:
mov xl, r16
mov xh, r17
rjmp List_GetPredecessorFor
List_GetPredecessorFor_haveIt:
sbiw xh:xl, 2
sbiw xh:xl, 1
List_GetPredecessorFor_ret:
ret
; @end
@@ -142,14 +127,8 @@ List_AddObject:
rcall List_GetLastObject ; (r16, r17, X, Y)
pop yh
pop yl
mov r16, xl
or r16, xh
clc
breq List_AddObject_ret
st X+, yl ; LIST_OFFS_NEXT_LO
st X+, yh ; LIST_OFFS_NEXT_HI
sec
List_AddObject_ret:
st X+, yl ; WID_OFFS_WNEXT_LO
st X+, yh ; WID_OFFS_WNEXT_HI
ret
; @end
@@ -184,68 +163,4 @@ 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

View File

@@ -1,240 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -52,7 +52,7 @@ l_loop:
brcs l_loop
rjmp l_end ; use cleared CFLAG
l_foundfree:
ldi r16, 0x10 ; mark as used
ldi r16, 0x80 ; mark as used
st X, r16
mov r16, r17
sec ; set CFLAG, return bufnum in r16, pointre in X

View File

@@ -120,7 +120,7 @@ RingBufferY_Reset:
;
; @return CFLAG on success, cleared on error
; @return r16 byte read
; @param Y base address of ringbuffer struct
; @param Y pointer to start of interface data
; @clobbers R17, R18, X
RingBufferY_ReadByteGuarded:

View File

@@ -17,10 +17,10 @@
; defs
.equ TREE_OFFS_LIST = 0
.equ TREE_OFFS_PARENT_LO = TREE_OFFS_LIST+LIST_SIZE
.equ TREE_OFFS_PARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
.equ TREE_OFFS_CHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
.equ TREE_OFFS_CHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
.equ TREE_OFFS_WPARENT_LO = TREE_OFFS_LIST+LIST_SIZE
.equ TREE_OFFS_WPARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
.equ TREE_OFFS_WCHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
.equ TREE_OFFS_WCHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
.equ TREE_SIZE = TREE_OFFS_LIST+LIST_SIZE+4
@@ -42,10 +42,10 @@
Tree_InitObject:
rcall List_InitObject ; (R16)
clr r16 ; clear this->TREE data
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_HI, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_HI, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_HI, r16
ret
; @end
@@ -59,8 +59,8 @@ Tree_InitObject:
; @clobbers none
Tree_GetParentObject:
ldd xl, Y+TREE_OFFS_PARENT_LO
ldd xh, Y+TREE_OFFS_PARENT_HI
ldd xl, Y+TREE_OFFS_WPARENT_LO
ldd xh, Y+TREE_OFFS_WPARENT_HI
ret
; @end
@@ -74,46 +74,13 @@ Tree_GetParentObject:
; @clobbers none
Tree_GetFirstChildObject:
ldd xl, Y+TREE_OFFS_CHILD_LO
ldd xh, Y+TREE_OFFS_CHILD_HI
ldd xl, Y+TREE_OFFS_WCHILD_LO
ldd xh, Y+TREE_OFFS_WCHILD_HI
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetLastChildObject @global
; @param Y pointer to object
; @return X pointer to last child object
; @clobbers none
Tree_GetLastChildObject:
ldd xl, Y+TREE_OFFS_CHILD_LO
ldd xh, Y+TREE_OFFS_CHILD_HI
mov r16, xl
or r16, xh
breq Tree_GetLastChildObject_ret
rcall List_GetLastObject
Tree_GetLastChildObject_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetNextSibling @global
; @param Y pointer to object
; @return X pointer to successor object
; @clobbers none
Tree_GetNextSibling:
rjmp List_GetNextObject
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetObjectBelow @global
@@ -134,7 +101,7 @@ treeGetObjectBelow:
mov r16, xl
or r16, xh
brne treeGetObjectBelow_ret ; got one
rcall Tree_GetNextSibling
rcall List_GetNextObject
mov r16, xl
or r16, xh
brne treeGetObjectBelow_ret ; got one
@@ -155,27 +122,27 @@ treeGetObjectBelow_ret:
; ---------------------------------------------------------------------------
; @routine Tree_AddChildObject @global
; @param Y pointer to object to add
; @param X pointer to parent to add to
; @param Y pointer to object to add
; @clobbers r16, r17, r18, x
Tree_AddChildObject:
std Y+TREE_OFFS_PARENT_LO, xl ; immediately store parent pointer
std Y+TREE_OFFS_PARENT_HI, xh
adiw xh:xl, TREE_OFFS_CHILD_LO ; read pointer to first child
std Y+TREE_OFFS_WPARENT_LO, xl ; immediately store parent pointer
std Y+TREE_OFFS_WPARENT_HI, xh
adiw xh:xl, TREE_OFFS_WCHILD_LO
ld r16, X+
ld r17, X
mov r18, r16
or r18, r17
brne Tree_AddChildObject_addToChildList
st X, yh ; no child, set THIS as first
st X, yh ; no child, set THIS as first
st -X, yl
sbiw xh:xl, TREE_OFFS_CHILD_LO
sbiw xh:xl, WID_OFFS_TREE+TREE_OFFS_WCHILD_LO
ret
Tree_AddChildObject_addToChildList:
mov xl, r16 ; X=first child
mov xl, r16
mov xh, r17
rjmp List_AddObject ; add Y as new object
rjmp List_AddObject
; @end
@@ -187,17 +154,17 @@ Tree_AddChildObject_addToChildList:
; @clobbers r16, r17, x
Tree_UnlinkObject:
ldd xl, Y+TREE_OFFS_PARENT_LO
ldd xh, Y+TREE_OFFS_PARENT_HI
ldd xl, Y+TREE_OFFS_WPARENT_LO
ldd xh, Y+TREE_OFFS_WPARENT_HI
mov r16, xl
or r16, xh
breq Tree_UnlinkObject_ret ; not part of a tree
adiw xh:xl, TREE_OFFS_CHILD_LO ; get parent's first child to R17:R16
adiw xh:xl, TREE_OFFS_WCHILD_LO ; get parent's first child to R17:R16
ld r16, X+
ld r17, X
cp r16, yl ; same as THIS?
brne Tree_UnlinkObject_inList ; nope, need to check childList
cp r17, yh ; same as THIS?
cp r17, yh
brne Tree_UnlinkObject_inList ; nope, need to check childList
ldd r16, Y+TREE_OFFS_LIST+LIST_OFFS_NEXT_HI ; is first child, set this->NEXT as new first child
st X, r16
@@ -210,8 +177,8 @@ Tree_UnlinkObject_inList:
rcall List_UnlinkObject ; (R16, R17, X)
Tree_UnlinkObject_clrParentAndSibling:
clr r16 ; clear this->PARENT
std Y+TREE_OFFS_PARENT_LO, r16
std Y+TREE_OFFS_PARENT_HI, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16
std Y+LIST_OFFS_NEXT_LO, r16
std Y+LIST_OFFS_NEXT_HI, r16 ; clear this->NEXT
Tree_UnlinkObject_ret:
@@ -221,6 +188,5 @@ Tree_UnlinkObject_ret:
#endif ; AQH_AVR_COMMON_TREE_H

View File

@@ -1,381 +0,0 @@
; ***************************************************************************
; 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

View File

@@ -7,6 +7,29 @@
; * 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
.macro inr

View File

@@ -18,8 +18,7 @@
; @clobbers r22
Utils_WaitFor50MicroSecs:
Utils_WaitNanoSecs 25000, 0, r22 ; wait for 25us
Utils_WaitNanoSecs 25000, 7, r22 ; wait for 25us (minus RCALL and RET)
Utils_WaitNanoSecs 50000, 7, r22 ; wait for 50us (minus RCALL and RET)
ret
; @end

View File

@@ -7,7 +7,6 @@
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
.error "Dont include this, use devices/all/defs.asm instead"
.equ AQHOME_VALUETYPE_UNKNOWN = 0

View File

@@ -25,20 +25,12 @@
<subdirs>
all
c01
c02
n14
n16
n21
n22
n23
n24
n25
n26
n27
n28
r05
r06
s03
t03
t04
</subdirs>
</gwbuild>

View File

@@ -26,39 +26,27 @@ initApps:
#ifdef APPS_NETWORK
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall AppNetwork_Init
#endif
#ifdef APPS_ROUTER
bigcall AppRouter_Init
#endif
#ifdef APPS_HUB
bigcall AppHub_Init
#endif
#ifdef APPS_FORWARDER
bigcall AppForwarder_Init
rcall AppNetwork_Init
#endif
#ifdef APPS_MOTION
bigcall AppMotion_Init
rcall AppMotion_Init
#endif
#ifdef APPS_DOOR
bigcall AppDoor_Init
rcall AppDoor_Init
#endif
#ifdef APPS_REPORTSENSORS
bigcall AppReportSensors_Init
rcall AppReportSensors_Init
#endif
#ifdef APPS_STATS
bigcall AppStats_Init
rcall AppStats_Init
#endif
#ifdef APPS_MA_LIGHT
bigcall AppMotionLight_Init
rcall AppMotionLight_Init
#endif
; done
@@ -74,37 +62,9 @@ initApps:
;
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
tst r16
clc
breq runApps_end
sec
runApps_end:
ret
; @end
@@ -118,11 +78,11 @@ mainAppsOnPacketReceived:
; handle messages
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall AppNetwork_HandleMsg
rcall AppNetwork_HandleMsg
#endif
#ifdef APPS_MA_LIGHT
bigcall AppMotionLight_OnPacketReceived
rcall AppMotionLight_OnPacketReceived
#endif
; add more here

278
avr/devices/all/attn.asm Normal file
View File

@@ -0,0 +1,278 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; not used for now
; ***************************************************************************
; macros
.macro mAttnInitInt0
; select falling edge of ATTN
inr r16, MCUCR
cbr r16, (1<<ISC01) | (1<<ISC00)
sbr r16, (1<<ISC01) | (0<<ISC00)
outr MCUCR, r16
.endmacro
.macro mAttnInitPCI
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
ori r16, (1<<COM_IRQ_GIMSK_ATTN)
out GIMSK, R16
ldi r16, (1<<COM_IRQ_GIFR_ATTN) ; clear pending irq by writing 1 to ATTN bit
out GIFR, r16
.endmacro
.macro mAttnEnableIrqInt0
inr r16, COM_IRQ_ADDR_ATTN
sbr r16, (1<<ATTN_IRQ_BIT)
outr COM_IRQ_ADDR_ATTN, r16
.endmacro
.macro mAttnEnableIrqPCI
sbi COM_IRQ_ADDR_ATTN, ATTN_IRQ_BIT ; enable pin change irq for ATTN line
.endmacro
.macro mAttnDisableIrqInt0
inr r16, COM_IRQ_ADDR_ATTN ; disable irq for ATTN line
cbr r16, (1<<ATTN_IRQ_BIT)
outr COM_IRQ_ADDR_ATTN, r16
.endmacro
.macro mAttnDisableIrqPCI
cbi COM_IRQ_ADDR_ATTN, ATTN_IRQ_BIT ; disable pin change irq for ATTN line
.endmacro
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ATTN_Init @global
;
; @clobbers R16
ATTN_Init:
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnInitInt0
.else
mAttnInitPCI
.endif
.else
mAttnInitPCI
.endif
rcall ATTN_SetHighEnableIrq
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetLowDisableIrq @global
;
; @clobbers R16
ATTN_SetLowDisableIrq:
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnDisableIrqInt0
.else
mAttnDisableIrqPCI
.endif
.else
mAttnDisableIrqPCI
.endif
sbi ATTN_DDR, ATTN_PIN ; set ATTN as output
cbi ATTN_OUTPUT, ATTN_PIN ; set ATTN low
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_SetHighEnableIrq @global
;
; @clobbers R16
ATTN_SetHighEnableIrq:
cbi ATTN_DDR, ATTN_PIN ; set ATTN as input
.ifdef ATTN_PUE
cbi ATTN_PUE, ATTN_PIN ; disable pullup on ATTN
.else
cbi ATTN_OUTPUT, ATTN_PIN ; disable pullup on ATTN
.endif
.ifdef INT0
.if ATTN_IRQ_BIT == INT0
mAttnEnableIrqInt0
.else
mAttnEnableIrqPCI
.endif
.else
mAttnEnableIrqPCI
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_IsHigh @global
;
; @return CFLAG set if ATTN is high
; @clobbers none
ATTN_IsHigh:
clc
sbic ATTN_INPUT, ATTN_PIN ; ATTN low?
sec ; yes, set CF
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForStateSeconds
;
; Wait for ATTN state max given seconds
;
; @return CFLAG set if okay (data available), cleared on error
; @param R16 expected state (0xff for high, 0 for low)
; @param r20 maximum number of seconds to wait
; @clobbers: r20, r22
ATTN_WaitForStateSeconds:
ATTN_WaitForStateSeconds_loop:
push r20
rcall ATTN_WaitForState1s ; (r20, r22)
pop r20
brcs ATTN_WaitForStateSeconds_gotit
sbi LED_PIN, LED_PINNUM ; toggle (doen't work on AtMega8515)
dec r20
brne ATTN_WaitForStateSeconds_loop
clc
ATTN_WaitForStateSeconds_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForState1s
;
; Wait for ATTN state for max 1s
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (ATTN state reached), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState1s:
ldi r20, 100
ATTN_WaitForState1s_loop:
push r20
rcall ATTN_WaitForState10ms ; (R20, R22)
pop r20
brcs ATTN_WaitForState1s_gotit
dec r20
brne ATTN_WaitForState1s_loop
clc
ATTN_WaitForState1s_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForState10ms
;
; Wait for ATTN state for max 10 milliseconds.
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (ATTN state reached), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState10ms:
.if clock == 8000000
ldi r20, 80
.endif
.if clock == 1000000
ldi r20, 10
.endif
ATTN_WaitForState10ms_loop:
push r20
rcall ATTN_WaitForState1000Cycles ; (r20, r22)
pop r20
brcs ATTN_WaitForState10ms_gotit
dec r20
brne ATTN_WaitForState10ms_loop
clc
ATTN_WaitForState10ms_gotit:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ATTN_WaitForStateState1000Cycles
;
; Wait for ATTN state for max 1000 clock cycles
; (about 1ms at 1MHz, 0.125ms at 8MHz)
;
; @param R16 expected state (0xff for high, 0 for low)
; @return CFLAG set if okay (packet received), cleared on error
; @clobbers: r20, r22
ATTN_WaitForState1000Cycles:
ldi r20, 90 ; 1
ATTN_WaitForState1000Cycles_loop:
push r17 ; +2
in r17, COM_ATTN_INPUT ; +1
eor r17, r16 ; +1
andi r17, (1<<COM_ATTN_PIN) ; +1
pop r17 ; +2
breq ATTN_WaitForState1000Cycles_stateReached ; +1
dec r20 ; +1
brne ATTN_WaitForState1000Cycles_loop ; +2
clc
ret
ATTN_WaitForState1000Cycles_stateReached:
sec
ret
; @end

View File

@@ -7,6 +7,7 @@
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ---------------------------------------------------------------------------
; Value types
@@ -20,7 +21,6 @@
.equ AQHOME_VALUETYPE_CO2 = 7
.equ AQHOME_VALUETYPE_TVOC = 8
.equ AQHOME_VALUETYPE_STATS = 9
.equ AQHOME_VALUETYPE_LIGHT = 10
; Value Ids
@@ -32,21 +32,11 @@
.equ AQHOME_VALUEID_STATS_ERRS_NOBUF = 0xe4
.equ AQHOME_VALUEID_STATS_ERRS_COLLISIONS = 0xe5
.equ AQHOME_VALUEID_STATS_ERRS_BUSY = 0xe6
.equ AQHOME_VALUEID_STATS_ERRS_MSGSIZE = 0xe7
.equ AQHOME_VALUEID_STATS_ERRS_MISSED = 0xe8
.equ AQHOME_VALUEID_STATS_HEAP_USED = 0xe7
.equ AQHOME_VALUEID_STATS_HEAP_FREE = 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
; ---------------------------------------------------------------------------
@@ -57,12 +47,6 @@
.equ TLV_OFFS_LEN = 0
.equ TLV_OFFS_TYPE = 1
.equ TLV_OFFS_VALUE = 2
; ---------------------------------------------------------------------------
; EEPROM positions
@@ -82,18 +66,5 @@
.equ EEPROM_OFFS_MAL_CONF_SRC2_VALUEID = 19 ; 1 byte
.equ EEPROM_OFFS_MAL_CONF_RGBWVALUE = 20 ; 4 bytes
.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)
; next is 24

View File

@@ -1,152 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; Hardware routine for AtMega 644P devices
.cseg
; ---------------------------------------------------------------------------
; @routine systemInitHardware
;
systemInitHardware:
; set all ports as inputs and enable internal pull-up resistors
ldi r16, 0xff
clr r17
out DDRA, r17 ; all input
out PORTA, r16 ; enable pull-up on all
out DDRB, r17 ; all input
out PORTB, r16 ; enable pull-up on all
out DDRC, r17 ; all input
out PORTC, r16 ; enable pull-up on all
out DDRD, r17 ; all input
out PORTD, r16 ; enable pull-up on all
ret
; @end
; ---------------------------------------------------------------------------
; @routine systemSetSpeed
;
systemSetSpeed:
ret
; @end
; ---------------------------------------------------------------------------
; @routine systemSleep
;
systemSleep:
; only modify SE, SM2, SM1 and SM0
cli
inr r16, SMCR
cbr r16, (1<<SE) | (0<<SM2) | (0<<SM1) | (0<<SM0)
outr SMCR, r16
sei ; make sure interrupts really are enabled
inr r16, SMCR ; enable sleep mode
sbr r16, (1<<SE)
outr SMCR, r16
sleep ; sleep, wait for interrupt
inr r16, SMCR ; disable sleep mode
cbr r16, (1<<SE)
outr SMCR, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine systemSetupTimer0
;
systemSetupTimer0: ; setup timer for IRQ every 100ms
ldi r16, (1<<WGM01) | (0<<WGM00) ; Prescaler 1024, CTC mode
outr TCCR0A, r16
ldi r16, (1<<CS02) | (0<<CS01) | (1<<CS00) | (0<<WGM02) ; Prescaler 1024, CTC mode
outr TCCR0B, r16
;
; Settings for clock 1Mhz (default)
; use timer0 with OCR0A=98-1 (irq every 97.65625 millisecs), baseTimerModuleReloadValue 1
;
.if clock == 1000000
; CMP-A interrupt about every 100ms
ldi r16, 98-1 ; (1,000,000/1024)/10 = 97.65625
outr OCR0A, r16
ldi r16, 1
sts baseTimerModuleReloadValue, r16
sts baseTimerModuleTickCounter, r16
; Settings for clock 8Mhz
; use timer0 with OCR0=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
;
.elif clock == 8000000
; CMP interrupt about every 10ms
ldi r16, 78-1
outr OCR0A, r16
ldi r16, 10
sts baseTimerModuleReloadValue, 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
ldi r16, (1<<OCF0A) ; clear pending interrupts
outr TIFR0, r16
inr r16, TIMSK0
sbr r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
outr TIMSK0, r16
.endif
sec
ret
; @end

View File

@@ -72,14 +72,13 @@ systemSleep:
; only modify SE, SM1 and SM0
cli
in r16, MCUCR
cbr r16, (1<<SE) | (1<<SM1) | (1<<SM0)
out MCUCR, r16
sbr r16, (1<<SE) | (0<<SM1) | (0<<SM0) ; sleep mode "idle", enable
ldi r17, (1<<SE) | (1<<SM1) | (1<<SM0)
neg r17
and r16, r17
ori r16, (1<<SE) ; sleep mode "idle", enable
out MCUCR, r16
sei ; make sure interrupts really are enabled
sleep ; sleep, wait for interrupt
cbr r16, (1<<SE) | (1<<SM1) | (1<<SM0)
out MCUCR, r16
ret
; @end
@@ -91,7 +90,7 @@ systemSleep:
;
systemSetupTimer0: ; setup timer for IRQ every 100ms
ldi r16, (0<<WGM02) | (1<<CS02) | (0<<CS01) | (1<<CS00) ; Prescaler 1024
ldi r16, (1<<CS02) | (0<<CS01) | (1<<CS00) ; Prescaler 1024
out TCCR0B, r16
ldi r16, (1<<WGM01) | (0<<WGM00) ; CTC mode
@@ -126,12 +125,19 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
ldi r16, (1<<OCF0A) ; clear pending interrupts
.ifdef TIFR0
out TIFR0, r16
.else
out TIFR, r16
.endif
ldi r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
.ifdef TIMSK0
out TIMSK0, r16
sec
.else
out TIMSK, r16
.endif
sec
ret
; @end

View File

@@ -19,14 +19,14 @@
systemInitHardware:
; set all ports as inputs and enable internal pull-up resistors
; ldi r16, 0xff
ldi r16, 0xff
clr r17
outr DDRA, r17 ; all input
outr PUEA, r17 ; disable pull-up on all
out DDRA, r17 ; all input
sts PUEA, r16 ; enable pull-up on all
outr DDRB, r17 ; all input
outr PUEB, r17 ; disable pull-up on all
out DDRB, r17 ; all input
sts PUEB, r16 ; enable pull-up on all
ret
; @end
@@ -50,22 +50,6 @@ systemSetSpeed:
clr r16 ; SUT=0, CLKPS=0
sts CCP, r17
sts CLKPR, r16
#if 0
; read and set calibration data
push r15
inr r15, SREG
cli
ldi zl, 0
ldi zh, 1
ldi r16, (1<<RSIG) | (1<<SPMEN)
outr SPMCSR, r16
lpm r17, Z
outr OSCCAL0, r17
outr SREG, r15
pop r15
#endif
.endif
ret
@@ -134,16 +118,16 @@ systemSetupTimer0: ; setup timer for IRQ every 100ms
ldi r16, (1<<OCF0A) ; clear pending interrupts
.ifdef TIFR0
outr TIFR0, r16
out TIFR0, r16
.else
outr TIFR, r16
out TIFR, r16
.endif
ldi r16, (1<<OCIE0A) ; Timer/Counter0 Output Compare Match A Interrupt Enable
.ifdef TIMSK0
outr TIMSK0, r16
out TIMSK0, r16
.else
outr TIMSK, r16
out TIMSK, r16
.endif
sec
ret

Some files were not shown because too many files have changed in this diff Show More