#include #include #include #include #include #include #include "../src/defines.h" ///////////////////////////////////////////////////////////////////////////// #define _APPNAME_MQTTCL "MQTTCL" #define _APPNAME_REMANENT "Remanent" #define _APPNAME_REST "REST" #define _CTRL_MSG_DELAY 8 ///////////////////////////////////////////////////////////////////////////// #define UNUSED(v) (void)v #define _USLEEP_DELAY 20000 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 _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: g_fPause = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Paused); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Paused]); break; case GFA_APPCTRL_CTRLMSG_RESUME: g_fPause = false; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); TRACE("%-8s: State: %s\n", "Me", g_pszStateNames[GIAS_Running]); break; case _CTRL_MSG_DELAY: TRACE("Delaying 2 seconds.\n"); sleep(2); 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, _USLEEP_DELAY * 5))) break; ;;GfaIpcDumpSHMROT(); ::GfaIpcAppCtrlPresetDisplayName(hAC, _APPID_1, _APPNAME_1); ::GfaIpcAppCtrlPresetDisplayName(hAC, _APPID_2, _APPNAME_2); ::GfaIpcAppCtrlSetState(hAC, GIAS_Initializing); if(!::GfaIpcAppCtrlSubscribeStateEvents(hAC, _APPID_1 | _APPID_2)) break; TRACE("My Name: %s\n", _APPNAME_0); TRACE("My AppID: %llu\n", _APPID_0); g_fRun = true; ::GfaIpcAppCtrlSetState(hAC, GIAS_Running); } while(false); ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // run while(g_fRun) { do { ///////////////////////////////////////////////////////////////// // test input _ProcessInput(hAC); ///////////////////////////////////////////////////////////////// // update app control info if((hAI = ::GfaIpcAppCtrlInfoUpdate(hAC, !g_fPause))) { _ProcessCtrlMessages(hAC, hAI); _ProcessStateEvents(hAC, hAI); } ///////////////////////////////////////////////////////////////// ::usleep(_USLEEP_DELAY); } while(g_fRun && g_fPause); ///////////////////////////////////////////////////////////////////// if(g_fRun) { _DoWork(); } ///////////////////////////////////////////////////////////////////// } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // terminate if(hAC) { ::GfaIpcAppCtrlSetState(hAC, GIAS_Terminating); ::GfaIpcAppCtrlRelease(hAC); } return 0; }