aqhome: started reworking message code to use gwen's new msgio code.

This commit is contained in:
Martin Preuss
2023-03-18 00:57:03 +01:00
parent 8c00c94d9c
commit 6507f3896f
35 changed files with 2267 additions and 31 deletions

104
aqhome/msg/0BUILD Normal file
View File

@@ -0,0 +1,104 @@
<?xml?>
<gwbuild>
<target type="ConvenienceLibrary" name="aqhmsg" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
</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)/nodes" >
$(local/built_headers_pub)
</headers>
<headers dist="true" install="$(pkgincludedir)/nodes" >
endpointmgr.h
endpoint_node.h
endpoint_log.h
msg_node.h
msg_ping.h
msg_pong.h
msg_claimaddr.h
msg_denyaddr.h
msg_haveaddr.h
msg_needaddr.h
msg_sendstats.h
msg_value.h
</headers>
<headers dist="true" >
endpointmgr_p.h
endpoint_node_p.h
endpoint_log_p.h
msg_node_p.h
</headers>
<sources>
$(local/typefiles)
endpointmgr.c
endpoint_node.c
endpoint_log.c
msg_node.c
msg_ping.c
msg_pong.c
msg_claimaddr.c
msg_denyaddr.c
msg_haveaddr.c
msg_needaddr.c
msg_sendstats.c
msg_value.c
</sources>
<extradist>
</extradist>
<useTargets>
</useTargets>
<subdirs>
</subdirs>
</target>
</gwbuild>

159
aqhome/msg/endpoint_log.c Normal file
View File

@@ -0,0 +1,159 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/endpoint_log_p.h"
#include "aqhome/msg/msg_value.h"
#include "aqhome/msg/msg_sendstats.h"
#include "aqhome/msg/msg_ping.h"
#include "aqhome/msg/msg_pong.h"
#include "aqhome/msg/msg_needaddr.h"
#include "aqhome/msg/msg_claimaddr.h"
#include "aqhome/msg/msg_haveaddr.h"
#include "aqhome/msg/msg_denyaddr.h"
#include <gwenhywfar/list.h>
#include <gwenhywfar/inherit.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/gwentime.h>
#define AQH_MSG_ENDPOINT_LOG_NAME "log"
GWEN_INHERIT(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG)
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static void _run(GWEN_MSG_ENDPOINT *ep);
static void _logMessage(GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg);
static void _writeToLogFile(const char *filename, const char *txt);
GWEN_MSG_ENDPOINT *AQH_LogEndpoint_new(const char *filename, int groupId)
{
int fd;
GWEN_MSG_ENDPOINT *ep;
AQH_MSG_ENDPOINT_LOG *xep;
ep=GWEN_MsgEndpoint_new(AQH_MSG_ENDPOINT_LOG_NAME, groupId);
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_LOG, xep);
xep->filename=strdup(filename);
GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep, xep, _freeData);
AQH_NodeEndpoint_SetAcceptedMsgGroups(ep, AQH_MSG_TYPEGROUP_ALL);
GWEN_MsgEndpoint_AddFlags(ep, GWEN_MSG_ENDPOINT_FLAGS_NOIO);
GWEN_MsgEndpoint_SetRunFn(ep, _run);
return ep;
}
void _freeData(void *bp, void *p)
{
AQH_MSG_ENDPOINT_LOG *xep;
xep=(AQH_MSG_ENDPOINT_LOG*) p;
free(xep->filename);
GWEN_FREE_OBJECT(xep);
}
void _run(GWEN_MSG_ENDPOINT *ep)
{
GWEN_MSG_LIST *msgList;
msgList=GWEN_MsgEndpoint_GetSendMessageList(ep);
if (msgList && GWEN_Msg_List_GetCount(msgList)) {
GWEN_MSG *msg;
msg=GWEN_Msg_List_First(msgList);
while(msg) {
GWEN_MSG *next;
next=GWEN_Msg_List_Next(msg);
if (GWEN_Msg_GetGroupId(msg)==GWEN_MsgEndpoint_GetGroupId(ep))
_logMessage(ep, msg);
GWEN_Msg_free(msg);
msg=next;
}
}
}
void _logMessage(GWEN_MSG_ENDPOINT *ep, const GWEN_MSG *msg)
{
AQH_MSG_ENDPOINT_LOG *xep;
const uint8_t *ptr;
uint8_t len;
uint8_t msgType;
int msgIsValid;
GWEN_BUFFER *dbuf;
GWEN_TIME *ti;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep);
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
ti=GWEN_CurrentTime();
GWEN_Time_toString(ti, "YYYY-MM-DD hh:mm:ss ", dbuf);
GWEN_Time_free(ti);
ti=NULL;
msgIsValid=(AQH_NodeMsg_IsChecksumValid(msg) && AQH_NodeMsg_IsMsgComplete(msg));
ptr=GWEN_Msg_GetConstBuffer(msg);
len=GWEN_Msg_GetBytesInBuffer(msg);
msgType=AQH_NodeMsg_GetMsgType(msg);
switch(msgType) {
case AQH_MSG_TYPE_PING: AQH_PingMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_PONG: AQH_PongMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_COMSENDSTATS: AQH_SendStatsMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_TWIBUSMEMBER: AQH_NodeMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_DEBUG: AQH_NodeMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_VALUE: AQH_ValueMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_NEED_ADDRESS: AQH_NeedAddrMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_CLAIM_ADDRESS: AQH_ClaimAddrMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_HAVE_ADDRESS: AQH_HaveAddrMsg_DumpToBuffer(msg, dbuf, "received"); break;
case AQH_MSG_TYPE_DENY_ADDRESS: AQH_DenyAddrMsg_DumpToBuffer(msg, dbuf, "received"); break;
default: AQH_ValueMsg_DumpToBuffer(msg, dbuf, "received"); break;
}
_writeToLogFile(xep->filename, GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
}
void _writeToLogFile(const char *filename, const char *txt)
{
if (txt && *txt) {
FILE *f;
f=fopen(filename, "a+");
if (f) {
if (1!=fwrite(txt, strlen(txt), 1, f)) {
DBG_ERROR(AQH_LOGDOMAIN, "Error logging.");
}
fclose(f);
}
}
}

