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
340 changed files with 11376 additions and 22790 deletions

5
0BUILD
View File

@@ -2,7 +2,7 @@
<gwbuild>
<project name="aqhome" version="0.0.12" so_current="0" so_age="0" so_revision="12" 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

@@ -37,9 +37,6 @@
getdevices.h
adddata.h
getdatapoints.h
getfirstdata.h
getlastdata.h
getperioddata.h
setdata.h
moddevice.h
watch.h
@@ -52,9 +49,6 @@
getdevices.c
adddata.c
getdatapoints.c
getfirstdata.c
getlastdata.c
getperioddata.c
setdata.c
moddevice.c
watch.c

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,9 +17,6 @@
#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"
@@ -95,9 +92,6 @@ 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")),

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

@@ -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;

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_ERROR(NULL, "Server Error: %d", AQH_IpcMessageResult_GetResult(tagList));
GWEN_Tag16_List_free(tagList);
AQH_Message_free(msgIn);
return 0;
}
else {
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
}
GWEN_Tag16_List_free(tagList);
}
AQH_Message_free(msgIn);
} /* while */
return fullNumberOfPoints;
}
int _handleResult(AQH_DATACLIENT *dc, uint32_t msgId)
{
AQH_MESSAGE *msgIn;
while( (msgIn=AQH_IpcEndpoint_WaitForResponseMsg(dc->ipcEndpoint, msgId, dc->timeoutInSeconds)) ) {
GWEN_TAG16_LIST *tagList;
tagList=AQH_IpcMessageTag16_ParsePayload(msgIn, 0);
if (tagList) {
uint16_t code;
code=AQH_IpcMessage_GetCode(msgIn);
if (code==AQH_MSGTYPE_IPC_DATA_RESULT) {
int result;
result=AQH_IpcMessageResult_GetResult(tagList);
DBG_INFO(NULL, "Server result: %d", result);
GWEN_Tag16_List_free(tagList);
AQH_Message_free(msgIn);
if (result!=AQH_MSGDATA_RESULT_SUCCESS) {
DBG_INFO(NULL, "here (%d)", result);
return GWEN_ERROR_GENERIC;
}
return 0;
}
else {
DBG_INFO(NULL, "Ignoring message \"%d\"", code);
}
GWEN_Tag16_List_free(tagList);
}
AQH_Message_free(msgIn);
} /* while */
return GWEN_ERROR_TIMEOUT;
}
int AQH_DataClient_ConnectWithArgs(AQH_DATACLIENT *dc, uint32_t flags)
{
const char *brokerAddress;
int brokerPort;
const char *userId;
const char *passwd;
const char *clientId;
int rv;
brokerAddress=GWEN_DB_GetCharValue(dc->dbLocalArgs, "brokerAddress", 0, NULL);
if (!(brokerAddress && *brokerAddress))
brokerAddress=GWEN_DB_GetCharValue(dc->dbLocalArgs, "ConfigFile/brokerAddress", 0, "127.0.0.1");
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "brokerPort", 0, -1);
if (brokerPort<0)
brokerPort=GWEN_DB_GetIntValue(dc->dbLocalArgs, "ConfigFile/brokerPort", 0, 45456);
userId=GWEN_DB_GetCharValue(dc->dbLocalArgs, "userId", 0, NULL);
passwd=GWEN_DB_GetCharValue(dc->dbLocalArgs, "password", 0, NULL);
clientId=GWEN_DB_GetCharValue(dc->dbLocalArgs, "brokerClientId", 0, NULL);
rv=AQH_DataClient_Connect(dc, brokerAddress, brokerPort, userId, passwd, clientId, flags);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}

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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -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,8 +9,6 @@
network
reportsensors
stats
router
hub
</subdirs>
<extradist>

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
rcall 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,57 +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:
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
rcall Utils_ReadUid ; r21:r20:r19:r18=uid (r16, X)
pop xh
pop xl
rcall NETMSG_Range_Read ; r20=range begin, r21=range end (none)
ldi r16, APP_NETWORK_STATE_INITIALWAIT
std Y+NET_IFACE_OFFS_STATUS, r16
cpi r18, 20
brcc appNetworkHandleReeunumRequest_setWait
subi r18, -20 ; minimum 2s
appNetworkHandleReeunumRequest_setWait:
std Y+NET_IFACE_OFFS_STATETIMER, r18 ; use lowest byte of uid as wat time
std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20
std Y+NET_IFACE_OFFS_RANGE_END, r21
ret
; @end
appNetworkTimerTable:
rjmp appNetworkHandleStateInitialWait
@@ -276,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
@@ -291,6 +233,7 @@ appNetworkHandleStateUp:
ret
; ---------------------------------------------------------------------------
; @routine appNetworkSendMsgNextState
;
@@ -298,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
@@ -363,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
@@ -387,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
@@ -402,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
@@ -422,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
@@ -453,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
@@ -481,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,14 +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
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendTxdStats_end:
ret
; @end
@@ -39,14 +39,14 @@ AppNetwork_SendTxdStats_end:
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendRxdStats:
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
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendRxdStats_end:
ret
; @end
@@ -60,14 +60,14 @@ AppNetwork_SendRxdStats_end:
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendMemStats:
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
bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
rcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X)
AppNetwork_SendMemStats_end:
ret
; @end
@@ -81,14 +81,14 @@ AppNetwork_SendMemStats_end:
; @clobbers R16, X (R17, R18, R19, R20, R21, Z)
AppNetwork_SendDevice:
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,15 +0,0 @@
<?xml?>
<gwbuild>
<subdirs>
</subdirs>
<extradist>
main.asm
</extradist>
</gwbuild>

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 = 31
.equ APP_STATS_INTERVAL_MINS = 11
@@ -53,19 +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:
; ldi yl, LOW(netInterfaceData)
; ldi yh, HIGH(netInterfaceData)
; rcall AppNetwork_SendRxdStats ; debug
lds r16, appStatsTimer
inc r16
cpi r16, APP_STATS_INTERVAL_MINS
@@ -75,105 +62,67 @@ AppStats_OnEveryMinute_store:
sts appStatsTimer, r16
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
ldi xl, LOW(netInterfaceData)
ldi xh, HIGH(netInterfaceData)
cpi r16, 1
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 2
breq AppStats_OnEveryMinute_sendPacketsIn
cpi r16, 3
breq AppStats_OnEveryMinute_sendPacketsIn
breq AppStats_OnEveryMinute_sendPacketsOut
cpi r16, 4
breq AppStats_OnEveryMinute_sendContentErrs
cpi r16, 5
breq AppStats_OnEveryMinute_sendPacketsOut
breq AppStats_OnEveryMinute_sendIoErrs
cpi r16, 6
breq AppStats_OnEveryMinute_sendDevice
breq AppStats_OnEveryMinute_sendNoBufErrs
cpi r16, 7
breq AppStats_OnEveryMinute_sendContentErrs
cpi r16, 9
breq AppStats_OnEveryMinute_sendIoErrs
cpi r16, 10
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 11
breq AppStats_OnEveryMinute_sendNoBufErrs
cpi r16, 13
breq AppStats_OnEveryMinute_sendCollisionErrs
cpi r16, 14
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 15
cpi r16, 8
breq AppStats_OnEveryMinute_sendBusyErrs
#ifdef APP_STATS_NETDEV2
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN2
ldi xl, LOW(netInterfaceData2)
ldi xh, HIGH(netInterfaceData2)
cpi r16, 16
breq AppStats_OnEveryMinute_sendPacketsIn
cpi r16, 17
breq AppStats_OnEveryMinute_sendPacketsOut
cpi r16, 18
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 19
breq AppStats_OnEveryMinute_sendContentErrs
cpi r16, 20
breq AppStats_OnEveryMinute_sendIoErrs
cpi r16, 21
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 22
breq AppStats_OnEveryMinute_sendNoBufErrs
cpi r16, 23
breq AppStats_OnEveryMinute_sendDevice
cpi r16, 24
breq AppStats_OnEveryMinute_sendCollisionErrs
cpi r16, 25
breq AppStats_OnEveryMinute_sendBusyErrs
#endif
#ifdef MODULES_HEAP
cpi r16, 26
cpi r16, 9
breq AppStats_OnEveryMinute_sendHeapUsed
cpi r16, 27
cpi r16, 10
breq AppStats_OnEveryMinute_sendHeapfree
#endif
cpi r16, 28
breq AppStats_OnEveryMinute_sendDevice
ret
AppStats_OnEveryMinute_sendDevice:
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
ret
AppStats_OnEveryMinute_sendPacketsIn:
ldi r16, 0
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendPacketsOut:
ldi r16, 1
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendContentErrs:
ldi r16, 2
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendIoErrs:
ldi r16, 3
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendNoBufErrs:
ldi r16, 4
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendCollisionErrs:
ldi r16, 5
rjmp appStatsSendDeviceStat
AppStats_OnEveryMinute_sendBusyErrs:
ldi r16, 6
rjmp appStatsSendDeviceStat
rjmp AppNetwork_SendDevice
AppStats_OnEveryMinute_sendPacketsIn:
ldi r17, AQHOME_VALUEID_STATS_PACKETS_IN
ldd r18, Y+NET_IFACE_OFFS_PACKETSIN_LOW
ldd r19, Y+NET_IFACE_OFFS_PACKETSIN_HIGH
rjmp appStatsSend16BitValue
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
@@ -190,30 +139,6 @@ AppStats_OnEveryMinute_sendHeapfree:
; ---------------------------------------------------------------------------
; @routine AppStats_OnEveryMinute @global
;
; @param r16 index into device table (e.g. 0 for NET_IFACE_OFFS_PACKETSIN_LOW)
; @param r17 offset to first value id (e.g. AQHOME_VALUEID_STATS_PACKETS_IN for device 0,
; AQHOME_VALUEID_STATS_PACKETS_IN2 for device 1)
; @param Y pointer to device to send data to
; @param X pointer to device to inspect
appStatsSendDeviceStat:
add r17, r16
lsl r16
adiw xh:xl, NET_IFACE_OFFS_PACKETSIN_LOW
add xl, r16
adc xh, r16
sub xh, r16
ld r18, X+
ld r19, X
rjmp appStatsSend16BitValue
; @end
; ---------------------------------------------------------------------------
; @routine AppStats_OnEveryMinute @global
;
@@ -224,7 +149,7 @@ appStatsSend16BitValue:
ldi r20, 1
clr r21
ldi r22, AQHOME_VALUETYPE_STATS
bigjmp Main_SendValueReport
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,17 +25,11 @@
<subdirs>
all
c01
c02
n14
n16
n21
n22
n23
n24
n25
n26
n27
r05
r06
s03
t03
</subdirs>

