#include #include #include #include #include #include #include #include "../src/defines.h" #include "app.h" ///////////////////////////////////////////////////////////////////////////// #define _APPNAME_MQTTCL "MQTTCL" #define _APPNAME_REMANENT "Remanent" #define _APPNAME_REST "REST" #define _CTRL_MSG_DELAY 8 #define _HANG_DELAY 10 ///////////////////////////////////////////////////////////////////////////// #define UNUSED(v) (void)v #define _MAX_CYCLE_DELAY (_CYCLE_INTV * 5000) static volatile bool g_fRun = false; static volatile bool g_fPause = false; ///////////////////////////////////////////////////////////////////////////// static const char *g_pszStateNames[] = { "Not running", "Initializing", "Running", "Paused", "Hanging", "Terminating", "Invalid" }; ///////////////////////////////////////////////////////////////////////////// static void _SigHandler(int sig) { UNUSED(sig); g_fPause = false; g_fRun = false; } ///////////////////////////////////////////////////////////////////////////// static int _InputAvailable(void) { static struct pollfd poIn[1] = {{0, POLLIN, 0}}; int n = poll(poIn, 1, 0); return n; } ///////////////////////////////////////////////////////////////////////////// static void _DoHang(time_t nSec) { time_t t = time(NULL) + nSec; do { if(t < time(NULL)) break; } while(true); } ///////////////////////////////////////////////////////////////////////////// static void _ProcessCtrlMessages(HAPPCTRL hAC, HAPPINFO hAI) { ctrlmsg_t nCtrlMsg; while(g_fRun && (nCtrlMsg = ::GfaIpcAppCtrlGetNextCtrlMsg(hAI))) { switch(nCtrlMsg) { case GFA_APPCTRL_CTRLMSG_STOP: g_fRun = false; TRACE("Received Message: STOP!\n"); break; case GFA_APPCTRL_CTRLMSG_PAUSE: if(!g_fPause) { g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]); } break; case GFA_APPCTRL_CTRLMSG_RESUME: if(g_fPause) { g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]); } break; case _CTRL_MSG_DELAY: TRACE("Hanging %d seconds.\n", _HANG_DELAY); _DoHang(_HANG_DELAY); break; default: break; } } } ///////////////////////////////////////////////////////////////////////////// static void _ProcessStateEvents(HAPPCTRL hAC, HAPPINFO hAI) { appid_t nAppIdSrc; char szDispName[128]; while(g_fRun && (nAppIdSrc = ::GfaIpcAppCtrlGetNextStateEvtSrc(hAI))) { GfaIpcAppStates state = ::GfaIpcAppCtrlGetState(hAC, nAppIdSrc); GfaIpcAppCtrlGetDisplayName(hAC, nAppIdSrc, szDispName, sizeof(szDispName)); TRACE("%-8s: State: %s\n", szDispName, g_pszStateNames[state]); switch(nAppIdSrc) { case GFA_APPCTRL_APPID_REMANENT: if(state == GIAS_Running) { if(g_fPause) { g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]); } } else { if(!g_fPause) { g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]); } } break; case GFA_APPCTRL_APPID_REST: break; case GFA_APPCTRL_APPID_MQTTCL: break; } } } ///////////////////////////////////////////////////////////////////////////// static void _ProcessInput(HAPPCTRL hAC) { if(_InputAvailable()) { ctrlmsg_t msg = 0; appid_t aiTarget = 0; int nRet = scanf("%llu %llu", &aiTarget, &msg); if(nRet == 2) { ::GfaIpcAppCtrlSendCtrlMsg(hAC, aiTarget, msg); } } } ///////////////////////////////////////////////////////////////////////////// static int _DoWork(void) { static int nCounter = 0; return ++nCounter; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// int main(void) { HAPPCTRL hAC = NULL; HAPPINFO hAI; ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // signal handling struct sigaction sa; memset(&sa, 0, sizeof(sa)); // handle signals sa.sa_handler = _SigHandler; sigaction(SIGHUP, &sa, NULL); // handles user's terminal disconnect sigaction(SIGQUIT, &sa, NULL); // handles Ctrl + '\' sigaction(SIGTERM, &sa, NULL); // handles normal termination sigaction(SIGABRT, &sa, NULL); // handles abnormal termination (i.e. abort()) sigaction(SIGINT, &sa, NULL); // handles Ctrl + 'C' // ignore signals sa.sa_handler = SIG_IGN; sigaction(SIGTSTP, &sa, NULL); // ignores Ctrl + 'Z' sigaction(SIGCHLD, &sa, NULL); // ignores child process termination sigaction(0, &sa, NULL); // ignores shell termination ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // initialize do { if(!(hAC = ::GfaIpcAppCtrlAcquire(_APPID_0, _APPNAME_0, _MAX_CYCLE_DELAY))) break; ;;GfaIpcDumpSHMROT(); ::GfaIpcAppCtrlPresetDisplayName(hAC, GFA_APPCTRL_APPID_USER_01, "qmlApp"); ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing); if(!::GfaIpcAppCtrlSubscribeStateEvents(hAC, _APPID_1 | _APPID_2 | GFA_APPCTRL_APPID_USER_01)) break; TRACE("My Name: %s\n", _APPNAME_0); TRACE("My AppID: %llu\n", _APPID_0); TRACE("My PID: %d\n", getpid()); TRACE("My Cycle: %d\n", _CYCLE_INTV); g_fRun = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); } while(false); ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // run CCycleTimer ct(_CYCLE_INTV); while(g_fRun) { ///////////////////////////////////////////////////////////////////// // trigger cycle timer ct.Trigger(); ///////////////////////////////////////////////////////////////////// // test input _ProcessInput(hAC); ///////////////////////////////////////////////////////////////////// // update app control info if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC))) { _ProcessCtrlMessages(hAC, hAI); _ProcessStateEvents(hAC, hAI); } ///////////////////////////////////////////////////////////////////// // if not paused, do work if(!g_fPause && g_fRun) { _DoWork(); } ///////////////////////////////////////////////////////////////////// // if running, sleep if(g_fRun) ct.Sleep1(); } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // terminate if(hAC) { ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating); ::GfaIpcAppCtrlRelease(hAC); } return 0; }