23
aqhome/msg/endpoint_log.h Normal file
View File

@@ -0,0 +1,23 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_ENDPOINT_LOG_H
#define AQH_ENDPOINT_LOG_H
#include "aqhome/msg/endpoint_node.h"
AQHOME_API GWEN_MSG_ENDPOINT *AQH_LogEndpoint_new(const char *filename, int groupId);
#endif

View File

@@ -0,0 +1,29 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_ENDPOINT_LOG_P_H
#define AQH_ENDPOINT_LOG_P_H
#include <aqhome/api.h>
#include "aqhome/msg/endpoint_log.h"
#include <gwenhywfar/list.h>
#include <gwenhywfar/inherit.h>
typedef struct AQH_MSG_ENDPOINT_LOG AQH_MSG_ENDPOINT_LOG;
struct AQH_MSG_ENDPOINT_LOG {
char *filename;
};
#endif

475
aqhome/msg/endpoint_node.c Normal file
View File

@@ -0,0 +1,475 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/endpoint_node_p.h"
#include "aqhome/msg/msg_node.h"
#include <gwenhywfar/inherit.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define AQH_MSG_ENDPOINT_NODE_NAME "node"
#define AQH_MSG_ENDPOINT_NODE_BAUDRATE B19200
#define AQH_MSG_ENDPOINT_NODE_BYTE_MICROSECS 520
#define AQH_MSG_ENDPOINT_NODE_BUFFERSIZE 128
GWEN_INHERIT(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE)
static int _getReadFd(GWEN_MSG_ENDPOINT *ep);
static int _getWriteFd(GWEN_MSG_ENDPOINT *ep);
static int _handleReadable(GWEN_MSG_ENDPOINT *ep, GWEN_UNUSED GWEN_MSG_ENDPOINT_MGR *emgr);
static int _handleWritable(GWEN_MSG_ENDPOINT *ep, GWEN_UNUSED GWEN_MSG_ENDPOINT_MGR *emgr);
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static int _startMsg(GWEN_MSG_ENDPOINT *ep);
static int _endMsg(GWEN_MSG_ENDPOINT *ep);
static int _isLineBusy(GWEN_MSG_ENDPOINT *ep);
static int _openDevice(GWEN_MSG_ENDPOINT *ep);
static int _attnLow(GWEN_MSG_ENDPOINT *ep);
static int _attnHigh(GWEN_MSG_ENDPOINT *ep);
static int _isAttnLow(GWEN_MSG_ENDPOINT *ep);
GWEN_MSG_ENDPOINT *AQH_MsgEndpointNode_new(const char *devicePath, int groupId)
{
GWEN_MSG_ENDPOINT *ep;
AQH_MSG_ENDPOINT_NODE *xep;
int fd;
ep=GWEN_MsgEndpoint_new(AQH_MSG_ENDPOINT_NODE_NAME, groupId);
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_NODE, xep);
GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep, xep, _freeData);
GWEN_MsgEndpoint_SetHandleReadableFn(ep, _handleReadable);
GWEN_MsgEndpoint_SetHandleWritableFn(ep, _handleWritable);
GWEN_MsgEndpoint_SetGetReadFdFn(ep, _getReadFd);
GWEN_MsgEndpoint_SetGetWriteFdFn(ep, _getWriteFd);
xep->deviceName=strdup(devicePath);
fd=_openDevice(ep);
if (fd<0) {
DBG_INFO(NULL, "here (%d)", fd);
GWEN_MsgEndpoint_free(ep);
return NULL;
}
GWEN_MsgEndpoint_SetFd(ep, fd);
_attnHigh(ep);
return ep;
}
void _freeData(void *bp, void *p)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=(AQH_MSG_ENDPOINT_NODE*) p;
GWEN_FREE_OBJECT(xep);
}
uint32_t AQH_NodeEndpoint_GetAcceptedMsgGroups(const GWEN_MSG_ENDPOINT *ep)
{
const AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep)
return xep->acceptedMsgGroups;
return 0;
}
void AQH_NodeEndpoint_SetAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep)
xep->acceptedMsgGroups=f;
}
void AQH_NodeEndpoint_AddAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep)
xep->acceptedMsgGroups|=f;
}
void AQH_NodeEndpoint_DelAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep)
xep->acceptedMsgGroups&=~f;
}
int _getReadFd(GWEN_MSG_ENDPOINT *ep)
{
return GWEN_MsgEndpoint_GetFd(ep);
}
int _getWriteFd(GWEN_MSG_ENDPOINT *ep)
{
return GWEN_MsgEndpoint_HaveMessageToSend(ep)?GWEN_MsgEndpoint_GetFd(ep):GWEN_ERROR_NO_DATA;
}
int _handleReadable(GWEN_MSG_ENDPOINT *ep, GWEN_UNUSED GWEN_MSG_ENDPOINT_MGR *emgr)
{
int rv;
uint8_t buffer[AQH_MSG_ENDPOINT_NODE_BUFFERSIZE];
int len;
int i;
DBG_DEBUG(GWEN_LOGDOMAIN, "Reading from endpoint %s", GWEN_MsgEndpoint_GetName(ep));
do {
rv=read(GWEN_MsgEndpoint_GetFd(ep), buffer, sizeof(buffer));
} while( (rv<0) && errno==EINTR);
if (rv<0) {
if (errno==EAGAIN || errno==EWOULDBLOCK)
return GWEN_ERROR_TRY_AGAIN;
DBG_ERROR(GWEN_LOGDOMAIN, "Error on read(): %s (%d)", strerror(errno), errno);
return GWEN_ERROR_IO;
}
else if (rv==0) {
DBG_ERROR(GWEN_LOGDOMAIN, "EOF met on read()");
return GWEN_ERROR_IO;
}
len=rv;
for (i=0; i<len; i++) {
GWEN_MSG *msg;
msg=GWEN_MsgEndpoint_GetCurrentlyReceivedMsg(ep);
if (msg==NULL) {
msg=GWEN_Msg_new(AQH_MSG_ENDPOINT_NODE_BUFFERSIZE);
GWEN_Msg_SetGroupId(msg, GWEN_MsgEndpoint_GetGroupId(ep));
GWEN_MsgEndpoint_SetCurrentlyReceivedMsg(ep, msg);
}
rv=GWEN_Msg_AddByte(msg, buffer[i]);
if (rv<0) {
DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}
rv=AQH_NodeMsg_IsMsgComplete(msg);
if (rv<0) {
/* invalid message */
DBG_ERROR(GWEN_LOGDOMAIN, "Invalid message, discarding");
GWEN_MsgEndpoint_SetCurrentlyReceivedMsg(ep, NULL);
rv=GWEN_MsgEndpoint_DiscardInput(ep);
if (rv<0) {
DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
else if (rv>0) {
/* complete msg received, add to list */
if (!AQH_NodeMsg_IsChecksumValid(msg)) {
DBG_ERROR(AQH_LOGDOMAIN, "Invalid checksum, discarding message");
GWEN_Text_DumpString(GWEN_Msg_GetBuffer(msg), GWEN_Msg_GetBytesInBuffer(msg), 6);
GWEN_MsgEndpoint_SetCurrentlyReceivedMsg(ep, NULL);
rv=GWEN_MsgEndpoint_DiscardInput(ep);
if (rv<0) {
DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
else {
GWEN_Msg_Attach(msg);
GWEN_MsgEndpoint_SetCurrentlyReceivedMsg(ep, NULL);
GWEN_MsgEndpoint_AddReceivedMessage(ep, msg);
}
}
} /* for */
return 0;
}
int _handleWritable(GWEN_MSG_ENDPOINT *ep, GWEN_UNUSED GWEN_MSG_ENDPOINT_MGR *emgr)
{
GWEN_MSG *msg;
DBG_DEBUG(GWEN_LOGDOMAIN, "Writing to endpoint %s", GWEN_MsgEndpoint_GetName(ep));
msg=GWEN_MsgEndpoint_GetFirstSendMessage(ep);
if (msg) {
uint8_t pos;
int remaining;
int rv;
pos=GWEN_Msg_GetCurrentPos(msg);
remaining=GWEN_Msg_GetRemainingBytes(msg);
if (remaining>0) {
const uint8_t *buf;
int fd;
if (pos==0) {
/* start new message */
rv=_isLineBusy(ep);
if (rv<0 || rv==1) {
DBG_ERROR(AQH_LOGDOMAIN, "Line busy, not sending");
usleep(100);
return 0;
}
rv=_startMsg(ep);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
fd=GWEN_MsgEndpoint_GetFd(ep);
/* start new message */
buf=GWEN_Msg_GetBuffer(msg)+pos;
do {
rv=write(fd, buf, remaining);
} while(rv<0 && errno==EINTR);
if (rv<0) {
if (errno==EAGAIN || errno==EWOULDBLOCK)
return GWEN_ERROR_TRY_AGAIN;
DBG_ERROR(GWEN_LOGDOMAIN, "Error on write(): %s (%d)", strerror(errno), errno);
return GWEN_ERROR_IO;
}
GWEN_Msg_IncCurrentPos(msg, rv);
if (rv==remaining) {
/* end current message */
rv=_endMsg(ep);
GWEN_Msg_List_Del(msg);
GWEN_Msg_free(msg);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
}
}
return 0;
}
int _openDevice(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
int fd;
int status;
int i;
struct termios options;
int rv;
int m;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
fd=open(xep->deviceName, O_NOCTTY | O_NDELAY | O_RDWR);
if (fd<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on open(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
rv=tcgetattr(fd, &(xep->previousOptions));
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on tcgetattr(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
memset(&options, 0, sizeof(options)); /* preset */
options.c_cflag=CLOCAL | CREAD | CS8;
options.c_iflag=IGNPAR | IGNBRK;
options.c_oflag=0;
options.c_lflag=0;
cfmakeraw(&options);
options.c_cc[VTIME]=0; /* read timeout in deciseconds */
options.c_cc[VMIN]=0; /* no minimum number of receive bytes */
rv=cfsetispeed(&options, AQH_MSG_ENDPOINT_NODE_BAUDRATE);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on cfsetispeed(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
rv=cfsetospeed(&options, AQH_MSG_ENDPOINT_NODE_BAUDRATE);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on cfsetospeed(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
rv=tcflush(fd, TCIOFLUSH);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on tcflush(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
rv=tcsetattr(fd, TCSANOW, &options);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on tcsetattr(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
return fd;
}
int _startMsg(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep->intendedAttnState==1) {
int rv;
rv=_attnLow(ep);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
usleep(AQH_MSG_ENDPOINT_NODE_BYTE_MICROSECS/5);
}
return 0;
}
int _endMsg(GWEN_MSG_ENDPOINT *ep)
{
/* TODO: flush before releasing ATTN */
_attnHigh(ep);
}
int _isLineBusy(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
if (xep->intendedAttnState==0) {
/* we pulled the line low ourselves, and because of the circuitry nobody can pull it high */
return 0;
}
return _isAttnLow(ep);
}
int _attnLow(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
int status;
int rv;
int fd;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
fd=GWEN_MsgEndpoint_GetFd(ep);
rv=ioctl(fd, TIOCMGET, &status); /* GET the State of MODEM bits in Status */
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
status |= TIOCM_DTR | TIOCM_RTS; /* clear the DTR pin (cave: signals inverted!) */
rv=ioctl(fd, TIOCMSET, &status);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
xep->intendedAttnState=0;
return 0;
}
int _attnHigh(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
int status;
int rv;
int fd;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
fd=GWEN_MsgEndpoint_GetFd(ep);
rv=ioctl(fd, TIOCMGET, &status);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
status |= TIOCM_DTR; /* Set the DTR pin */
status &= ~ (TIOCM_DTR | TIOCM_RTS); /* clear the DTR pin (cave: signals inverted!) */
rv=ioctl(fd, TIOCMSET, &status);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
xep->intendedAttnState=1;
return 0;
}
int _isAttnLow(GWEN_MSG_ENDPOINT *ep)
{
AQH_MSG_ENDPOINT_NODE *xep;
int status;
int rv;
int fd;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_MSG_ENDPOINT_NODE, ep);
fd=GWEN_MsgEndpoint_GetFd(ep);
rv=ioctl(fd, TIOCMGET, &status);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
return GWEN_ERROR_IO;
}
return (status & TIOCM_CTS)?1:0;
}

View File

@@ -0,0 +1,32 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSGENDPOINT_NODE_H
#define AQH_MSGENDPOINT_NODE_H
#include <aqhome/api.h>
#include <gwenhywfar/endpoint.h>
#define AQH_MSGEP_NODE_FLAGS_NOMESSAGES 0x0001
#define AQH_MSGEP_NODE_FLAGS_NOIO 0x0002
AQHOME_API GWEN_MSG_ENDPOINT *AQH_NodeEndpointNode_new(const char *devicePath, int groupId);
AQHOME_API uint32_t AQH_NodeEndpoint_GetAcceptedMsgGroups(const GWEN_MSG_ENDPOINT *ep);
AQHOME_API void AQH_NodeEndpoint_SetAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f);
AQHOME_API void AQH_NodeEndpoint_AddAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f);
AQHOME_API void AQH_NodeEndpoint_DelAcceptedMsgGroups(GWEN_MSG_ENDPOINT *ep, uint32_t f);
#endif

View File

@@ -0,0 +1,34 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSGENDPOINT_NODE_P_H
#define AQH_MSGENDPOINT_NODE_P_H
#include <aqhome/api.h>
#include "aqhome/msg/endpoint_node.h"
#include <termios.h>
typedef struct AQH_MSG_ENDPOINT_NODE AQH_MSG_ENDPOINT_NODE;
struct AQH_MSG_ENDPOINT_NODE {
uint32_t acceptedMsgGroups;
char *deviceName;
struct termios previousOptions;
int intendedAttnState;
};
#endif

165
aqhome/msg/endpointmgr.c Normal file
View File

@@ -0,0 +1,165 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/endpointmgr_p.h"
#include "aqhome/msg/msg_node.h"
#include "aqhome/msg/endpoint_node.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
GWEN_INHERIT(GWEN_MSG_ENDPOINT_MGR, AQH_MSG_ENDPOINT_MGR);
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
static void _handleEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep);
static void _handleNodeEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep);
static void _handleIpcEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep);
static void _distributeMsgFromNodeEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *srcEp, const GWEN_MSG *msg);
GWEN_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr)
{
GWEN_MSG_ENDPOINT_MGR *mgr;
AQH_MSG_ENDPOINT_MGR *xmgr;
mgr=GWEN_MsgEndpointMgr_new();
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_MGR, xmgr);
GWEN_INHERIT_SETDATA(GWEN_MSG_ENDPOINT_MGR, AQH_MSG_ENDPOINT_MGR, mgr, xmgr, _freeData);
xmgr->busAddr=busAddr;
return mgr;
}
void _freeData(void *bp, void *p)
{
AQH_MSG_ENDPOINT_MGR *xmgr;
xmgr=(AQH_MSG_ENDPOINT_MGR*) p;
GWEN_FREE_OBJECT(xmgr);
}
void _msgLoopOnce(GWEN_MSG_ENDPOINT_MGR *emgr)
{
GWEN_MSG_ENDPOINT_LIST *endpointList;
DBG_DEBUG(AQH_LOGDOMAIN, "Handle endpoint messages");
endpointList=GWEN_MsgEndpointMgr_GetEndpointList(emgr);
if (endpointList) {
GWEN_MSG_ENDPOINT *ep;
ep=GWEN_MsgEndpoint_List_First(endpointList);
while(ep) {
DBG_DEBUG(AQH_LOGDOMAIN, "- endpoint(%s)", GWEN_MsgEndpoint_GetName(ep));
_handleEndpoint(emgr, ep);
ep=GWEN_MsgEndpoint_List_Next(ep);
}
}
}
void _handleEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep)
{
switch(GWEN_MsgEndpoint_GetGroupId(ep)) {
case AQH_MSG_ENDPOINTGROUP_NODE: _handleNodeEndpoint(emgr, ep); break;
case AQH_MSG_ENDPOINTGROUP_IPC: _handleIpcEndpoint(emgr, ep); break;
default: break;
}
}
void _handleNodeEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep)
{
GWEN_MSG *msg;
while( (msg=GWEN_MsgEndpoint_TakeFirstReceivedMessage(ep)) ) {
DBG_INFO(AQH_LOGDOMAIN,
" - msg %d from %d to %d",
AQH_NodeMsg_GetMsgType(msg), AQH_NodeMsg_GetSourceAddress(msg), AQH_NodeMsg_GetDestAddress(msg));
_distributeMsgFromNodeEndpoint(emgr, ep, msg);
GWEN_Msg_free(msg);
}
}
void _handleIpcEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *ep)
{
/* TODO: handle IPC messages */
}
void _distributeMsgFromNodeEndpoint(GWEN_MSG_ENDPOINT_MGR *emgr, GWEN_MSG_ENDPOINT *srcEp, const GWEN_MSG *msg)
{
GWEN_MSG_ENDPOINT_LIST *endpointList;
endpointList=GWEN_MsgEndpointMgr_GetEndpointList(emgr);
if (endpointList) {
GWEN_MSG_ENDPOINT *ep;
int srcGroupId;
uint32_t msgGroup;
msgGroup=AQH_NodeMsg_GetMsgGroup(AQH_NodeMsg_GetMsgType(msg));
srcGroupId=GWEN_MsgEndpoint_GetGroupId(srcEp);
ep=GWEN_MsgEndpoint_List_First(endpointList);
while(ep) {
if (ep!=srcEp) {
uint32_t acceptedGroupIds;
uint32_t acceptedMsgGroups;
DBG_DEBUG(AQH_LOGDOMAIN, "- checking endpoint %s", GWEN_MsgEndpoint_GetName(ep));
acceptedGroupIds=AQH_NodeEndpoint_GetAcceptedMsgGroups(ep);
acceptedMsgGroups=AQH_NodeEndpoint_GetAcceptedMsgGroups(ep);
if (
!(GWEN_MsgEndpoint_GetFlags(ep) & AQH_MSGEP_NODE_FLAGS_NOMESSAGES) &&
(acceptedMsgGroups & msgGroup) &&
(acceptedGroupIds & srcGroupId)
) {
/* endpoint accepts this message */
DBG_DEBUG(AQH_LOGDOMAIN, " - endpoint %s accepts message", GWEN_MsgEndpoint_GetName(ep));
GWEN_MsgEndpoint_AddSendMessage(ep, GWEN_Msg_dup(msg));
}
else {
DBG_DEBUG(AQH_LOGDOMAIN, " - endpoint %s does not accept message", GWEN_MsgEndpoint_GetName(ep));
}
}
ep=GWEN_MsgEndpoint_List_Next(ep);
}
}
}