View File

@@ -26,35 +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
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
@@ -70,27 +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
bigcall AppHub_Run
#endif
; add more modules here
tst r16
clc
breq runApps_end
sec
runApps_end:
ret
; @end
@@ -104,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,136 +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
.endif
;
; Settings for clock 8Mhz
; use timer0 with OCR0=78 (irq every 9.984 millisecs), baseTimerModuleReloadValue 10
;
.if clock == 8000000
; CMP interrupt about every 10ms
ldi r16, 78-1
outr OCR0A, r16
ldi r16, 10
sts baseTimerModuleReloadValue, r16
sts baseTimerModuleTickCounter, r16
.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

View File

@@ -54,8 +54,7 @@
#ifdef MODULES_UART_BITBANG
.include "modules/uart_bitbang2/defs.asm"
.include "modules/uart_bitbang2/iface.asm"
.include "modules/uart_bitbang2/bytelevel.asm"
.include "modules/uart_bitbang2/msglevel.asm"
.include "modules/uart_bitbang2/lowlevel.asm"
#endif
#ifdef MODULES_UART_HW
@@ -68,68 +67,20 @@
#ifdef MODULES_COMONUART0
;.include "modules/uart_hw/defs.asm"
;.include "modules/uart_hw/lowlevel.asm"
;.include "modules/uart_hw/m_lowlevel_uart.asm"
;.include "modules/uart_hw/comonuart0.asm"
.include "modules/uart_hw2/defs.asm"
.include "modules/uart_hw2/comonuart0.asm"
#endif
#ifdef MODULES_COMONUART1
;.include "modules/uart_hw/defs.asm"
;.include "modules/uart_hw/lowlevel.asm"
;.include "modules/uart_hw/m_lowlevel_uart.asm"
;.include "modules/uart_hw/comonuart1.asm"
.include "modules/uart_hw2/defs.asm"
.include "modules/uart_hw2/comonuart1.asm"
.include "modules/uart_hw/defs.asm"
.include "modules/uart_hw/lowlevel.asm"
.include "modules/uart_hw/m_lowlevel_uart.asm"
.include "modules/uart_hw/comonuart0.asm"
#endif
#ifdef MODULES_TTYONUART1
#ifndef MODULES_COMONUART0
.include "modules/uart_hw/defs.asm"
.include "modules/uart_hw/lowlevel.asm"
.include "modules/uart_hw/m_lowlevel_uart.asm"
#endif
.include "modules/uart_hw/ttyonuart1.asm"
;.include "modules/uart_hw2/defs.asm"
;.include "modules/uart_hw2/ttyonuart1.asm"
#endif
#ifdef MODULES_COM2W
.include "modules/com2w/defs.asm"
.include "modules/com2w/com2w.asm"
#endif
#ifdef MODULES_COM2W0
.include "modules/com2w/defs.asm"
.include "modules/com2w/common.asm"
.include "modules/com2w/com2w0.asm"
#endif
#ifdef MODULES_COM2W1
.include "modules/com2w/defs.asm"
.include "modules/com2w/common.asm"
.include "modules/com2w/com2w1.asm"
#endif
#ifdef MODULES_COM2WN
.include "modules/com2w/defs.asm"
.include "modules/com2w/com2wn_init.asm"
.include "modules/com2w/com2wn_io.asm"
.include "modules/com2w/com2wn_irq.asm"
.include "modules/com2w/com2wn_recv.asm"
.include "modules/com2w/com2wn_run.asm"
.include "modules/com2w/com2wn_send.asm"
.include "modules/com2w/com2wn_wait.asm"
.include "modules/com2w/com2wn_data.asm"
#endif
@@ -192,9 +143,6 @@
#ifdef MODULES_CCS811
.include "modules/ccs811/main.asm"
#ifdef MODULES_NETWORK
.include "modules/ccs811/send.asm"
#endif
#endif
#ifdef MODULES_TCRT1000
@@ -208,10 +156,6 @@
#endif
#endif
#ifdef MODULES_LCD
.include "modules/lcd/main.asm"
#endif
#ifdef MODULES_ILI9341
.include "modules/lcd2/ili9341/defs.asm"
.include "modules/lcd2/ili9341/main.asm"
@@ -220,21 +164,6 @@
.include "modules/lcd2/ili9341/text.asm"
#endif
#ifdef MODULES_FONT
.include "modules/lcd2/font/defs.asm"
.include "modules/lcd2/font/main.asm"
#endif
#ifdef MODULES_WIN
.include "common/list.asm"
.include "common/tree.asm"
.include "modules/lcd2/win/defs.asm"
.include "modules/lcd2/win/object.asm"
.include "modules/lcd2/win/widget.asm"
.include "modules/lcd2/win/gui.asm"
#endif
#ifdef MODULES_FONT_8X8
.include "modules/lcd2/font/defs.asm"
.include "modules/lcd2/font/font8x8.asm"
@@ -247,14 +176,6 @@
#endif
#ifdef MODULES_BRIGHTNESS
.include "modules/brightness/main.asm"
#ifdef MODULES_NETWORK
.include "modules/brightness/send.asm"
#endif
#endif
#ifdef APPS_MOTION
.include "modules/f_keepup/main.asm"
.include "modules/valsched/main.asm"
@@ -275,37 +196,6 @@
.include "apps/network/main.asm"
.include "modules/network/msg/reboot-d.asm"
.include "modules/network/msg/reboot-r.asm"
.include "modules/network/msg/pong-w.asm"
.include "modules/network/msg/range-d.asm"
.include "modules/network/msg/range-r.asm"
.include "common/eeprom-r.asm"
.include "common/eeprom-w.asm"
#endif
#ifdef APPS_ROUTER
.include "apps/router/main.asm"
.include "modules/network/msg/reboot-d.asm"
.include "modules/network/msg/reboot-r.asm"
.include "modules/network/msg/pong-w.asm"
.include "modules/network/msg/range-d.asm"
.include "modules/network/msg/range-r.asm"
.include "modules/network/msg/range-w.asm"
.include "common/eeprom-r.asm"
.include "common/eeprom-w.asm"
#endif
#ifdef APPS_HUB
.include "apps/hub/main.asm"
.include "modules/network/msg/reboot-d.asm"
.include "modules/network/msg/reboot-r.asm"
.include "modules/network/msg/pong-w.asm"
.include "modules/network/msg/range-d.asm"
.include "modules/network/msg/range-r.asm"
.include "modules/network/msg/range-w.asm"
.include "common/eeprom-r.asm"
.include "common/eeprom-w.asm"
#endif

