277 lines
5.6 KiB
C
277 lines
5.6 KiB
C
/****************************************************************************
|
|
* 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 <config.h>
|
|
#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 <gwenhywfar/gwenhywfar.h>
|
|
#include <gwenhywfar/args.h>
|
|
#include <gwenhywfar/logger.h>
|
|
#include <gwenhywfar/db.h>
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/cgui.h>
|
|
#include <gwenhywfar/text.h>
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
# include <signal.h>
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* 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(aqh));
|
|
|
|
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(aqh);
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|