From 6507f3896f06cde717bba0a41fc15a35871f54e7 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 18 Mar 2023 00:57:03 +0100 Subject: [PATCH] aqhome: started reworking message code to use gwen's new msgio code. --- aqhome/0BUILD | 2 + aqhome/libtest.c | 8 +- aqhome/msg/0BUILD | 104 ++++++++ aqhome/msg/endpoint_log.c | 159 ++++++++++++ aqhome/msg/endpoint_log.h | 23 ++ aqhome/msg/endpoint_log_p.h | 29 +++ aqhome/msg/endpoint_node.c | 475 +++++++++++++++++++++++++++++++++++ aqhome/msg/endpoint_node.h | 32 +++ aqhome/msg/endpoint_node_p.h | 34 +++ aqhome/msg/endpointmgr.c | 165 ++++++++++++ aqhome/msg/endpointmgr.h | 31 +++ aqhome/msg/endpointmgr_p.h | 29 +++ aqhome/msg/msg_claimaddr.c | 68 +++++ aqhome/msg/msg_claimaddr.h | 37 +++ aqhome/msg/msg_denyaddr.c | 68 +++++ aqhome/msg/msg_denyaddr.h | 37 +++ aqhome/msg/msg_haveaddr.c | 68 +++++ aqhome/msg/msg_haveaddr.h | 37 +++ aqhome/msg/msg_needaddr.c | 53 ++++ aqhome/msg/msg_needaddr.h | 35 +++ aqhome/msg/msg_node.c | 186 ++++++++++++++ aqhome/msg/msg_node.h | 75 ++++++ aqhome/msg/msg_ping.c | 53 ++++ aqhome/msg/msg_ping.h | 36 +++ aqhome/msg/msg_pong.c | 53 ++++ aqhome/msg/msg_pong.h | 36 +++ aqhome/msg/msg_sendstats.c | 99 ++++++++ aqhome/msg/msg_sendstats.h | 44 ++++ aqhome/msg/msg_value.c | 121 +++++++++ aqhome/msg/msg_value.h | 47 ++++ aqhome/msgendpointlog.c | 16 +- aqhome/msgendpointlog_p.h | 4 +- aqhome/msgendpointmanager.c | 18 +- aqhome/msgendpointmanager.h | 14 +- aqhome/msgendpointtcp.c | 2 +- 35 files changed, 2267 insertions(+), 31 deletions(-) create mode 100644 aqhome/msg/0BUILD create mode 100644 aqhome/msg/endpoint_log.c create mode 100644 aqhome/msg/endpoint_log.h create mode 100644 aqhome/msg/endpoint_log_p.h create mode 100644 aqhome/msg/endpoint_node.c create mode 100644 aqhome/msg/endpoint_node.h create mode 100644 aqhome/msg/endpoint_node_p.h create mode 100644 aqhome/msg/endpointmgr.c create mode 100644 aqhome/msg/endpointmgr.h create mode 100644 aqhome/msg/endpointmgr_p.h create mode 100644 aqhome/msg/msg_claimaddr.c create mode 100644 aqhome/msg/msg_claimaddr.h create mode 100644 aqhome/msg/msg_denyaddr.c create mode 100644 aqhome/msg/msg_denyaddr.h create mode 100644 aqhome/msg/msg_haveaddr.c create mode 100644 aqhome/msg/msg_haveaddr.h create mode 100644 aqhome/msg/msg_needaddr.c create mode 100644 aqhome/msg/msg_needaddr.h create mode 100644 aqhome/msg/msg_node.c create mode 100644 aqhome/msg/msg_node.h create mode 100644 aqhome/msg/msg_ping.c create mode 100644 aqhome/msg/msg_ping.h create mode 100644 aqhome/msg/msg_pong.c create mode 100644 aqhome/msg/msg_pong.h create mode 100644 aqhome/msg/msg_sendstats.c create mode 100644 aqhome/msg/msg_sendstats.h create mode 100644 aqhome/msg/msg_value.c create mode 100644 aqhome/msg/msg_value.h diff --git a/aqhome/0BUILD b/aqhome/0BUILD index 6eccb1f..31a5f8f 100644 --- a/aqhome/0BUILD +++ b/aqhome/0BUILD @@ -93,11 +93,13 @@ + msg nodes + aqhmsg aqhnodes diff --git a/aqhome/libtest.c b/aqhome/libtest.c index 12ee904..b9cfae6 100644 --- a/aqhome/libtest.c +++ b/aqhome/libtest.c @@ -388,24 +388,24 @@ int testEndpoints() if (rv<0) { } - emgr=AQH_MsgEndpointMgr_new(0xc0); + emgr=AQH_MsgEndpointManager_new(0xc0); epTty=AQH_MsgEndpointTty_new("/dev/ttyUSB0"); if (epTty==NULL) { DBG_ERROR(NULL, "Error creating endpoint TTY"); return 2; } - AQH_MsgEndpointMgr_AddEndpoint(emgr, epTty); + AQH_MsgEndpointManager_AddEndpoint(emgr, epTty); epLog=AQH_MsgEndpointLog_new("endpoints.log"); if (epLog==NULL) { DBG_ERROR(AQH_LOGDOMAIN, "Error creating endpoint LOG"); return 2; } - AQH_MsgEndpointMgr_AddEndpoint(emgr, epLog); + AQH_MsgEndpointManager_AddEndpoint(emgr, epLog); for (;;) { DBG_DEBUG(AQH_LOGDOMAIN, "Next loop"); - AQH_MsgEndpointMgr_LoopOnce(emgr); + AQH_MsgEndpointManager_LoopOnce(emgr); } return 0; diff --git a/aqhome/msg/0BUILD b/aqhome/msg/0BUILD new file mode 100644 index 0000000..89ccd7c --- /dev/null +++ b/aqhome/msg/0BUILD @@ -0,0 +1,104 @@ + + + + + + + + $(gwenhywfar_cflags) + -I$(topsrcdir) + -I$(topbuilddir) + + + + --include=$(builddir) + --include=$(srcdir) + + + + + + $(visibility_cflags) + + + + --api=AQHOME_API + + + + + + + + + + + + + + + + + + $(local/built_headers_pub) + + + + + 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 + + + + + endpointmgr_p.h + endpoint_node_p.h + endpoint_log_p.h + msg_node_p.h + + + + + $(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 + + + + + + + + + + + + + + + + + + + diff --git a/aqhome/msg/endpoint_log.c b/aqhome/msg/endpoint_log.c new file mode 100644 index 0000000..5409844 --- /dev/null +++ b/aqhome/msg/endpoint_log.c @@ -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 +#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 +#include +#include +#include + + +#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); + } + } +} + + + + + diff --git a/aqhome/msg/endpoint_log.h b/aqhome/msg/endpoint_log.h new file mode 100644 index 0000000..9d08b77 --- /dev/null +++ b/aqhome/msg/endpoint_log.h @@ -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 + diff --git a/aqhome/msg/endpoint_log_p.h b/aqhome/msg/endpoint_log_p.h new file mode 100644 index 0000000..d5d643c --- /dev/null +++ b/aqhome/msg/endpoint_log_p.h @@ -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 + +#include "aqhome/msg/endpoint_log.h" + +#include +#include + + +typedef struct AQH_MSG_ENDPOINT_LOG AQH_MSG_ENDPOINT_LOG; +struct AQH_MSG_ENDPOINT_LOG { + char *filename; +}; + + + +#endif + diff --git a/aqhome/msg/endpoint_node.c b/aqhome/msg/endpoint_node.c new file mode 100644 index 0000000..0d26037 --- /dev/null +++ b/aqhome/msg/endpoint_node.c @@ -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 +#endif + + +#include "aqhome/msg/endpoint_node_p.h" +#include "aqhome/msg/msg_node.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#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; i0) { + /* 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; +} + + + + + + + diff --git a/aqhome/msg/endpoint_node.h b/aqhome/msg/endpoint_node.h new file mode 100644 index 0000000..328b8e8 --- /dev/null +++ b/aqhome/msg/endpoint_node.h @@ -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 + +#include + + +#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 diff --git a/aqhome/msg/endpoint_node_p.h b/aqhome/msg/endpoint_node_p.h new file mode 100644 index 0000000..e0a70a1 --- /dev/null +++ b/aqhome/msg/endpoint_node_p.h @@ -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 + +#include "aqhome/msg/endpoint_node.h" + +#include + + + + +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 diff --git a/aqhome/msg/endpointmgr.c b/aqhome/msg/endpointmgr.c new file mode 100644 index 0000000..802450d --- /dev/null +++ b/aqhome/msg/endpointmgr.c @@ -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 +#endif + + +#include "aqhome/msg/endpointmgr_p.h" +#include "aqhome/msg/msg_node.h" +#include "aqhome/msg/endpoint_node.h" + +#include +#include + + + + +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); + } + } +} + + + + + + + + diff --git a/aqhome/msg/endpointmgr.h b/aqhome/msg/endpointmgr.h new file mode 100644 index 0000000..9b1471c --- /dev/null +++ b/aqhome/msg/endpointmgr.h @@ -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 + +#include + + + +#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 diff --git a/aqhome/msg/endpointmgr_p.h b/aqhome/msg/endpointmgr_p.h new file mode 100644 index 0000000..b2261f1 --- /dev/null +++ b/aqhome/msg/endpointmgr_p.h @@ -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 + +#include "aqhome/msg/endpointmgr.h" + + + + + +typedef struct AQH_MSG_ENDPOINT_MGR AQH_MSG_ENDPOINT_MGR; +struct AQH_MSG_ENDPOINT_MGR { + uint8_t busAddr; +}; + + + + +#endif diff --git a/aqhome/msg/msg_claimaddr.c b/aqhome/msg/msg_claimaddr.c new file mode 100644 index 0000000..994015d --- /dev/null +++ b/aqhome/msg/msg_claimaddr.c @@ -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 +#endif + +#include "aqhome/msg/msg_claimaddr.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_claimaddr.h b/aqhome/msg/msg_claimaddr.h new file mode 100644 index 0000000..834c993 --- /dev/null +++ b/aqhome/msg/msg_claimaddr.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_denyaddr.c b/aqhome/msg/msg_denyaddr.c new file mode 100644 index 0000000..cead745 --- /dev/null +++ b/aqhome/msg/msg_denyaddr.c @@ -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 +#endif + +#include "aqhome/msg/msg_denyaddr.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_denyaddr.h b/aqhome/msg/msg_denyaddr.h new file mode 100644 index 0000000..09d69a8 --- /dev/null +++ b/aqhome/msg/msg_denyaddr.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_haveaddr.c b/aqhome/msg/msg_haveaddr.c new file mode 100644 index 0000000..0020bf3 --- /dev/null +++ b/aqhome/msg/msg_haveaddr.c @@ -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 +#endif + +#include "aqhome/msg/msg_haveaddr.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_haveaddr.h b/aqhome/msg/msg_haveaddr.h new file mode 100644 index 0000000..7d75b7a --- /dev/null +++ b/aqhome/msg/msg_haveaddr.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_needaddr.c b/aqhome/msg/msg_needaddr.c new file mode 100644 index 0000000..6927f84 --- /dev/null +++ b/aqhome/msg/msg_needaddr.c @@ -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 +#endif + +#include "aqhome/msg/msg_needaddr.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_needaddr.h b/aqhome/msg/msg_needaddr.h new file mode 100644 index 0000000..a55bda6 --- /dev/null +++ b/aqhome/msg/msg_needaddr.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_node.c b/aqhome/msg/msg_node.c new file mode 100644 index 0000000..0c2ef43 --- /dev/null +++ b/aqhome/msg/msg_node.c @@ -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 +#endif + + +#include "aqhome/msg/msg_node.h" + +#include + + + +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 + +#include +#include + + +#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 diff --git a/aqhome/msg/msg_ping.c b/aqhome/msg/msg_ping.c new file mode 100644 index 0000000..85b8d2e --- /dev/null +++ b/aqhome/msg/msg_ping.c @@ -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 +#endif + +#include "aqhome/msg/msg_ping.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_ping.h b/aqhome/msg/msg_ping.h new file mode 100644 index 0000000..d575fab --- /dev/null +++ b/aqhome/msg/msg_ping.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_pong.c b/aqhome/msg/msg_pong.c new file mode 100644 index 0000000..363a600 --- /dev/null +++ b/aqhome/msg/msg_pong.c @@ -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 +#endif + +#include "aqhome/msg/msg_pong.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + diff --git a/aqhome/msg/msg_pong.h b/aqhome/msg/msg_pong.h new file mode 100644 index 0000000..693626d --- /dev/null +++ b/aqhome/msg/msg_pong.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_sendstats.c b/aqhome/msg/msg_sendstats.c new file mode 100644 index 0000000..861f521 --- /dev/null +++ b/aqhome/msg/msg_sendstats.c @@ -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 +#endif + +#include "aqhome/msg/msg_sendstats.h" + +#include +#include +#include +#include + + + +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)); + } +} + + + + + + + diff --git a/aqhome/msg/msg_sendstats.h b/aqhome/msg/msg_sendstats.h new file mode 100644 index 0000000..46b4884 --- /dev/null +++ b/aqhome/msg/msg_sendstats.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msg/msg_value.c b/aqhome/msg/msg_value.c new file mode 100644 index 0000000..1a678ed --- /dev/null +++ b/aqhome/msg/msg_value.c @@ -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 +#endif + +#include "aqhome/msg/msg_value.h" + +#include +#include +#include +#include + + + + +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)); + } +} + + + + + diff --git a/aqhome/msg/msg_value.h b/aqhome/msg/msg_value.h new file mode 100644 index 0000000..f8799e0 --- /dev/null +++ b/aqhome/msg/msg_value.h @@ -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 +#include + +#include +#include + + + +#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 + + + diff --git a/aqhome/msgendpointlog.c b/aqhome/msgendpointlog.c index 69d22fa..b40b022 100644 --- a/aqhome/msgendpointlog.c +++ b/aqhome/msgendpointlog.c @@ -29,7 +29,7 @@ -GWEN_INHERIT(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG) +GWEN_INHERIT(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG_OLD) static void GWENHYWFAR_CB _freeData(void *bp, void *p); @@ -45,12 +45,12 @@ AQH_MSG_ENDPOINT *AQH_MsgEndpointLog_new(const char *filename) { int fd; AQH_MSG_ENDPOINT *ep; - AQH_MSG_ENDPOINT_LOG *xep; + AQH_MSG_ENDPOINT_LOG_OLD *xep; ep=AQH_MsgEndpoint_new(-1, AQH_MSG_ENDPOINT_ENDPOINTGROUP_NET, "LOG"); - GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_LOG, xep); + GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_LOG_OLD, xep); xep->filename=strdup(filename); - GWEN_INHERIT_SETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep, xep, _freeData); + GWEN_INHERIT_SETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG_OLD, ep, xep, _freeData); AQH_MsgEndpoint_SetAcceptedEndpointGroups(ep, AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS); AQH_MsgEndpoint_SetAcceptedMsgGroups(ep, AQH_MSG_ENDPOINT_MSGGROUP_ALL); AQH_MsgEndpoint_AddFlags(ep, AQH_MSG_ENDPOINT_FLAGS_NOIO); @@ -63,9 +63,9 @@ AQH_MSG_ENDPOINT *AQH_MsgEndpointLog_new(const char *filename) void _freeData(void *bp, void *p) { - AQH_MSG_ENDPOINT_LOG *xep; + AQH_MSG_ENDPOINT_LOG_OLD *xep; - xep=(AQH_MSG_ENDPOINT_LOG*) p; + xep=(AQH_MSG_ENDPOINT_LOG_OLD*) p; free(xep->filename); GWEN_FREE_OBJECT(xep); } @@ -96,7 +96,7 @@ void _run(AQH_MSG_ENDPOINT *ep) void _logMessage(AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg) { - AQH_MSG_ENDPOINT_LOG *xep; + AQH_MSG_ENDPOINT_LOG_OLD *xep; const uint8_t *ptr; uint8_t len; uint8_t msgType; @@ -104,7 +104,7 @@ void _logMessage(AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg) GWEN_BUFFER *dbuf; GWEN_TIME *ti; - xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep); + xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG_OLD, ep); dbuf=GWEN_Buffer_new(0, 256, 0, 1); ti=GWEN_CurrentTime(); GWEN_Time_toString(ti, "YYYY-MM-DD hh:mm:ss ", dbuf); diff --git a/aqhome/msgendpointlog_p.h b/aqhome/msgendpointlog_p.h index 47bdb38..876b388 100644 --- a/aqhome/msgendpointlog_p.h +++ b/aqhome/msgendpointlog_p.h @@ -13,8 +13,8 @@ #include "aqhome/msgendpointlog.h" -typedef struct AQH_MSG_ENDPOINT_LOG AQH_MSG_ENDPOINT_LOG; -struct AQH_MSG_ENDPOINT_LOG { +typedef struct AQH_MSG_ENDPOINT_LOG_OLD AQH_MSG_ENDPOINT_LOG_OLD; +struct AQH_MSG_ENDPOINT_LOG_OLD { char *filename; }; diff --git a/aqhome/msgendpointmanager.c b/aqhome/msgendpointmanager.c index b8304f8..de01125 100644 --- a/aqhome/msgendpointmanager.c +++ b/aqhome/msgendpointmanager.c @@ -33,7 +33,7 @@ static uint32_t _getMsgGroup(uint8_t msgType); -AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr) +AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointManager_new(uint8_t busAddr) { AQH_MSG_ENDPOINT_MGR *emgr; @@ -45,7 +45,7 @@ AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr) -void AQH_MsgEndpointMgr_free(AQH_MSG_ENDPOINT_MGR *emgr) +void AQH_MsgEndpointManager_free(AQH_MSG_ENDPOINT_MGR *emgr) { if (emgr) { AQH_MsgEndpoint_List_free(emgr->endpointList); @@ -55,35 +55,35 @@ void AQH_MsgEndpointMgr_free(AQH_MSG_ENDPOINT_MGR *emgr) -uint8_t AQH_MsgEndpointMgr_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr) +uint8_t AQH_MsgEndpointManager_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr) { return emgr->busAddr; } -AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointMgr_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr) +AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointManager_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr) { return emgr->endpointList; } -void AQH_MsgEndpointMgr_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep) +void AQH_MsgEndpointManager_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep) { AQH_MsgEndpoint_List_Add(ep, emgr->endpointList); } -void AQH_MsgEndpointMgr_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep) +void AQH_MsgEndpointManager_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep) { AQH_MsgEndpoint_List_Del(ep); } -int AQH_MsgEndpointMgr_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr) +int AQH_MsgEndpointManager_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr) { int rv; @@ -175,7 +175,7 @@ int _ioLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr) if (rv<0 && rv!=GWEN_ERROR_TRY_AGAIN) { DBG_DEBUG(AQH_LOGDOMAIN, "error, removing endpoint %s", AQH_MsgEndpoint_GetName(ep)); fd=-1; - AQH_MsgEndpointMgr_DelEndpoint(emgr, ep); + AQH_MsgEndpointManager_DelEndpoint(emgr, ep); } } if (fd!=-1 && FD_ISSET(fd, &writeSet)) { @@ -184,7 +184,7 @@ int _ioLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr) if (rv<0 && rv!=GWEN_ERROR_TRY_AGAIN) { DBG_DEBUG(AQH_LOGDOMAIN, "error, removing endpoint %s", AQH_MsgEndpoint_GetName(ep)); fd=-1; - AQH_MsgEndpointMgr_DelEndpoint(emgr, ep); + AQH_MsgEndpointManager_DelEndpoint(emgr, ep); } } ep=epNext; diff --git a/aqhome/msgendpointmanager.h b/aqhome/msgendpointmanager.h index 54ee800..9bde4a4 100644 --- a/aqhome/msgendpointmanager.h +++ b/aqhome/msgendpointmanager.h @@ -22,17 +22,17 @@ typedef struct AQH_MSG_ENDPOINT_MGR AQH_MSG_ENDPOINT_MGR; -AQHOME_API AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr); -AQHOME_API void AQH_MsgEndpointMgr_free(AQH_MSG_ENDPOINT_MGR *emgr); +AQHOME_API AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointManager_new(uint8_t busAddr); +AQHOME_API void AQH_MsgEndpointManager_free(AQH_MSG_ENDPOINT_MGR *emgr); -AQHOME_API uint8_t AQH_MsgEndpointMgr_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr); +AQHOME_API uint8_t AQH_MsgEndpointManager_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr); -AQHOME_API AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointMgr_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr); +AQHOME_API AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointManager_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr); -AQHOME_API void AQH_MsgEndpointMgr_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep); -AQHOME_API void AQH_MsgEndpointMgr_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep); +AQHOME_API void AQH_MsgEndpointManager_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep); +AQHOME_API void AQH_MsgEndpointManager_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep); -AQHOME_API int AQH_MsgEndpointMgr_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr); +AQHOME_API int AQH_MsgEndpointManager_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr); diff --git a/aqhome/msgendpointtcp.c b/aqhome/msgendpointtcp.c index c98754e..45d6b66 100644 --- a/aqhome/msgendpointtcp.c +++ b/aqhome/msgendpointtcp.c @@ -202,7 +202,7 @@ int _handleReadable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr) AQH_MsgEndpoint_SetAcceptedMsgGroups(newEp, AQH_MsgEndpoint_GetAcceptedMsgGroups(ep)); AQH_MsgEndpoint_SetAcceptedEndpointGroups(newEp, AQH_MsgEndpoint_GetAcceptedEndpointGroups(ep)); - AQH_MsgEndpointMgr_AddEndpoint(emgr, newEp); + AQH_MsgEndpointManager_AddEndpoint(emgr, newEp); return 0; }