diff --git a/apps/aqhome-nodes/main.c b/apps/aqhome-nodes/main.c index 0d6fc9e..b55b22d 100644 --- a/apps/aqhome-nodes/main.c +++ b/apps/aqhome-nodes/main.c @@ -36,6 +36,7 @@ #define CONNCLEAN_INTERVAL_IN_SECS 2 #define CONNCHECK_INTERVAL_IN_SECS 10 +#define HEARTBEAT_INTERVAL_IN_SECS 120 /* every 2mins */ @@ -133,11 +134,13 @@ void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop) int timeout; time_t timeLastConnectionCleanup; time_t timeLastConnCheck; + time_t timeLastHeartbeat; timeout=AQH_NodeServer_GetTimeout(aqh); timeStart=time(NULL); - timeLastConnectionCleanup=time(NULL); - timeLastConnCheck=time(NULL); + timeLastConnectionCleanup=timeStart; + timeLastConnCheck=timeStart; + timeLastHeartbeat=timeStart; while(!stopService) { time_t now; @@ -162,6 +165,13 @@ void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop) timeLastConnCheck=now; } + if (_diffInSeconds(now, timeLastHeartbeat)>HEARTBEAT_INTERVAL_IN_SECS) { + DBG_INFO(NULL, "Sending heartbeat message"); + AQH_NodeServer_SendHeartbeat(aqh); + timeLastHeartbeat=now; + } + + if (timeout && (_diffInSeconds(now, timeStart)>timeout)) { DBG_INFO(NULL, "Timeout"); break; diff --git a/apps/aqhome-nodes/server.c b/apps/aqhome-nodes/server.c index 71fd547..5c57ef5 100644 --- a/apps/aqhome-nodes/server.c +++ b/apps/aqhome-nodes/server.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -811,6 +812,25 @@ void AQH_NodeServer_HandleTtyMsgs(AQH_OBJECT *o) +void AQH_NodeServer_SendHeartbeat(AQH_OBJECT *o) +{ + AQH_NODE_SERVER *xo; + + xo=GWEN_INHERIT_GETDATA(AQH_OBJECT, AQH_NODE_SERVER, o); + if (xo && xo->ttyEndpoint) { + AQH_MESSAGE *nodeMsg; + time_t t; + + t=time(0); + nodeMsg=AQH_HeartbeatMessage_new(0xf0, 0x00, AQH_MSG_TYPE_HEARTBEAT, (uint32_t) t); + AQH_Endpoint_AddMsgOut(xo->ttyEndpoint, nodeMsg); + AQH_NodeServer_WriteTtyMsgToLogFile(o, nodeMsg, "sending"); + DBG_ERROR(NULL, "Forwarding node message %d to node", AQH_NodeMessage_GetMsgType(nodeMsg)); + } +} + + + void _handleMsgFromTty(AQH_OBJECT *o, AQH_NODE_SERVER *xo, const AQH_MESSAGE *msg) { uint8_t code; diff --git a/apps/aqhome-nodes/server.h b/apps/aqhome-nodes/server.h index 44078a0..8e0b36d 100644 --- a/apps/aqhome-nodes/server.h +++ b/apps/aqhome-nodes/server.h @@ -57,6 +57,7 @@ void AQH_NodeServer_HandleClientMsgs(AQH_OBJECT *o); void AQH_NodeServer_HandleBrokerMsgs(AQH_OBJECT *o); void AQH_NodeServer_CheckBrokerConnection(AQH_OBJECT *o); void AQH_NodeServer_CheckTtyConnection(AQH_OBJECT *o); +void AQH_NodeServer_SendHeartbeat(AQH_OBJECT *o); /* getters and setters */ diff --git a/apps/aqhome-nodes/tty_log.c b/apps/aqhome-nodes/tty_log.c index 9c68417..e984268 100644 --- a/apps/aqhome-nodes/tty_log.c +++ b/apps/aqhome-nodes/tty_log.c @@ -23,6 +23,7 @@ #include "aqhome/msg/msg_sysstats.h" #include "aqhome/msg/msg_ping.h" #include "aqhome/msg/msg_pong.h" +#include "aqhome/msg/m_heartbeat.h" #include "aqhome/msg/msg_needaddr.h" #include "aqhome/msg/msg_claimaddr.h" #include "aqhome/msg/msg_haveaddr.h" @@ -80,6 +81,7 @@ void AqHomed_LogTtyMsg(AQHOMED *aqh, const GWEN_MSG *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_HEARTBEAT: AQH_HeartbeatMessage_DumpToBuffer(msg, dbuf, "received"); break; case AQH_MSG_TYPE_COMSENDSTATS: AQH_SendStatsMsg_DumpToBuffer(msg, dbuf, "received"); break; case AQH_MSG_TYPE_COMRECVSTATS: AQH_RecvStatsMsg_DumpToBuffer(msg, dbuf, "received"); break; case AQH_MSG_TYPE_TWIBUSMEMBER: AQH_NodeMsg_DumpToBuffer(msg, dbuf, "received"); break; diff --git a/aqhome/msg/node/0BUILD b/aqhome/msg/node/0BUILD index 5737c40..5f4fd94 100644 --- a/aqhome/msg/node/0BUILD +++ b/aqhome/msg/node/0BUILD @@ -64,6 +64,7 @@ m_flashresponse.h m_range.h m_time.h + m_heartbeat.h @@ -93,6 +94,7 @@ m_flashresponse.c m_range.c m_time.c + m_heartbeat.c diff --git a/aqhome/msg/node/m_heartbeat.c b/aqhome/msg/node/m_heartbeat.c new file mode 100644 index 0000000..5221b11 --- /dev/null +++ b/aqhome/msg/node/m_heartbeat.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2026 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/node/m_heartbeat.h" +#include "aqhome/msg/node/m_node.h" + +#include +#include + + + +#define AQH_MSG_OFFS_HEARTBEAT_TIMESTAMP 0 /* 4 bytes */ + + + +AQH_MESSAGE *AQH_HeartbeatMessage_new(uint8_t destAddr, uint8_t srcAddr, uint8_t code, uint32_t timestamp) +{ + uint32_t payload; + + payload=GWEN_ENDIAN_HTOLE32(timestamp); + return AQH_NodeMessage_new(destAddr, srcAddr, code, sizeof(payload), (const uint8_t*)&payload); +} + + + +uint32_t AQH_HeartbeatMessage_GetTimestamp(const AQH_MESSAGE *msg) +{ + return AQH_Message_ReadUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_HEARTBEAT_TIMESTAMP, 0); +} + + + +void AQH_HeartbeatMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText) +{ + GWEN_Buffer_AppendArgs(dbuf, + "0x%02x->0x%02x: HEARTBEAT(%s) %s (uid=0x%08x)\n", + AQH_NodeMessage_GetSourceAddress(msg), + AQH_NodeMessage_GetDestAddress(msg), + AQH_NodeMessage_MsgTypeToChar(AQH_NodeMessage_GetMsgType(msg)), + sText, + (unsigned int) AQH_HeartbeatMessage_GetTimestamp(msg)); +} + + diff --git a/aqhome/msg/node/m_heartbeat.h b/aqhome/msg/node/m_heartbeat.h new file mode 100644 index 0000000..6c9f0a7 --- /dev/null +++ b/aqhome/msg/node/m_heartbeat.h @@ -0,0 +1,28 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2026 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_M_HEARTBEAT_H +#define AQH_M_HEARTBEAT_H + + +#include +#include + +#include + + +AQHOME_API AQH_MESSAGE *AQH_HeartbeatMessage_new(uint8_t destAddr, uint8_t srcAddr, uint8_t code, uint32_t timestamp); +AQHOME_API uint32_t AQH_HeartbeatMessage_GetTimestamp(const AQH_MESSAGE *msg); + +AQHOME_API void AQH_HeartbeatMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText); + + + + + +#endif diff --git a/aqhome/msg/node/m_node.c b/aqhome/msg/node/m_node.c index 8871d8c..04060d8 100644 --- a/aqhome/msg/node/m_node.c +++ b/aqhome/msg/node/m_node.c @@ -21,6 +21,7 @@ #include "aqhome/msg/node/m_needaddr.h" #include "aqhome/msg/node/m_ping.h" #include "aqhome/msg/node/m_pong.h" +#include "aqhome/msg/node/m_heartbeat.h" #include "aqhome/msg/node/m_reboot.h" #include "aqhome/msg/node/m_value.h" #include "aqhome/msg/node/m_flashstart.h" @@ -29,6 +30,7 @@ #include "aqhome/msg/node/m_flashready.h" #include "aqhome/msg/node/m_flashresponse.h" #include "aqhome/msg/node/m_range.h" +#include "aqhome/msg/node/m_time.h" #include @@ -202,6 +204,7 @@ const char *AQH_NodeMessage_MsgTypeToChar(uint8_t i) switch(i) { case AQH_MSG_TYPE_PING: return "Ping"; case AQH_MSG_TYPE_PONG: return "Pong"; + case AQH_MSG_TYPE_HEARTBEAT: return "Heartbeat"; case AQH_MSG_TYPE_COMSENDSTATS: return "SendStats"; case AQH_MSG_TYPE_COMRECVSTATS: return "RecvStats"; case AQH_MSG_TYPE_TWIBUSMEMBER: return "TwiBusMember"; @@ -245,6 +248,7 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d switch(AQH_NodeMessage_GetMsgType(msg)) { case AQH_MSG_TYPE_PING: AQH_PingMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_PONG: AQH_PongMessage_DumpToBuffer(msg, dbuf, sText); break; + case AQH_MSG_TYPE_HEARTBEAT: AQH_HeartbeatMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_COMSENDSTATS: AQH_SendStatsMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_COMRECVSTATS: AQH_RecvStatsMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_NEED_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break; diff --git a/aqhome/msg/node/m_node.h b/aqhome/msg/node/m_node.h index 0f6b356..ec1aacf 100644 --- a/aqhome/msg/node/m_node.h +++ b/aqhome/msg/node/m_node.h @@ -29,6 +29,7 @@ #define AQH_MSG_TYPE_PING 10 #define AQH_MSG_TYPE_PONG 11 +#define AQH_MSG_TYPE_HEARTBEAT 12 #define AQH_MSG_TYPE_COMSENDSTATS 22 #define AQH_MSG_TYPE_COMRECVSTATS 23 #define AQH_MSG_TYPE_TWIBUSMEMBER 30 diff --git a/avr/devices/e02/defs.asm b/avr/devices/e02/defs.asm index 4ea31b6..52f2928 100644 --- a/avr/devices/e02/defs.asm +++ b/avr/devices/e02/defs.asm @@ -108,3 +108,13 @@ .equ USART0_DATAREG = UDR0 .equ USART1_DATAREG = UDR1 + +; --------------------------------------------------------------------------- +; MCP2221 + +.equ MCP2221_RESET_DDR = DDRB +.equ MCP2221_RESET_PORT = PORTB +.equ MCP2221_RESET_PINNUM = PORTB0 + + + diff --git a/avr/devices/e02/main/main.asm b/avr/devices/e02/main/main.asm index ba0b848..f39c742 100644 --- a/avr/devices/e02/main/main.asm +++ b/avr/devices/e02/main/main.asm @@ -72,30 +72,12 @@ #define APP_ROUTER_NO_ADDR_MGR #define MODULES_CLOCK -;#define MODULES_COM -;#define MODULES_COM_WITH_ADDR_PROTO -;#define MODULES_LED #define MODULES_LED_SIMPLE -;#define MODULES_LED_SIGNAL -;#define MODULES_LED_ACTIVITY -;#define MODULES_TWI_MASTER -;#define MODULES_LCD -;#define LCD_MINIMAL_FONT -;#define MODULES_SI7021 -;#define MODULES_STATS -;#define MODULES_CNY70 -;#define MODULES_REED -;#define MODULES_OWI_MASTER -;#define MODULES_DS18B20 -;#define MODULES_MOTION #define MODULES_NETWORK #define MODULES_COM2W -;#define MODULES_COMONUART0 -;#define MODULES_TTYONUART1 #define MODULES_UARTFD0 + #define APPS_STATS -;#define APPS_NETWORK -;#define APPS_ROUTER #define APPS_FORWARDER @@ -106,14 +88,17 @@ +.equ HEARTBEAT_MAXTIME_IN_MINS = 10 ; 10 minutes + +.equ LEDMCPRESET_ONTIME = 2 +.equ LEDMCPRESET_OFFTIME = 2 +.equ LEDMCPRESET_REPEATS = 50 ; 50*0.4=20s + ; --------------------------------------------------------------------------- ; defines for values -.equ VALUE_ID_DS18B20_TEMP = 0x06 - -.equ VALUE_ID_LEDSIMPLE_TIMING = 0x88 -;.equ VALUE_ID_ROUTER_SETRANGE = 0x89 +; none @@ -187,6 +172,30 @@ onSystemStart: ldi r16, 0xf0 sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r16 sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r16 + + ldi r16, HEARTBEAT_MAXTIME_IN_MINS + sts heartbeatTimer, r16 + + rcall resetMcp2221 + + ret +; @end + + + +onEveryMinute: + lds r16, heartbeatTimer + tst r16 + breq onEverySecond_ret + dec r16 + sts heartbeatTimer, r16 + brne onEverySecond_ret + + rcall resetMcp2221 + + ldi r16, HEARTBEAT_MAXTIME_IN_MINS + sts heartbeatTimer, r16 +onEverySecond_ret: ret ; @end @@ -194,7 +203,6 @@ onSystemStart: onEvery100ms: onEverySecond: -onEveryMinute: onEveryHour: onEveryDay: ret @@ -218,12 +226,48 @@ onEveryLoop: ; Called on every message received onMessageReceived: + adiw xh:xl, NETMSG_OFFS_CMD + ld r16, X + sbiw xh:xl, NETMSG_OFFS_CMD + cpi r16, NETMSG_CMD_HEARTBEAT + brne onMessageReceived_ret + ldi r16, HEARTBEAT_MAXTIME_IN_MINS + sts heartbeatTimer, r16 +onMessageReceived_ret: clc ret ; @end +; --------------------------------------------------------------------------- +; @routine resetMcp2221 +; +; Reset MCP2221 by pulling /RST low for 10us. + +resetMcp2221: + push r15 + inr r15, SREG + cli + sbi MCP2221_RESET_DDR, MCP2221_RESET_PINNUM ; out + cbi MCP2221_RESET_PORT, MCP2221_RESET_PINNUM ; set RST low + Utils_WaitNanoSecs 10000, 0, r22 ; minimum is 2us, use 10us to be safe + sbi MCP2221_RESET_PORT, MCP2221_RESET_PINNUM ; set RST high + outr SREG, r15 + pop r15 + +#ifdef MODULES_LED_SIMPLE + ldi r18, LEDMCPRESET_ONTIME + ldi r19, LEDMCPRESET_OFFTIME + ldi r20, LEDMCPRESET_REPEATS + bigcall LedSimple_SetTiming +#endif + + ret +; @end + + + @@ -249,3 +293,16 @@ deviceCodeEnd: .warning "Code reaches into boot loader!" .endif + + + +; *************************************************************************** +; data segment + +.dseg + +heartbeatTimer: .byte 1 + + + + diff --git a/avr/modules/network/msg/defs.asm b/avr/modules/network/msg/defs.asm index 8becdfd..113ad62 100644 --- a/avr/modules/network/msg/defs.asm +++ b/avr/modules/network/msg/defs.asm @@ -17,6 +17,7 @@ .equ NETMSG_CMD_PING = 10 .equ NETMSG_CMD_PONG = 11 +.equ NETMSG_CMD_HEARTBEAT = 12 .equ NETMSG_CMD_SENDSTATS = 22 .equ NETMSG_CMD_RECVSTATS = 23 .equ NETMSG_CMD_TWIBUSMEMBER = 30