31
aqhome/msg/endpointmgr.h Normal file
View File

@@ -0,0 +1,31 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_ENDPOINT_MGR_H
#define AQH_MSG_ENDPOINT_MGR_H
#include <aqhome/api.h>
#include <gwenhywfar/endpointmgr.h>
#define AQH_MSG_ENDPOINTGROUP_NODE 1
#define AQH_MSG_ENDPOINTGROUP_IPC 2
AQHOME_API GWEN_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr);
#endif

View File

@@ -0,0 +1,29 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_ENDPOINT_MGR_P_H
#define AQH_MSG_ENDPOINT_MGR_P_H
#include <aqhome/api.h>
#include "aqhome/msg/endpointmgr.h"
typedef struct AQH_MSG_ENDPOINT_MGR AQH_MSG_ENDPOINT_MGR;
struct AQH_MSG_ENDPOINT_MGR {
uint8_t busAddr;
};
#endif

View File

@@ -0,0 +1,68 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_claimaddr.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_ClaimAddrMsg_GetUid(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_CLAIM_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_CLAIMADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_CLAIMADDR_UID;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
uint8_t AQH_ClaimAddrMsg_GetAddress(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_CLAIM_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_CLAIMADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_CLAIMADDR_ADDR;
return ptr[0];
}
return 0;
}
void AQH_ClaimAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_CLAIM_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_CLAIMADDR_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: CLAIM_ADDRESS %s (uid=0x%08x, address=0x%02x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_ClaimAddrMsg_GetUid(msg),
AQH_ClaimAddrMsg_GetAddress(msg));
}
}