View File

@@ -8,7 +8,6 @@
; ***************************************************************************
; ***************************************************************************
; code
@@ -32,16 +31,16 @@ main:
; rcall watchdogOff ; turn off watchdog timer (sometimes it stays on after reboot)
bigcall systemSetSpeed
bigcall systemInitHardware
bigcall Utils_Init
bigcall Utils_SetupUid
bigcall initModules
bigcall initApps
bigcall Utils_InitialWait
rcall systemSetSpeed
rcall systemInitHardware
rcall Utils_Init
rcall Utils_SetupUid
rcall initModules
rcall initApps
rcall Utils_InitialWait
sei ; Enable interrupts
bigcall onSystemStart
rcall onSystemStart
#ifdef MODULES_LED
ldi xl, LOW(blinkPattern) ; debug: set blink pattern
@@ -54,36 +53,12 @@ main:
#endif
main_loop:
bigcall systemSleep ; system-dependant
; run loop as long as some run function returns with CFLAG set
clr r17
main_runLoop:
push r17
clr r16
push r16
bigcall runModules
pop r16
sbci r16, 0
push r16
bigcall runApps
pop r16
sbci r16, 0
rcall systemSleep ; system-dependant
rcall runModules
rcall runApps
rcall onEveryLoop ; call into main app
push r16
bigcall onEveryLoop ; call into main app
pop r16
pop r17
tst r16
breq main_endRunLoop
inc r17
cpi r17, 10
brcc main_endRunLoop
brne main_runLoop
main_endRunLoop:
#ifdef MODULES_NETWORK
#ifndef MAIN_WITHOUT_MSG_HANDLING
rcall mainHandleMessages
@@ -94,7 +69,7 @@ main_endRunLoop:
main_loop_reboot:
cli
bigjmp BOOTLOADER_ADDR
rjmp BOOTLOADER_ADDR
; @end
@@ -105,78 +80,53 @@ main_loop_reboot:
; Called every 100ms. No arguments, no results.
onSystemTimerTick:
bigcall onEvery100ms
rcall onEvery100ms
#ifdef MODULES_CLOCK
bigcall Clock_Every100ms ; generates calls to onEverySecond/Minute/Hour/Day
rcall Clock_Every100ms ; generates calls to onEverySecond/Minute/Hour/Day
#endif
#ifdef MODULES_LED_SIMPLE
bigcall LedSimple_Every100ms
rcall LedSimple_Every100ms
#endif
#ifdef MODULES_UART_BITBANG
bigcall UART_BitBang_Every100ms
rcall UART_BitBang_Every100ms
#endif
#ifdef MODULES_UART_HW
bigcall NET_Uart_Every100ms
rcall NET_Uart_Every100ms
#endif
#ifdef MODULES_TTYONUART1
bigcall TtyOnUart1_Periodically
rcall TtyOnUart1_Periodically
#endif
#ifdef MODULES_COMONUART0
bigcall ComOnUart0_Periodically
rcall ComOnUart0_Periodically
#endif
#ifdef MODULES_COMONUART1
bigcall ComOnUart1_Periodically
#endif
#ifdef MODULES_COM2W
bigcall COM2W_Every100ms
#endif
#ifdef MODULES_COM2W0
bigcall COM2W0_Periodically
#endif
#ifdef MODULES_COM2W1
bigcall COM2W1_Periodically
#endif
#ifdef MODULES_COM2WN
bigcall COM2WN_Periodically
#endif
#ifdef MODULES_TCRT1000
bigcall TCRT1K_Every100ms
rcall TCRT1K_Every100ms
#endif
#ifdef MODULES_BRIGHTNESS
bigcall Brightness_Every100ms
#endif
#ifdef APPS_NETWORK
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall AppNetwork_Every100ms
rcall AppNetwork_Every100ms
#endif
#ifdef APPS_MOTION
bigcall AppMotion_Every100ms
rcall AppMotion_Every100ms
#endif
#ifdef APPS_DOOR
bigcall AppDoor_Every100ms
rcall AppDoor_Every100ms
#endif
#ifdef APPS_MA_LIGHT
bigcall AppMotionLight_Every100ms
rcall AppMotionLight_Every100ms
#endif
ret
@@ -188,51 +138,32 @@ onSystemTimerTick:
sysOnEverySecond:
#ifdef MODULES_DS18B20
bigcall Ds18b20_OnEverySecond
rcall Ds18b20_OnEverySecond
#endif
#ifdef APPS_REPORTSENSORS
bigcall AppReportSensors_OnEverySecond
rcall AppReportSensors_OnEverySecond
#endif
#ifdef MODULES_SGP30
bigcall SGP30_EverySecond
#endif
bigjmp onEverySecond
rjmp onEverySecond
; @end
sysOnEveryMinute:
#ifdef APPS_STATS
bigcall AppStats_OnEveryMinute
rcall AppStats_OnEveryMinute
#endif
#ifdef MODULES_CCS811
bigcall CCS811_OnEveryMinute
#endif
bigjmp onEveryMinute
rjmp onEveryMinute
; @end
sysOnEveryHour:
bigjmp onEveryHour
rjmp onEveryHour
; @end
sysOnEveryDay:
#ifdef APPS_NETWORK
ldi yl, LOW(netInterfaceData)
ldi yh, HIGH(netInterfaceData)
bigcall AppNetwork_EveryDay
#endif
#ifdef APPS_ROUTER
bigcall AppRouter_EveryDay
#endif
bigjmp onEveryDay
rjmp onEveryDay
; @end
#endif
@@ -244,17 +175,17 @@ sysOnEveryDay:
; @routine mainHandleMessages
mainHandleMessages:
bigcall NET_GetNextIncomingMsgNum ; R16=msg num
rcall NET_GetNextIncomingMsgNum ; R16=msg num
brcc mainHandleMessages_end
bigcall NET_Buffer_Locate ; X=buffer addr (R17)
rcall NET_Buffer_Locate ; X=buffer addr (R17)
adiw xh:xl, 1
push r16
bigcall onMessageReceived
bigcall mainModulesOnPacketReceived
bigcall mainAppsOnPacketReceived
rcall onMessageReceived
rcall mainModulesOnPacketReceived
rcall mainAppsOnPacketReceived
pop r16
bigcall NET_Buffer_ReleaseByNum
rcall NET_Buffer_ReleaseByNum
sec
mainHandleMessages_end:
ret

