357 lines
7.8 KiB
C
357 lines
7.8 KiB
C
/****************************************************************************
|
|
* This file is part of the project AqHome.
|
|
* AqHome (c) by 2025 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 "./server.h"
|
|
#include "./net_read.h"
|
|
#include "aqhome-react/units/u_timer.h"
|
|
#include "aqhome-react/types/prgrule.h"
|
|
//#include "aqhome-react/types/prgrule-t.h"
|
|
|
|
#include "aqhome/aqhome.h"
|
|
#include "aqhome/data/path-t.h"
|
|
#include "aqhome/data/vars-t.h"
|
|
//#include "aqhome/data/vars_dbread-t.h"
|
|
//#include "aqhome/data/vars_dbwrite-t.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>
|
|
#include <gwenhywfar/testframework.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 300
|
|
#define AQHOME_REACT_SAVE_INTERVAL 300
|
|
|
|
#define CONNCLEAN_INTERVAL_IN_SECS 2
|
|
#define CONNCHECK_INTERVAL_IN_SECS 10
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop);
|
|
static int _diffInSeconds(time_t t1, time_t t0);
|
|
//static int _testModules(int argc, char **argv);
|
|
|
|
#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, saPIPE;
|
|
#endif
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* static vars
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static int stopService=0;
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int rv;
|
|
AQH_EVENT_LOOP *eventLoop;
|
|
AQH_OBJECT *aqh;
|
|
GWEN_GUI *gui;
|
|
|
|
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);
|
|
//GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Info);
|
|
|
|
rv=_setSignalHandlers();
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
rv=AQH_Init();
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return 2;
|
|
}
|
|
|
|
gui=GWEN_Gui_CGui_new();
|
|
GWEN_Gui_SetGui(gui);
|
|
|
|
eventLoop=AQH_EventLoop_new();
|
|
aqh=AQH_ReactServer_new(eventLoop);
|
|
rv=AQH_ReactServer_Init(aqh, argc, argv);
|
|
if (rv<0) {
|
|
if (rv==GWEN_ERROR_CLOSE)
|
|
return 1;
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return 2;
|
|
}
|
|
|
|
_runService(aqh, eventLoop);
|
|
|
|
AQH_ReactServer_Fini(aqh);
|
|
AQH_Object_free(aqh);
|
|
|
|
GWEN_Gui_SetGui(NULL);
|
|
GWEN_Gui_free(gui);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop)
|
|
{
|
|
time_t timeStart;
|
|
int timeout;
|
|
time_t timeLastConnCheck;
|
|
time_t lastFileScanTime;
|
|
time_t lastSaveTime;
|
|
|
|
timeout=AQH_ReactServer_GetTimeout(aqh);
|
|
timeStart=time(NULL);
|
|
timeLastConnCheck=time(NULL);
|
|
lastFileScanTime=timeStart;
|
|
lastSaveTime=timeStart;
|
|
|
|
AQH_ReactServer_SetLatestNetworkFileTime(aqh, AQH_ReactServer_GetNewestUnitNetFiletime());
|
|
|
|
while(!stopService) {
|
|
time_t now;
|
|
int rv;
|
|
|
|
AQH_EventLoop_Run(eventLoop, 2000);
|
|
AQH_ReactServer_HandleBrokerMsgs(aqh);
|
|
|
|
now=time(NULL);
|
|
|
|
if (_diffInSeconds(now, timeLastConnCheck)>CONNCHECK_INTERVAL_IN_SECS) {
|
|
DBG_INFO(NULL, "Check connections");
|
|
AQH_ReactServer_CheckBrokerConnection(aqh);
|
|
timeLastConnCheck=now;
|
|
}
|
|
|
|
AQH_ReactServer_ProcessAllUnits(aqh);
|
|
|
|
if (_diffInSeconds(now, lastFileScanTime)>AQHOME_REACT_READNET_INTERVAL) {
|
|
time_t tNew;
|
|
time_t t;
|
|
|
|
DBG_INFO(NULL, "Checking network files");
|
|
tNew=AQH_ReactServer_GetNewestUnitNetFiletime();
|
|
t=AQH_ReactServer_GetLatestNetworkFileTime(aqh);
|
|
if (tNew && tNew>t) {
|
|
DBG_INFO(NULL, "Reloading network files");
|
|
AQH_ReactServer_ReloadUnitNets(aqh);
|
|
AQH_ReactServer_SetLatestNetworkFileTime(aqh, tNew);
|
|
}
|
|
lastFileScanTime=now;
|
|
}
|
|
|
|
if (_diffInSeconds(now, lastSaveTime)>AQHOME_REACT_SAVE_INTERVAL) {
|
|
DBG_ERROR(NULL, "Writing var file");
|
|
rv=AQH_ReactServer_WriteVarsFile(aqh);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "Error writing runtime data");
|
|
}
|
|
lastSaveTime=time(NULL);
|
|
}
|
|
|
|
if (timeout && (_diffInSeconds(now, timeStart)>timeout)) {
|
|
DBG_INFO(NULL, "Timeout");
|
|
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;
|
|
|
|
rv=_setupSigAction(&saPIPE, SIGPIPE);
|
|
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;
|
|
case SIGPIPE:
|
|
DBG_WARN(0, "Received PIPE signal");
|
|
break;
|
|
default:
|
|
DBG_WARN(0, "Unknown signal %d",s);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
int _testModules(int argc, char **argv)
|
|
{
|
|
GWEN_GUI *gui;
|
|
GWEN_TEST_FRAMEWORK *tf;
|
|
int rv;
|
|
|
|
gui=GWEN_Gui_CGui_new();
|
|
GWEN_Gui_SetGui(gui);
|
|
|
|
tf=TestFramework_new();
|
|
|
|
rv=AQHREACT_PrgRule_AddTests(TestFramework_GetModulesRoot(tf));
|
|
if (rv<0) {
|
|
fprintf(stderr, "Adding module \"PrgRule\" failed.\n");
|
|
return 2;
|
|
}
|
|
|
|
rv=AQH_Path_AddTests(TestFramework_GetModulesRoot(tf));
|
|
if (rv<0) {
|
|
fprintf(stderr, "Adding module \"path\" failed.\n");
|
|
return 2;
|
|
}
|
|
|
|
rv=AQH_Vars_AddTests(TestFramework_GetModulesRoot(tf));
|
|
if (rv<0) {
|
|
fprintf(stderr, "Adding module \"vars\" failed.\n");
|
|
return 2;
|
|
}
|
|
|
|
rv=AQH_Vars_DbRead_AddTests(TestFramework_GetModulesRoot(tf));
|
|
if (rv<0) {
|
|
fprintf(stderr, "Adding module \"vars_dbread\" failed.\n");
|
|
return 2;
|
|
}
|
|
|
|
rv=AQH_Vars_DbWrite_AddTests(TestFramework_GetModulesRoot(tf));
|
|
if (rv<0) {
|
|
fprintf(stderr, "Adding module \"vars_dbwrite\" failed.\n");
|
|
return 2;
|
|
}
|
|
|
|
argc--;
|
|
argv++;
|
|
rv=TestFramework_Run(tf, argc, argv);
|
|
if (rv) {
|
|
fprintf(stderr, "SomeError in tests failed.\n");
|
|
GWEN_Gui_SetGui(NULL);
|
|
GWEN_Gui_free(gui);
|
|
return 2;
|
|
}
|
|
TestFramework_free(tf);
|
|
|
|
GWEN_Gui_SetGui(NULL);
|
|
GWEN_Gui_free(gui);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int _diffInSeconds(time_t t1, time_t t0)
|
|
{
|
|
return t1-t0;
|
|
}
|
|
|