View File

@@ -0,0 +1,37 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_CLAIMADDR_H
#define AQH_MSG_CLAIMADDR_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_CLAIMADDR_UID 0
#define AQH_MSG_OFFS_CLAIMADDR_ADDR 4
#define AQH_MSG_CLAIMADDR_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_CLAIMADDR_ADDR+1)
AQHOME_API uint32_t AQH_ClaimAddrMsg_GetUid(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_ClaimAddrMsg_GetAddress(const GWEN_MSG *msg);
AQHOME_API void AQH_ClaimAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

68
aqhome/msg/msg_denyaddr.c Normal file
View File

@@ -0,0 +1,68 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_denyaddr.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_DenyAddrMsg_GetUid(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_DENY_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_DENYADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_DENYADDR_UID;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
uint8_t AQH_DenyAddrMsg_GetAddress(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_DENY_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_DENYADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_DENYADDR_ADDR;
return ptr[0];
}
return 0;
}
void AQH_DenyAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_DENY_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_DENYADDR_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: DENY_ADDRESS %s (uid=0x%08x, address=0x%02x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_DenyAddrMsg_GetUid(msg),
AQH_DenyAddrMsg_GetAddress(msg));
}
}

37
aqhome/msg/msg_denyaddr.h Normal file
View File