View File

@@ -22,22 +22,22 @@
; Call init functions of the used modules. Add your routine calls here.
initModules:
bigcall BaseTimer_Init ; unconditionally call this
rcall BaseTimer_Init ; unconditionally call this
#ifdef MODULES_HEAP
bigcall Heap_Init
rcall Heap_Init
#endif
#ifdef MODULES_CLOCK
bigcall Clock_Init
rcall Clock_Init
#endif
#ifdef MODULES_TIMER
bigcall Timer_Init
rcall Timer_Init
#endif
#ifdef MODULES_XRAM
bigcall XRAM_Init
rcall XRAM_Init
#endif
#ifdef MODULES_LED
@@ -45,132 +45,107 @@ initModules:
ldi zh, HIGH(ledA3Flash)
ldi yl, LOW(ledA3Sram)
ldi yh, HIGH(ledA3Sram)
bigcall Led_Init
rcall Led_Init
#endif
#ifdef MODULES_LED_SIMPLE
bigcall LedSimple_Init
rcall LedSimple_Init
#endif
#ifdef MODULES_COM
bigcall Com2_Init ; init COM module
bigcall CPRO_Init ; init COM protocol module
rcall Com2_Init ; init COM module
rcall CPRO_Init ; init COM protocol module
#endif
#ifdef MODULES_NETWORK
bigcall NET_Init
rcall NET_Init
#endif
#ifdef MODULES_UART_BITBANG
bigcall UART_BitBang_Init
rcall UART_BitBang_Init
#endif
#ifdef MODULES_UART_HW
bigcall NET_Uart_Init
rcall NET_Uart_Init
#endif
#ifdef MODULES_TTYONUART1
bigcall TtyOnUart1_Init
rcall TtyOnUart1_Init
#endif
#ifdef MODULES_COMONUART0
bigcall ComOnUart0_Init
rcall ComOnUart0_Init
#endif
#ifdef MODULES_COMONUART1
bigcall ComOnUart1_Init
#endif
#ifdef MODULES_COM2W
bigcall COM2W_Init
#endif
#ifdef MODULES_COM2W0
bigcall COM2W0_Init
#endif
#ifdef MODULES_COM2W1
bigcall COM2W1_Init
#endif
#ifdef MODULES_COM2WN
bigcall COM2WN_Init
#endif
#ifdef MODULES_MOTION
bigcall Motion_Init
rcall Motion_Init
#endif
#ifdef MODULES_TWI_MASTER
bigcall TWI_Master_Init
rcall TWI_Master_Init
#endif
#ifdef MODULES_OWI_MASTER
bigcall OwiMaster_Init
rcall OwiMaster_Init
#endif
#ifdef MODULES_SPI_HW
bigcall SPIHW_Init
rcall SPIHW_Init
#endif
#ifdef MODULES_LCD
bigcall LCD_Init
rcall LCD_Init
#endif
#ifdef MODULES_BMP280
bigcall BMP280_Init
rcall BMP280_Init
#endif
#ifdef MODULES_SI7021
bigcall SI7021_Init
rcall SI7021_Init
#endif
#ifdef MODULES_SGP30
bigcall SGP30_Init
rcall SGP30_Init
#endif
#ifdef MODULES_SGP40
bigcall SGP40_Init
rcall SGP40_Init
#endif
#ifdef MODULES_DS18B20
bigcall Ds18b20_Init
rcall Ds18b20_Init
#endif
#ifdef MODULES_STATS
bigcall Stats_Init
rcall Stats_Init
#endif
#ifdef MODULES_CNY70
bigcall CNY70_Init
rcall CNY70_Init
#endif
#ifdef MODULES_REED
bigcall REED_Init
rcall REED_Init
#endif
#ifdef MODULES_SK6812
bigcall SK6812_Init
rcall SK6812_Init
#endif
#ifdef MODULES_MOTION_LIGHT
bigcall MotionLight_Init
rcall MotionLight_Init
#endif
#ifdef MODULES_TCRT1000
bigcall TCRT1K_Init
rcall TCRT1K_Init
#endif
#ifdef MODULES_CCS811
bigcall CCS811_Init
rcall CCS811_Init
#endif
#ifdef MODULES_ILI9341
bigcall ILI9341_Init
#endif
#ifdef MODULES_BRIGHTNESS
bigcall Brightness_Init
rcall ILI9341_Init
#endif
@@ -185,79 +160,72 @@ initModules:
;
; Call run functions of the used modules. Add your routine calls here.
;
; @return CFLAG set: at least one RUN routine returned CFLAG set
; @clobbers all
; IN:
; - nothing
; OUT:
; - nothing
; USED: depending on called routines
runModules:
clr r16
push r16
bigcall BaseTimer_Run
pop r16
sbci r16, 0
rcall BaseTimer_Run
#ifdef MODULES_COM
; COM module (call until carry flag cleared but at most 10 times to not starve other modules)
ldi r16, 10
runModules_Com:
push r16
rcall Com2_Run
pop r16
brcc runModules_ComEnd
dec r16
brne runModules_Com
runModules_ComEnd:
#endif
#ifdef MODULES_TTYONUART1
push r16
bigcall TtyOnUart1_Run
pop r16
rcall TtyOnUart1_Run
#endif
#ifdef MODULES_COMONUART0
push r16
bigcall ComOnUart0_Run
pop r16
sbci r16, 0
rcall ComOnUart0_Run
#endif
#ifdef MODULES_COMONUART1
push r16
bigcall ComOnUart1_Run
pop r16
sbci r16, 0
#ifdef MODULES_STATS
rcall Stats_Run
#endif
#ifdef MODULES_COM2W0
push r16
bigcall COM2W0_Run
pop r16
sbci r16, 0
#ifdef MODULES_REED
rcall REED_Run
#endif
#ifdef MODULES_COM2W1
push r16
bigcall COM2W1_Run
pop r16
sbci r16, 0
#ifdef MODULES_CNY70
rcall CNY70_Run
#endif
#ifdef MODULES_COM2WN
push r16
bigcall COM2WN_Run
pop r16
sbci r16, 0
#ifdef MODULES_MOTION_LIGHT
; rcall MotionLight_Run
#endif
#ifdef MODULES_TCRT1000
; rcall TCRT1K_Run
#endif
; add more modules here
; check for repeat request
tst r16
clc
breq runModules_end
sec
runModules_end:
ret
; @end
mainModulesOnPacketReceived:
#ifdef MODULES_SK6812
bigcall SK6812_OnPacketReceived
rcall SK6812_OnPacketReceived
#endif
#ifdef MODULES_LED_SIMPLE
#ifdef MODULES_NETWORK
bigcall LedSimple_OnPacketReceived
rcall LedSimple_OnPacketReceived
#endif
#endif

