/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2024 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 "./init.h" #include "./fini.h" #include "./loop.h" #include "./net_read.h" #include "aqhome-react/units/u_timer.h" #include "aqhome/aqhome.h" #include #include #include #include #include #include #include #ifdef HAVE_SIGNAL_H # include #endif #include #include #include #include #include #include /* ------------------------------------------------------------------------------------------------ * defines * ------------------------------------------------------------------------------------------------ */ #define I18N(msg) msg #define I18S(msg) msg #define FULL_DEBUG #define AQHOME_REACT_READNET_INTERVAL 60 /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _serve(AQHOME_REACT *aqh); #ifdef HAVE_SIGNAL_H static int _setSignalHandlers(void); static int _setupSigAction(struct sigaction *sa, int sig); static void _signalHandler(int s); static struct sigaction saINT,saTERM, saHUP, saTSTP, saCONT; #endif /* ------------------------------------------------------------------------------------------------ * static vars * ------------------------------------------------------------------------------------------------ */ static int stopService=0; /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ int main(int argc, char **argv) { AQHOME_REACT *aqh; GWEN_DB_NODE *dbArgs; int rv; GWEN_GUI *gui; const char *s; rv=GWEN_Init(); if (rv) { fprintf(stderr, "ERROR: Unable to init Gwen.\n"); return 2; } GWEN_Logger_Open(0, "aqhome-react", 0, GWEN_LoggerType_Console, GWEN_LoggerFacility_User); GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Warning); rv=AQH_Init(); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return 2; } aqh=AqHomeReact_new(); rv=AqHomeReact_Init(aqh, argc, argv); if (rv<0) { if (rv==GWEN_ERROR_CLOSE) return 1; DBG_INFO(NULL, "here (%d)", rv); return 2; } dbArgs=AqHomeReact_GetDbArgs(aqh); gui=GWEN_Gui_CGui_new(); s=GWEN_DB_GetCharValue(dbArgs, "charset", 0, NULL); if (s && *s) GWEN_Gui_SetCharSet(gui, s); GWEN_Gui_SetGui(gui); _serve(aqh); AqHomeReact_Fini(aqh); AqHomeReact_free(aqh); GWEN_Gui_SetGui(NULL); GWEN_Gui_free(gui); return 0; } void _serve(AQHOME_REACT *aqh) { int rv; int timeout; time_t startTime; time_t lastTimerTime; time_t lastFileScanTime; GWEN_DB_NODE *dbArgs; AQHREACT_UNIT *timerUnit; startTime=time(NULL); lastTimerTime=startTime; lastFileScanTime=startTime; AqHomeReact_SetLatestNetworkFileTime(aqh, AQHomeReact_GetNewestUnitNetFiletime()); dbArgs=AqHomeReact_GetDbArgs(aqh); timerUnit=AqHomeReact_GetTimerUnit(aqh); rv=_setSignalHandlers(); if (rv<0) { DBG_ERROR(NULL, "Error setting signal handlers (%d)", rv); return; } timeout=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 0); while(!stopService) { time_t now; DBG_DEBUG(NULL, "Next loop"); AqHomeReact_IoLoop(aqh, 500); now=time(NULL); if (now!=lastTimerTime) { lastTimerTime=now; AqHomeReact_UnitTimer_GenerateTick(timerUnit); } AqHomeReact_ProcessAllUnits(aqh); if ((now-lastFileScanTime)>AQHOME_REACT_READNET_INTERVAL) { time_t tNew; time_t t; DBG_INFO(NULL, "Checking network files"); tNew=AQHomeReact_GetNewestUnitNetFiletime(); t=AqHomeReact_GetLatestNetworkFileTime(aqh); if (tNew && tNew>t) { DBG_INFO(NULL, "Reloading network files"); AqHomeReact_ReloadUnitNets(aqh); AqHomeReact_SetLatestNetworkFileTime(aqh, tNew); } lastFileScanTime=now; } if (timeout) { if ((now-startTime)>timeout) { DBG_ERROR(NULL, "Timeout, stopping service"); break; } } } /* while */ } int _setSignalHandlers(void) { #ifdef HAVE_SIGNAL_H int rv; rv=_setupSigAction(&saINT, SIGINT); if (rv) return rv; rv=_setupSigAction(&saTERM, SIGTERM); if (rv) return rv; rv=_setupSigAction(&saHUP, SIGHUP); if (rv) return rv; # ifdef SIGTSTP rv=_setupSigAction(&saTSTP, SIGTSTP); if (rv) return rv; # endif # ifdef SIGCONT rv=_setupSigAction(&saCONT, SIGCONT); if (rv) return rv; # endif #endif return 0; } int _setupSigAction(struct sigaction *sa, int sig) { sa->sa_handler=_signalHandler; sigemptyset(&sa->sa_mask); sa->sa_flags=0; if (sigaction(sig, sa, 0)) { DBG_ERROR(NULL, "Could not setup signal handler for signal %d", sig); return GWEN_ERROR_IO; } return 0; } void _signalHandler(int s) { switch(s) { case SIGINT: case SIGTERM: case SIGHUP: DBG_WARN(0, "Received signal %d, stopping service in next loop.",s); stopService=1; break; default: DBG_WARN(0, "Unknown signal %d",s); break; } }