@@ -0,0 +1,37 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_DENYADDR_H
#define AQH_MSG_DENYADDR_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_DENYADDR_UID 0
#define AQH_MSG_OFFS_DENYADDR_ADDR 4
#define AQH_MSG_DENYADDR_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_DENYADDR_ADDR+1)
AQHOME_API uint32_t AQH_DenyAddrMsg_GetUid(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_DenyAddrMsg_GetAddress(const GWEN_MSG *msg);
AQHOME_API void AQH_DenyAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

68
aqhome/msg/msg_haveaddr.c Normal file
View File

@@ -0,0 +1,68 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_haveaddr.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_HaveAddrMsg_GetUid(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_HAVE_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_HAVEADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_HAVEADDR_UID;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
uint8_t AQH_HaveAddrMsg_GetAddress(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_HAVE_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_HAVEADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_HAVEADDR_ADDR;
return ptr[0];
}
return 0;
}
void AQH_HaveAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_HAVE_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_HAVEADDR_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: HAVE_ADDRESS %s (uid=0x%08x, address=0x%02x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_HaveAddrMsg_GetUid(msg),
AQH_HaveAddrMsg_GetAddress(msg));
}
}

37
aqhome/msg/msg_haveaddr.h Normal file
View File

@@ -0,0 +1,37 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_HAVEADDR_H
#define AQH_MSG_HAVEADDR_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_HAVEADDR_UID 0
#define AQH_MSG_OFFS_HAVEADDR_ADDR 4
#define AQH_MSG_HAVEADDR_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_HAVEADDR_ADDR+1)
AQHOME_API uint32_t AQH_HaveAddrMsg_GetUid(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_HaveAddrMsg_GetAddress(const GWEN_MSG *msg);
AQHOME_API void AQH_HaveAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

53
aqhome/msg/msg_needaddr.c Normal file
View File

@@ -0,0 +1,53 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_needaddr.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_NeedAddrMsg_GetUid(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_NEED_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_NEEDADDR_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_NEEDADDR_UID;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
void AQH_NeedAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_NEED_ADDRESS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_NEEDADDR_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: NEED_ADDRESS %s (uid=0x%08x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_NeedAddrMsg_GetUid(msg));
}
}