View File

@@ -23,7 +23,6 @@
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 value type
; @return CFLAG on success, cleared on error
Main_SendValueReport:
push r17
@@ -53,7 +52,6 @@ Main_SendValueReport_end:
; @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
Main_SendValueResponse:
push r17

View File

@@ -13,9 +13,8 @@
.list
.include "../defs.asm"
.include "devices/all/defs.asm"
.include "defs_all.asm"
.include "common/calls.asm"
.include "common/utils_wait.asm"
.include "common/utils_io.asm"

View File

@@ -67,11 +67,12 @@
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DATA_DDR = DDRD
.equ COM_DATA_DDR = DDRD ; use RX pin
.equ COM_DATA_INPUT = PIND
.equ COM_DATA_OUTPUT = PORTD
.equ COM_DATA_PIN = PORTD0
.equ COM_ATTN_DDR = DDRD
.equ COM_ATTN_INPUT = PIND
.equ COM_ATTN_OUTPUT = PORTD

View File

@@ -16,12 +16,10 @@
.include "include/m8515def.inc" ; Define device ATmega8515
.list
.include "version.asm"
.include "../defs.asm"
.include "./data.asm"
.include "devices/all/defs.asm"
.include "common/calls.asm"
.include "common/utils_wait.asm"
.include "common/utils_io.asm"
@@ -50,6 +48,11 @@
; ---------------------------------------------------------------------------
; firmware settings including list of modules used
.equ FIRMWARE_VERSION_MAJOR = 0
.equ FIRMWARE_VERSION_MINOR = 0
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
; #define MODULES_TIMER
#define MODULES_CLOCK
#define MODULES_XRAM
@@ -57,8 +60,9 @@
#define MODULES_LED_SIMPLE
#define MODULES_NETWORK
;#define MODULES_COMONUART0
;#define MODULES_UART_HW
#define MODULES_UART_BITBANG
#define MODULES_UART_HW
;#define MODULES_UART_BITBANG
#define MODULES_SPI_HW
#define MODULES_ILI9341
;#define MODULES_FONT_8X8
@@ -119,8 +123,7 @@
; ---------------------------------------------------------------------------
; Reset and interrupt vectors
rjmp BOOTLOADER_ADDR ; 1: Reset vector RESET
; rjmp NetUart_AttnChangeIsr ; 2: INT0 External Interrupt Request 0
rjmp UART_BitBang_PcintIsr ; 2: INT0 External Interrupt Request 0
rjmp NetUart_AttnChangeIsr ; 2: INT0 External Interrupt Request 0
reti ; 3: INT1 External Interrupt Request 1
reti ; 4: TIMER1_CAPT Timer/Counter1 Capture Event
reti ; 5: TIMER1_COMPA Timer/Counter1 Compare Match A
@@ -219,8 +222,7 @@ onEveryLoop:
; ---------------------------------------------------------------------------
; defines for network interface
;.equ netInterfaceData = netUartIface
.equ netInterfaceData = uart_bitbang_iface
.equ netInterfaceData = netUartIface
;.equ netInterfaceData = uart_bitbang_iface

View File

@@ -1,10 +0,0 @@
C01
===
- Role: Controller with Display
- MCU: AtMega 644P
- Connection: RJ45
- Periphery:
- Display with SPI

View File

@@ -1,24 +0,0 @@
<device name="aqua_c02" driver="nodes">
<manufacturer>AQUA</manufacturer>
<devicetype>C</devicetype>
<deviceversion>2</deviceversion>
<values>
<value name="LEDTIMING" id="0x88" type="actor" dataType="uint16" />
<value name="stats_packets_in" id="0xe0" type="sensor" dataType="uint16" denom="1" />
<value name="stats_packets_out" id="0xe1" type="sensor" dataType="uint16" denom="1" />
<value name="stats_content_errors" id="0xe2" type="sensor" dataType="uint16" denom="1" />
<value name="stats_io_errors" id="0xe3" type="sensor" dataType="uint16" denom="1" />
<value name="stats_nobuf_errors" id="0xe4" type="sensor" dataType="uint16" denom="1" />
<value name="stats_collision_errors" id="0xe5" type="sensor" dataType="uint16" denom="1" />
<value name="stats_busy_errors" id="0xe6" type="sensor" dataType="uint16" denom="1" />
<value name="stats_heap_used" id="0xe7" type="sensor" dataType="uint16" denom="1" />
<value name="stats_heap_free" id="0xe8" type="sensor" dataType="uint16" denom="1" />
<value name="stats_noram_errors" id="0xe9" type="sensor" dataType="uint16" denom="1" />
</values>
</device>

View File

@@ -1,32 +0,0 @@
<?xml?>
<gwbuild>
<target type="AvrHexFile" name="c02_boot" >
<includes type="avrasm" >
-I $(builddir)
-I $(srcdir)
-I $(topsrcdir)/avr
-I $(topbuilddir)/avr
</includes>
<sources type="avrasm" >
boot.asm
</sources>
</target>
<subdirs>
</subdirs>
<extradist>
</extradist>
</gwbuild>

View File