35
aqhome/msg/msg_needaddr.h Normal file
View File

@@ -0,0 +1,35 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_NEEDADDR_H
#define AQH_MSG_NEEDADDR_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_NEEDADDR_UID 0
#define AQH_MSG_NEEDADDR_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_NEEDADDR_UID+4)
AQHOME_API uint32_t AQH_NeedAddrMsg_GetUid(const GWEN_MSG *msg);
AQHOME_API void AQH_NeedAddrMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

186
aqhome/msg/msg_node.c Normal file
View File

@@ -0,0 +1,186 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_node.h"
#include <gwenhywfar/debug.h>
static uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len);
uint8_t AQH_NodeMsg_GetDestAddress(const GWEN_MSG *msg)
{
if (msg && GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_OFFS_ALL_DATA_BEGIN) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg);
return ptr[AQH_MSG_OFFS_ALL_DEST_ADDRESS];
}
return 0;
}
uint8_t AQH_NodeMsg_GetMsgType(const GWEN_MSG *msg)
{
if (msg && GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_OFFS_ALL_DATA_BEGIN) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg);
return ptr[AQH_MSG_OFFS_ALL_MSG_TYPE];
}
return 0;
}
uint8_t AQH_NodeMsg_GetSourceAddress(const GWEN_MSG *msg)
{
if (msg && GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_OFFS_ALL_DATA_BEGIN) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg);
return ptr[AQH_MSG_OFFS_ALL_SRC_ADDRESS];
}
return 0;
}
uint8_t AQH_NodeMsg_GetMsgPayloadLen(const GWEN_MSG *msg)
{
if (msg && GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_OFFS_ALL_DATA_BEGIN) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg);
return ptr[AQH_MSG_OFFS_ALL_PAYLOAD_LEN];
}
return 0;
}
int AQH_NodeMsg_IsMsgComplete(const GWEN_MSG *msg)
{
if (msg) {
uint8_t msgLen;
msgLen=GWEN_Msg_GetBytesInBuffer(msg);
if (msgLen>=AQH_MSG_OFFS_ALL_DATA_BEGIN) {
const uint8_t *ptr;
uint8_t len;
ptr=GWEN_Msg_GetConstBuffer(msg);
len=ptr[AQH_MSG_OFFS_ALL_PAYLOAD_LEN]+AQH_MSG_OFFS_ALL_PAYLOAD_BEGIN+1;
if (len>AQH_MAXMSGSIZE)
return -1;
else if (msgLen>=len)
return 1;
}
}
return 0;
}
int AQH_NodeMsg_IsChecksumValid(const GWEN_MSG *msg)
{
if (msg && AQH_NodeMsg_IsMsgComplete(msg))
return (_calcChecksum(GWEN_Msg_GetConstBuffer(msg), GWEN_Msg_GetBytesInBuffer(msg))==0)?1:0;
return 0;
}
int AQH_NodeMsg_AddChecksum(GWEN_MSG *msg)
{
if (msg) {
int rv;
rv=GWEN_Msg_AddByte(msg, _calcChecksum(GWEN_Msg_GetConstBuffer(msg), GWEN_Msg_GetBytesInBuffer(msg)));
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}
return GWEN_ERROR_GENERIC;
}
void AQH_NodeMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: %d %s\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
AQH_NodeMsg_GetMsgType(msg),
sText);
}
uint32_t AQH_NodeMsg_GetMsgGroup(uint8_t msgType)
{
switch(msgType) {
case AQH_MSG_TYPE_PING:
case AQH_MSG_TYPE_PONG:
case AQH_MSG_TYPE_COMSENDSTATS:
case AQH_MSG_TYPE_COMRECVSTATS:
case AQH_MSG_TYPE_TWIBUSMEMBER:
case AQH_MSG_TYPE_DEBUG:
return AQH_MSG_TYPEGROUP_INFO;
case AQH_MSG_TYPE_VALUE:
return AQH_MSG_TYPEGROUP_VALUES;
case AQH_MSG_TYPE_NEED_ADDRESS:
case AQH_MSG_TYPE_HAVE_ADDRESS:
case AQH_MSG_TYPE_CLAIM_ADDRESS:
case AQH_MSG_TYPE_DENY_ADDRESS:
case AQH_MSG_TYPE_ADDRESS_RANGE:
return AQH_MSG_TYPEGROUP_ADDRESS;
case AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS:
return AQH_MSG_TYPEGROUP_ADMIN;
default:
return 0;
}
}
uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len)
{
int i;
uint8_t x=0;
for (i=0; i<len; i++, ptr++) {
x^=*ptr;
}
return x;
}