@@ -1,160 +0,0 @@
; ***************************************************************************
; Source file for base system node on AtMega 644P
;
; This is for the maintenance system (i.e. the flash loader).
;
; All definitions and changes should go into this file.
; ***************************************************************************
.equ clock=8000000 ; Define the clock frequency
.nolist
.include "include/m644Pdef.inc" ; Define device ATmega8515
.list
.include "../defs.asm"
.include "devices/all/defs.asm"
.include "common/calls.asm"
.include "common/utils_wait.asm"
.include "common/utils_io.asm"
; ***************************************************************************
; defines
; ---------------------------------------------------------------------------
; generic
.equ NET_BUFFERS_NUM = 6
.equ NET_BUFFERS_SIZE = 32
; ---------------------------------------------------------------------------
; firmware settings
.equ FIRMWARE_VERSION_MAJOR = 0
.equ FIRMWARE_VERSION_MINOR = 0
.equ FIRMWARE_VERSION_PATCHLEVEL = 1
; ---------------------------------------------------------------------------
; LED
.equ LED_DDR = DDRD
.equ LED_PORT = PORTD
.equ LED_PIN = PIND
.equ LED_PINNUM = PORTD4
; ***************************************************************************
; code segment
.cseg
.org 0x0000
; ---------------------------------------------------------------------------
; Reset and interrupt vectors
jmp main ; 1: Reset vector RESET
jmp irqNotSet ; 2: INT0 External Interrupt Request 0
jmp irqNotSet ; 3: INT1 External Interrupt Request 1
jmp irqNotSet ; 4: INT2 External Interrupt Request 2
jmp irqNotSet ; 5: PCINT0 Pin Change Interrupt Request 0
jmp irqNotSet ; 6: PCINT1 Pin Change Interrupt Request 1
jmp irqNotSet ; 7: PCINT2 Pin Change Interrupt Request 2
jmp irqNotSet ; 8: PCINT3 Pin Change Interrupt Request 3
jmp irqNotSet ; 9: WDT Watchdog Time-out Interrupt
jmp irqNotSet ; 10: TIMER2_COMPA Timer/Counter2 Compare Match A
jmp irqNotSet ; 11: TIMER2_COMPB Timer/Counter2 Compare Match B
jmp irqNotSet ; 12: TIMER2_OVF Timer/Counter2 Overflow
jmp irqNotSet ; 13: TIMER1_CAPT Timer/Counter1 Capture Event
jmp irqNotSet ; 14: TIMER1_COMPA Timer/Counter1 Compare Match A
jmp irqNotSet ; 15: TIMER1_COMPB Timer/Counter1 Compare Match B
jmp irqNotSet ; 16: TIMER1_OVF Timer/Counter1 Overflow
jmp irqNotSet ; 17: TIMER0_COMPA Timer/Counter0 Compare Match A
jmp irqNotSet ; 18: TIMER0_COMPB Timer/Counter0 Compare Match B
jmp irqNotSet ; 19: TIMER0_OVF Timer/Counter0 Overflow
jmp irqNotSet ; 20: SPI_STC Serial Transfer Complete
jmp irqNotSet ; 21: USART0_RXC USART0 Rx Complete
jmp irqNotSet ; 22: USART0_UDRE USART0 Data Register Empty
jmp irqNotSet ; 23: USART0_TXC USART0 Tx Complete
jmp irqNotSet ; 24: ANA_COMP Analog Comparator
jmp irqNotSet ; 25: ADC ADC Conversion Complete
jmp irqNotSet ; 26: EE_RDY EEPROM Ready
jmp irqNotSet ; 27: TWI 2-Wire Interface
jmp irqNotSet ; 28: SPM_RDY Store Program Memory Ready
; ---------------------------------------------------------------------------
; Device Info Block
devInfoBlock: ; 12 bytes
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
devInfoId: .db DEVICEINFO_ID, 0
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
firmwareVersion: .db FIRMWARE_VARIANT_BOOT, FIRMWARE_VERSION_MAJOR
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
firmwareStart:
jmp main ; will be overwritten when flashing
irqNotSet:
reti
; ***************************************************************************
; main code
.org BOOTLOADER_ADDR
main:
; ldi r16, 0xb0 ; orig: a0
; out OSCCAL, r16
jmp bootLoader ; this routine is in modules/bootloader/main.asm
; ***************************************************************************
; includes
.include "common/wait_10us.asm"
.include "common/utils_copy_from_flash.asm"
.include "common/utils_copy_sdram.asm"
.include "modules/flash/defs.asm"
.include "modules/flash/eeprom.asm"
.include "modules/flash/io.asm"
.include "modules/flash/io_attn.asm"
.include "modules/flash/io_bitbang.asm"
.include "modules/flash/flash1pmega.asm"
.include "modules/flash/flashxp.asm"
.include "modules/flash/flashprocess.asm"
.include "modules/flash/wait.asm"
.include "modules/bootloader/main.asm"
.include "modules/network/msg/defs.asm"
.include "modules/network/msg/crc.asm"
;.include "common/debug.asm"
systemSetSpeed:
; speed not changeable at runtime on this device
ret

View File

@@ -1,175 +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. *
; ***************************************************************************
; ***************************************************************************
;
; AtMega644
; --------
; DSPLED PB0 1 40 PA0 DEV0
; DC PB1 2 39 PA1 DEV1
; INT2 PB2 3 38 PA2 DEV2
; DSPRES PB3 4 37 PA3 PA3
; SS PB4 5 36 PA4 PA4
; MOSI PB5 6 35 PA5
; MISO PB6 7 34 PA6
; SCK PB7 8 33 PA7
; /RESET 9 32 AREF
; VCC 10 31 GND
; GND 11 30 AVCC
; XTAL2 12 29 PC7
; XTAL1 13 28 PC6
; RXD PD0 14 27 PC5
; TXD PD1 15 26 PC4
; ATTN PD2 16 25 PC3
; INT1 PD3 17 24 PC2
; LED PD4 18 23 PC1
; PD5 19 22 PC0
; PD6 20 21 PD7
; --------
;
; ***************************************************************************
.equ BOOTLOADER_ADDR = 0x7c00
.equ FIRMWARE_VARIANT_BOOT = 0
.equ FIRMWARE_VARIANT_TEMP_WINDOW = 1
.equ DEVICEINFO_ID = 'C'
.equ DEVICEINFO_VERSION = 2
.equ DEVICEINFO_REVISION = 0
; ---------------------------------------------------------------------------
; LED module
.equ LED_SIMPLE_ONTIME = 1 ; shorter
.equ LED_SIMPLE_OFFTIME = 50 ; longer
.equ LED_SIMPLE_DDR = DDRD
.equ LED_SIMPLE_PORT = PORTD
.equ LED_SIMPLE_PORTIN = PIND
.equ LED_SIMPLE_PINNUM = PORTD4
; ---------------------------------------------------------------------------
; COM module
.equ COM_BIT_LENGTH = 52000 ; 104000ns=9600, 52000ns=19200, 26000ns=38400
.equ COM_HALFBIT_LENGTH = 26000 ; see https://de.wikipedia.org/wiki/Universal_Asynchronous_Receiver_Transmitter
.equ COM_DATA_DDR = DDRD
.equ COM_DATA_INPUT = PIND
.equ COM_DATA_OUTPUT = PORTD
.equ COM_DATA_PIN = PORTD0
.equ COM_ATTN_DDR = DDRD
.equ COM_ATTN_INPUT = PIND
.equ COM_ATTN_OUTPUT = PORTD
.equ COM_ATTN_PIN = PORTD2
.equ COM_IRQ_ADDR_ATTN = EIMSK
.equ COM_IRQ_BIT_ATTN = INT0
.equ COM_IRQ_GIFR_ATTN = INTF0
;.equ COM_IRQ_GIMSK_ATTN = PCIE0
; ---------------------------------------------------------------------------
; SPI hardware module
.equ SPIHW_SS_DDR = DDRB
.equ SPIHW_SS_INPUT = PINB
.equ SPIHW_SS_OUTPUT = PORTB
.equ SPIHW_SS_PIN = PORTB4
.equ SPIHW_MOSI_DDR = DDRB
.equ SPIHW_MOSI_INPUT = PINB
.equ SPIHW_MOSI_OUTPUT = PORTB
.equ SPIHW_MOSI_PIN = PORTB5
.equ SPIHW_MISO_DDR = DDRB
.equ SPIHW_MISO_INPUT = PINB
.equ SPIHW_MISO_OUTPUT = PORTB
.equ SPIHW_MISO_PIN = PORTB6
.equ SPIHW_SCK_DDR = DDRB
.equ SPIHW_SCK_INPUT = PINB
.equ SPIHW_SCK_OUTPUT = PORTB
.equ SPIHW_SCK_PIN = PORTB7
.equ SPIHW_SS0_DDR = DDRA
.equ SPIHW_SS0_OUTPUT = PORTA
.equ SPIHW_SS0_INPUT = PORTA
.equ SPIHW_SS0_PIN = PORTA0
.equ SPIHW_SS1_DDR = DDRA
.equ SPIHW_SS1_OUTPUT = PORTA
.equ SPIHW_SS1_INPUT = PORTA
.equ SPIHW_SS1_PIN = PORTA1
.equ SPIHW_SS2_DDR = DDRA
.equ SPIHW_SS2_OUTPUT = PORTA
.equ SPIHW_SS2_INPUT = PORTA
.equ SPIHW_SS2_PIN = PORTA2
; ---------------------------------------------------------------------------
; ILI9341 module
.equ ILI9341_DEVICENUM = 0
.equ ILI9341_DSP_WIDTH = 320
.equ ILI9341_DSP_HEIGHT = 240
.equ ILI9341_RESET_DDR = DDRB
.equ ILI9341_RESET_OUTPUT = PORTB
.equ ILI9341_RESET_INPUT = PORTB
.equ ILI9341_RESET_PIN = PORTB3
.equ ILI9341_DC_DDR = DDRB
.equ ILI9341_DC_OUTPUT = PORTB
.equ ILI9341_DC_INPUT = PORTB
.equ ILI9341_DC_PIN = PORTB1
.equ ILI9341_LED_DDR = DDRB
.equ ILI9341_LED_OUTPUT = PORTB
.equ ILI9341_LED_INPUT = PORTB
.equ ILI9341_LED_PIN = PORTB0
; ---------------------------------------------------------------------------
; ComOnUart module
;.equ USART0_DATAREG = UDR
;.equ UCSR0A = UCSRA
;.equ UCSR0B = UCSRB
;.equ UCSR0C = UCSRC
;.equ UBRR0L = UBRRL
;.equ UBRR0H = UBRRH
;.equ UCSZ00 = UCSZ0
;.equ UCSZ01 = UCSZ1
;.equ UDRE0 = UDRE
;.equ RXC0 = RXC
;.equ TXC0 = TXC
;.equ FE0 = FE
;.equ DOR0 = DOR
;.equ UPE0 = UPE
;.equ RXEN0 = RXEN
;.equ TXEN0 = TXEN
;.equ USBS0 = USBS
;.equ RXCIE0 = RXCIE
;.equ UDRIE0 = UDRIE

View File