75
aqhome/msg/msg_node.h Normal file
View File

@@ -0,0 +1,75 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_NODE_H
#define AQH_MSG_NODE_H
#include <aqhome/api.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MAXMSGSIZE 16
#define AQH_MSG_OFFS_ALL_DEST_ADDRESS 0
#define AQH_MSG_OFFS_ALL_PAYLOAD_LEN 1
#define AQH_MSG_OFFS_ALL_PAYLOAD_BEGIN 2
#define AQH_MSG_OFFS_ALL_MSG_TYPE 2
#define AQH_MSG_OFFS_ALL_SRC_ADDRESS 3
#define AQH_MSG_OFFS_ALL_DATA_BEGIN 4
#define AQH_MSG_TYPE_PING 10
#define AQH_MSG_TYPE_PONG 11
#define AQH_MSG_TYPE_COMSENDSTATS 20
#define AQH_MSG_TYPE_COMRECVSTATS 21
#define AQH_MSG_TYPE_TWIBUSMEMBER 30
#define AQH_MSG_TYPE_DEBUG 40
#define AQH_MSG_TYPE_VALUE 50
#define AQH_MSG_TYPE_NEED_ADDRESS 60
#define AQH_MSG_TYPE_HAVE_ADDRESS 61
#define AQH_MSG_TYPE_CLAIM_ADDRESS 62
#define AQH_MSG_TYPE_DENY_ADDRESS 63
#define AQH_MSG_TYPE_ADDRESS_RANGE 64
/* internal msg types via NET interface */
#define AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS 200
#define AQH_MSG_TYPEGROUP_INFO 0x00000001
#define AQH_MSG_TYPEGROUP_VALUES 0x00000002
#define AQH_MSG_TYPEGROUP_ADDRESS 0x00000004
#define AQH_MSG_TYPEGROUP_FLASH 0x00000008
#define AQH_MSG_TYPEGROUP_ADMIN 0x00000010
#define AQH_MSG_TYPEGROUP_ALL 0xffffffff
AQHOME_API uint8_t AQH_NodeMsg_GetDestAddress(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_NodeMsg_GetMsgType(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_NodeMsg_GetSourceAddress(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_NodeMsg_GetMsgPayloadLen(const GWEN_MSG *msg);
AQHOME_API int AQH_NodeMsg_IsMsgComplete(const GWEN_MSG *msg);
AQHOME_API int AQH_NodeMsg_IsChecksumValid(const GWEN_MSG *msg);
AQHOME_API int AQH_NodeMsg_AddChecksum(GWEN_MSG *msg);
AQHOME_API void AQH_NodeMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
AQHOME_API uint32_t AQH_NodeMsg_GetMsgGroup(uint8_t msgType);
#endif

53
aqhome/msg/msg_ping.c Normal file
View File

@@ -0,0 +1,53 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_ping.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_PingMsg_GetTimestamp(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_PING) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_PING_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_PING_TIMESTAMP;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
void AQH_PingMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_PING) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_PING_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: PING %s (timestamp=0x%08x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_PingMsg_GetTimestamp(msg));
}
}

36
aqhome/msg/msg_ping.h Normal file
View File

@@ -0,0 +1,36 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_NODE_PING_H
#define AQH_MSG_NODE_PING_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_PING_TIMESTAMP 0
#define AQH_MSG_PING_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_PING_TIMESTAMP+4)
AQHOME_API uint32_t AQH_PingMsg_GetTimestamp(const GWEN_MSG *msg);
AQHOME_API void AQH_PingMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

53
aqhome/msg/msg_pong.c Normal file
View File

@@ -0,0 +1,53 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_pong.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_PongMsg_GetTimestamp(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_PONG) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_PONG_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_PONG_TIMESTAMP;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
void AQH_PongMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_PONG) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_PONG_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: PONG %s (timestamp=0x%08x)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_PongMsg_GetTimestamp(msg));
}
}

36
aqhome/msg/msg_pong.h Normal file
View File

@@ -0,0 +1,36 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_NODE_PONG_H
#define AQH_MSG_NODE_PONG_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_PONG_TIMESTAMP 0
#define AQH_MSG_PONG_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_PONG_TIMESTAMP+4)
AQHOME_API uint32_t AQH_PongMsg_GetTimestamp(const GWEN_MSG *msg);
AQHOME_API void AQH_PongMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

View File

@@ -0,0 +1,99 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_sendstats.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_SendStatsMsg_GetTimestamp(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_COMSENDSTATS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SENDSTATS_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_TIMESTAMP;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
uint16_t AQH_SendStatsMsg_GetPacketsOut(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_COMSENDSTATS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SENDSTATS_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_PACKETSOUT;
return (uint16_t)(ptr[0])+(ptr[1]<<8);
}
return 0;
}
uint16_t AQH_SendStatsMsg_GetCollisions(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_COMSENDSTATS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SENDSTATS_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_COLLISIONS;
return (uint16_t)(ptr[0])+(ptr[1]<<8);
}
return 0;
}
uint16_t AQH_SendStatsMsg_GetAborted(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_COMSENDSTATS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SENDSTATS_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_ABORTED;
return (uint16_t)(ptr[0])+(ptr[1]<<8);
}
return 0;
}
void AQH_SendStatsMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_COMSENDSTATS) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SENDSTATS_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf,
"0x%02x->0x%02x: SENDSTATS %s (timestamp=0x%08x, out=%d, collisions=%d, aborted=%d)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_SendStatsMsg_GetTimestamp(msg),
AQH_SendStatsMsg_GetPacketsOut(msg),
AQH_SendStatsMsg_GetCollisions(msg),
AQH_SendStatsMsg_GetAborted(msg));
}
}

View File

@@ -0,0 +1,44 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_SENDSTATS_H
#define AQH_MSG_SENDSTATS_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_SENDSTATS_TIMESTAMP 0
#define AQH_MSG_OFFS_SENDSTATS_PACKETSOUT 4
#define AQH_MSG_OFFS_SENDSTATS_COLLISIONS 6
#define AQH_MSG_OFFS_SENDSTATS_ABORTED 8
#define AQH_MSG_SENDSTATS_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SENDSTATS_ABORTED+2)
AQHOME_API uint32_t AQH_SendStatsMsg_GetTimestamp(const GWEN_MSG *msg);
AQHOME_API uint16_t AQH_SendStatsMsg_GetPacketsOut(const GWEN_MSG *msg);
AQHOME_API uint16_t AQH_SendStatsMsg_GetCollisions(const GWEN_MSG *msg);
AQHOME_API uint16_t AQH_SendStatsMsg_GetAborted(const GWEN_MSG *msg);
AQHOME_API void AQH_SendStatsMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif

121
aqhome/msg/msg_value.c Normal file
View File

@@ -0,0 +1,121 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqhome/msg/msg_value.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/error.h>
#include <gwenhywfar/debug.h>
uint32_t AQH_ValueMsg_GetTimestamp(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_TIMESTAMP;
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
}
return 0;
}
uint8_t AQH_ValueMsg_GetValueId(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_VALUEID;
return ptr[0];
}
return 0;
}
uint8_t AQH_ValueMsg_GetValueType(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE_MINSIZE)) {
const uint8_t *ptr;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_VALUETYPE;
return ptr[0];
}
return 0;
}
const char *AQH_ValueMsg_GetValueTypeName(const GWEN_MSG *msg)
{
uint8_t t;
t=AQH_ValueMsg_GetValueType(msg);
switch(t) {
case AQH_MSG_VALUE_TYPE_TEMP: return "temperature";
case AQH_MSG_VALUE_TYPE_HUMIDITY: return "humidity";
default: break;
}
return "unknown";
}
double AQH_ValueMsg_GetValue(const GWEN_MSG *msg)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE_MINSIZE)) {
const uint8_t *ptr;
double value;
double denom;
uint16_t intDenom;
ptr=GWEN_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN;
value=(double)((ptr[AQH_MSG_OFFS_VALUE_VALUE])+(ptr[AQH_MSG_OFFS_VALUE_VALUE+1]<<8));
intDenom=(ptr[AQH_MSG_OFFS_VALUE_DENOM])+(ptr[AQH_MSG_OFFS_VALUE_DENOM+1]<<8);
denom=(double)(intDenom);
if (intDenom==0)
denom=1.0;
return (double)(value/denom);
}
return 0.0;
}
void AQH_ValueMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
{
if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE) &&
(GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE_MINSIZE)) {
GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE %s (timestamp=0x%08x, value_id=0x%02x type=%s value=%f)\n",
AQH_NodeMsg_GetSourceAddress(msg),
AQH_NodeMsg_GetDestAddress(msg),
sText,
(unsigned int) AQH_ValueMsg_GetTimestamp(msg),
AQH_ValueMsg_GetValueId(msg),
AQH_ValueMsg_GetValueTypeName(msg),
AQH_ValueMsg_GetValue(msg));
}
}

47
aqhome/msg/msg_value.h Normal file
View File

@@ -0,0 +1,47 @@
/****************************************************************************
* This file is part of the project AqHome.
* 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.
****************************************************************************/
#ifndef AQH_MSG_VALUE_H
#define AQH_MSG_VALUE_H
#include <aqhome/api.h>
#include <aqhome/msg/msg_node.h>
#include <gwenhywfar/msg.h>
#include <gwenhywfar/buffer.h>
#define AQH_MSG_OFFS_VALUE_TIMESTAMP 0
#define AQH_MSG_OFFS_VALUE_VALUEID 4
#define AQH_MSG_OFFS_VALUE_VALUETYPE 5
#define AQH_MSG_OFFS_VALUE_VALUE 6
#define AQH_MSG_OFFS_VALUE_DENOM 8
#define AQH_MSG_VALUE_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE_DENOM+2)
#define AQH_MSG_VALUE_TYPE_TEMP 1
#define AQH_MSG_VALUE_TYPE_HUMIDITY 2
AQHOME_API uint32_t AQH_ValueMsg_GetTimestamp(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_ValueMsg_GetValueId(const GWEN_MSG *msg);
AQHOME_API uint8_t AQH_ValueMsg_GetValueType(const GWEN_MSG *msg);
AQHOME_API double AQH_ValueMsg_GetValue(const GWEN_MSG *msg);
AQHOME_API void AQH_ValueMsg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
#endif