@@ -1,450 +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 clock=1000000 ; Define the clock frequency
.equ clock=8000000 ; Define the clock frequency
.nolist
.include "include/m644Pdef.inc" ; Define device ATmega644P
.list
.include "version.asm"
.include "../defs.asm"
.include "./data.asm"
.include "devices/all/defs.asm"
.include "common/calls.asm"
.include "common/utils_wait.asm"
.include "common/utils_io.asm"
; ***************************************************************************
; defines
; ---------------------------------------------------------------------------
; generic
.equ STACK_SIZE = 256
.equ NET_BUFFERS_NUM = 8
.equ NET_BUFFERS_SIZE = 32
; ---------------------------------------------------------------------------
; firmware settings including list of modules used
; #define MODULES_TIMER
#define MODULES_CLOCK
;#define MODULES_XRAM
#define MODULES_HEAP
#define MODULES_LED_SIMPLE
#define MODULES_NETWORK
;#define MODULES_COMONUART0
;#define MODULES_UART_HW
#define MODULES_UART_BITBANG
#define MODULES_SPI_HW
#define MODULES_ILI9341
#define MODULES_FONT
#define MODULES_WIN
;#define MODULES_TWI_MASTER
;#define MODULES_LCD
;#define LCD_MINIMAL_FONT
;#define MODULES_SI7021
;#define MODULES_SGP30
;#define MODULES_SGP40
;#define MODULES_STATS
;#define MODULES_OWI_MASTER
;#define MODULES_DS18B20
;#define MODULES_MOTION
;#define MODULES_CCS811
#define APPS_NETWORK
;#define APPS_MOTION
;#define APPS_REPORTSENSORS
#define APPS_STATS
; ---------------------------------------------------------------------------
; defines for values
.equ VALUE_ID_SI7021_TEMP = 0x01
.equ VALUE_ID_SI7021_HUM = 0x02
.equ VALUE_ID_ADC = 0x03
;.equ VALUE_ID_DS18B20_TEMP = 0x06
.equ VALUE_ID_MOTION = 0x07
.equ VALUE_ID_SGP40_TVOC = 0x08
.equ VALUE_ID_SGP30_TVOC = 0x09
.equ VALUE_ID_SGP30_CO2 = 0x0a
;.equ VALUE_ID_REED_CONF = 0x81
.equ VALUE_ID_DEBUG = 0x7f
.equ VALUE_ID_LEDSIMPLE_TIMING = 0x88
; ***************************************************************************
; code segment
.cseg
.org 000000
; ---------------------------------------------------------------------------
; Reset and interrupt vectors
jmp BOOTLOADER_ADDR ; 1: Reset vector RESET
jmp UART_BitBang_PcintIsr ; 2: INT0 External Interrupt Request 0
jmp irqNotSet ; 3: INT1 External Interrupt Request 1
jmp irqNotSet ; 4: INT2 External Interrupt Request 2
jmp irqNotSet ; 5: PCINT0 Pin Change Interrupt Request 0
jmp irqNotSet ; 6: PCINT1 Pin Change Interrupt Request 1
jmp irqNotSet ; 7: PCINT2 Pin Change Interrupt Request 2
jmp irqNotSet ; 8: PCINT3 Pin Change Interrupt Request 3
jmp irqNotSet ; 9: WDT Watchdog Time-out Interrupt
jmp irqNotSet ; 10: TIMER2_COMPA Timer/Counter2 Compare Match A
jmp irqNotSet ; 11: TIMER2_COMPB Timer/Counter2 Compare Match B
jmp irqNotSet ; 12: TIMER2_OVF Timer/Counter2 Overflow
jmp irqNotSet ; 13: TIMER1_CAPT Timer/Counter1 Capture Event
jmp irqNotSet ; 14: TIMER1_COMPA Timer/Counter1 Compare Match A
jmp irqNotSet ; 15: TIMER1_COMPB Timer/Counter1 Compare Match B
jmp irqNotSet ; 16: TIMER1_OVF Timer/Counter1 Overflow
jmp baseTimerIrqOC0A ; 17: TIMER0_COMPA Timer/Counter0 Compare Match A
jmp irqNotSet ; 18: TIMER0_COMPB Timer/Counter0 Compare Match B
jmp irqNotSet ; 19: TIMER0_OVF Timer/Counter0 Overflow
jmp irqNotSet ; 20: SPI_STC Serial Transfer Complete
jmp irqNotSet ; 21: USART0_RXC USART0 Rx Complete
jmp irqNotSet ; 22: USART0_UDRE USART0 Data Register Empty
jmp irqNotSet ; 23: USART0_TXC USART0 Tx Complete
jmp irqNotSet ; 24: ANA_COMP Analog Comparator
jmp irqNotSet ; 25: ADC ADC Conversion Complete
jmp irqNotSet ; 26: EE_RDY EEPROM Ready
jmp irqNotSet ; 27: TWI 2-Wire Interface
jmp irqNotSet ; 28: SPM_RDY Store Program Memory Ready
devInfoBlock: ; 12 bytes
devInfoManufacturer: .db 'A', 'Q', 'U', 'A'
devInfoId: .db DEVICEINFO_ID, 0
devInfoVersion: .db DEVICEINFO_VERSION, DEVICEINFO_REVISION ; version, revision
firmwareVersion: .db FIRMWARE_VARIANT_TEMP_WINDOW, FIRMWARE_VERSION_MAJOR
.db FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCHLEVEL
; ---------------------------------------------------------------------------
; @routine firmwareStart @global
firmwareStart:
rjmp main
; @end
irqNotSet:
reti
; ---------------------------------------------------------------------------
; @routine onSystemStart
onSystemStart:
bigcall test
ret
; @end
; ---------------------------------------------------------------------------
; @routine onMessageReceived
;
; Called on every message received
onMessageReceived:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine onEvery100ms
;
; Called every 100ms. Add your routine calls here. No arguments, no results.
onEvery100ms:
onEverySecond:
onEveryMinute:
onEveryHour:
onEveryDay:
ret
; @end
; ---------------------------------------------------------------------------
; @routine onEveryLoop
;
; Called on every loop (i.e. after awakening from sleep).
;
onEveryLoop:
ret
; @end
; ***************************************************************************
; includes
.include "devices/all/hw_m644p.asm"
.include "devices/all/includes.asm"
;.include "common/debug.asm"
;.include "modules/lcd2/font/font2.asm"
;.include "modules/lcd2/font/font3.asm"
;.include "modules/lcd2/font/font16x26.asm"
;.include "modules/lcd2/font/font4.asm"
;.include "modules/lcd2/font/font12x16.asm"
.include "modules/lcd2/font/font5.asm"
.include "modules/lcd2/font/font12x20.asm"
;.include "common/list_t.asm"
.include "common/tree_t.asm"
.include "common/divide.asm"
; ---------------------------------------------------------------------------
; defines for network interface
;.equ netInterfaceData = netUartIface
.equ netInterfaceData = uart_bitbang_iface
; @param %0 X
; @param %1 Y
; @param %2 W
; @param %3 H
.macro M_FILL_RECT
ldi r16, LOW(@0) ; X0
mov r4, r16
ldi r16, HIGH(@0)
mov r5, r16
ldi r16, LOW(@1) ; Y0
mov r6, r16
ldi r16, HIGH(@1)
mov r7, r16
ldi r16, LOW(@2) ; W
mov r8, r16
ldi r16, HIGH(@2)
mov r9, r16
ldi r16, LOW(@3) ; H
mov r10, r16
ldi r16, HIGH(@3)
mov r11, r16
bigcall ILI9341_FillRect
.endmacro
test:
; set foreground (r3:r2)
; 0bRRRRRGGGGGGBBBBB
ldi r16, 0b11111111
mov r3, r16
ldi r16, 0b11111111 ; white
mov r2, r16
M_FILL_RECT 0, 0, 319, 239
; set foreground (r3:r2)
ldi r16, 0b00000000
mov r3, r16
ldi r16, 0b00011111 ; blue
mov r2, r16
M_FILL_RECT 0, 0, 319, 32
; set background (r1:r0)
mov r0, r2
mov r1, r3
; set foreground (r3:r2)
ldi r16, 0b11111111
mov r3, r16
ldi r16, 0b11111111 ; white
mov r2, r16
; set Xpos
ldi r16, LOW(10)
mov r4, r16
ldi r16, HIGH(10)
mov r5, r16
; setYpos
ldi r16, LOW(3)
mov r6, r16
ldi r16, HIGH(3)
mov r7, r16
; set font
; ldi zl, LOW(font3_16x26*2)
; ldi zh, HIGH(font3_16x26*2)
ldi zl, LOW(font5_12x20*2)
ldi zh, HIGH(font5_12x20*2)
; set buffer
ldi xl, LOW(glyphBuffer)
ldi xh, HIGH(glyphBuffer)
; write characters
ldi r16, 'A'
bigcall ili9341_WriteCharacterX1At
ldi r16, 'Q'
bigcall ili9341_WriteCharacterX1At
ldi r16, 'H'
bigcall ili9341_WriteCharacterX1At
ldi r16, 'O'
bigcall ili9341_WriteCharacterX1At
ldi r16, 'M'
bigcall ili9341_WriteCharacterX1At
ldi r16, 'E'
bigcall ili9341_WriteCharacterX1At
#if 0
push xl
push xh
rcall listTest1
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall listTest2
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall listTest3
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall listTest4
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
#endif
#if 1
push xl
push xh
rcall treeTest1
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall treeTest2
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall treeTest3
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
push xl
push xh
rcall treeTest4
pop xh
pop xl
brcc test_error
ldi r16, '!'
bigcall ili9341_WriteCharacterX1At
#endif
ret
test_error:
ldi r17, '0'
add r16, r17
bigcall ili9341_WriteCharacterX1At
ret
helloWorld: .db "Hello World", 0
.dseg
glyphBuffer: .byte 1024
heapStart:
.equ HEAP_START = heapStart
.equ HEAP_SIZE = (SRAM_SIZE-STACK_SIZE)-HEAP_START

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