static void tickTimerHandler (void *parm) { int i; PMON_STIM stim; for (i = 0; i < PMON_PROCESS_MAX; i ++) { if (procmonWork.process[i].timeout <= 0 || procmonWork.process[i].ticks <= 0) { // Skip this guy continue; } procmonWork.process[i].ticks --; if (procmonWork.process[i].ticks == 0) { // Tickle the state machine memset (&stim, 0, sizeof(stim)); stim.index = i; stim.type = PMON_STIM_TIMEOUT; radStatesProcess (procmonWork.process[i].stateMachine, &stim); } } radProcessTimerStart (procmonWork.tickTimer, PMON_TICK_INTERVAL); return; }
static void timerHandler (void *parm) { time_t ntime; struct tm locTime; radProcessTimerStart (cwopWork.timer, CWOP_MINUTE_INTERVAL); ntime = time (NULL); localtime_r (&ntime, &locTime); if ((locTime.tm_min % cwopWork.reportInterval) == cwopWork.callSignOffset) { // Time to send a packet if we have any new data: if (cwopWork.rxArchive) { processCWOP (); cwopWork.rxArchive = FALSE; } else { if (cwopWork.rxFirstArchive) { statusUpdateMessage("no new archive data received since last CWOP submission"); radMsgLog (PRI_MEDIUM, "wvcwopd: no new archive data received since last CWOP submission:"); } } } return; }
static void timerHandler (void *parm) { uint64_t msOffset = radTimeGetMSSinceEpoch (); int64_t netOffset; // ... allow for timer latency if (sshWork.msOffset == 0ULL) { // first time through sshWork.msOffset = msOffset; netOffset = 0LL; } else { netOffset = msOffset - sshWork.msOffset; } sshWork.msOffset += 60000ULL; // ALWAYS 1 minute radProcessTimerStart (sshWork.timer, (uint32_t)(60000LL - netOffset)); // ... process the ssh rules sshUtilsSendFiles (sshWork.sshId, sshWork.wviewdir); return; }
int htmlRunState (int state, void *stimulus, void *data) { STIM *stim = (STIM *)stimulus; HTML_WORK *work = (HTML_WORK *)data; WVIEW_MSG_LOOP_DATA *loop = (WVIEW_MSG_LOOP_DATA *)stim->msg; WVIEW_MSG_HILOW_DATA *hilow = (WVIEW_MSG_HILOW_DATA *)stim->msg; WVIEW_MSG_ARCHIVE_NOTIFY *arcNot = (WVIEW_MSG_ARCHIVE_NOTIFY *)stim->msg; switch (stim->type) { case STIM_QMSG: if (stim->msgType == WVIEW_MSG_TYPE_LOOP_DATA) { work->mgrId->loopStore = loop->loopData; return state; } else if (stim->msgType == WVIEW_MSG_TYPE_HILOW_DATA) { work->mgrId->hilowStore = hilow->hilowData; return state; } else if (stim->msgType == WVIEW_MSG_TYPE_ARCHIVE_NOTIFY) { processNewArchiveRecord (work, arcNot); return state; } break; case STIM_TIMER: if (stim->timerNumber == TIMER_GENERATE) { // ... request the next batch of data if (requestDataPackets (work) == ERROR) { radMsgLog (PRI_HIGH, "htmlRunState: requestDataPackets failed!"); statusUpdateMessage("requestDataPackets failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } radProcessTimerStart(work->rxTimer, HTML_RX_PACKETS_TIMEOUT); work->numDataReceived = 0; return HTML_STATE_DATA; } return state; } return state; }
static void timerHandler (void *parm) { ULONGLONG msOffset = radTimeGetMSSinceEpoch (); int rules; long long netOffset; // ... allow for timer latency if (ftpWork.msOffset == 0) { // first time through ftpWork.msOffset = msOffset; netOffset = 0; } else { netOffset = msOffset - ftpWork.msOffset; while (netOffset >= 60000LL) { netOffset -= 60000LL; } } while (ftpWork.msOffset < msOffset) { ftpWork.msOffset += 60000ULL; } radProcessTimerStart(ftpWork.timer, (ULONG)(60000LL - netOffset)); // ... process the ftp rules rules = ftpUtilsSendFiles(ftpWork.ftpId, ftpWork.wviewdir); if (rules > 0) { wvutilsLogEvent (PRI_STATUS, "FTP: %d rules processed", rules); } else if (rules < 0) { wvutilsLogEvent (PRI_MEDIUM, "FTP: ftpUtilsSendFiles failed!"); } return; }
int stationPushDataToClients (WVIEWD_WORK *work) { WVIEW_MSG_LOOP_DATA loop; if (!work->runningFlag) { return OK; } memcpy (&loop.loopData, &work->loopPkt, sizeof (loop.loopData)); if (radMsgRouterMessageSend (WVIEW_MSG_TYPE_LOOP_DATA_SVC, &loop, sizeof(loop)) == ERROR) { radMsgLog (PRI_HIGH, "radMsgRouterMessageSend failed for loop transmit!"); return ERROR; } radProcessTimerStart (work->pushTimer, work->pushInterval); return OK; }
static void timerHandler (void *parm) { uint64_t msOffset = radTimeGetMSSinceEpoch (); int64_t netOffset; uint64_t xoffset; // ... allow for timer latency if (sshWork.msOffset == 0ULL) { // first time through sshWork.msOffset = msOffset; netOffset = 0LL; } else { netOffset = msOffset - sshWork.msOffset; } sshWork.msOffset += 60000ULL; // ALWAYS 1 minute xoffset = sshWork.msOffset; // Cope with long scheduling delays or with the time being changed int32_t timerWait = (int32_t)(60000LL - netOffset); if ((timerWait <= 0) || (timerWait > 120000)) { radMsgLog (PRI_HIGH, "wviewsshd: unusual wait %d; fixing it up", timerWait); // Keep the offset into the minute to keep updates aligned with the original alignment. uint64_t baseNow = (msOffset / 60000ULL) * 60000ULL; netOffset = 60000ULL; sshWork.msOffset = baseNow + netOffset + (sshWork.msOffset % 60000ULL); radMsgLog (PRI_HIGH, "wviewsshd: fixed offset is %llu", sshWork.msOffset); } radProcessTimerStart (sshWork.timer, (uint32_t)(60000LL - netOffset)); // ... process the ssh rules sshUtilsSendFiles (sshWork.sshId, sshWork.wviewdir); return; }
static void pollTimerHandler (void *parm) { int i, mask = 0; WVIEW_MSG_POLL poll; PMON_STIM stim; // Set active process bits: for (i = 0; i < PMON_PROCESS_MAX; i ++) { if (procmonWork.process[i].timeout <= 0 || radStatesGetState (procmonWork.process[i].stateMachine) != PMON_STATE_IDLE) { // Skip this guy continue; } mask = PMON_PROCESS_SET(mask,i); procmonWork.process[i].ticks = procmonWork.process[i].timeout; // Tickle the state machine memset (&stim, 0, sizeof(stim)); stim.index = i; stim.type = PMON_STIM_POLL; radStatesProcess (procmonWork.process[i].stateMachine, &stim); } poll.mask = mask; if (radMsgRouterMessageSend (WVIEW_MSG_TYPE_POLL, &poll, sizeof(poll)) == ERROR) { radMsgLog (PRI_HIGH, "pollTimerHandler: radMsgRouterMessageSend failed!"); } radProcessTimerStart (procmonWork.pollTimer, PMON_POLL_INTERVAL); return; }
/* ... the main entry point for the wvcwopd process */ int main (int argc, char *argv[]) { void (*alarmHandler)(int); int retVal; FILE *pidfile; int iValue; double dValue; const char* sValue; int runAsDaemon = TRUE; if (argc > 1) { if (!strcmp(argv[1], "-f")) { runAsDaemon = FALSE; } } memset (&cwopWork, 0, sizeof (cwopWork)); /* ... initialize some system stuff first */ retVal = cwopSysInit (&cwopWork); if (retVal == ERROR) { radMsgLogInit (PROC_NAME_CWOP, FALSE, TRUE); radMsgLog (PRI_CATASTROPHIC, "wvcwopd init failed!"); radMsgLogExit (); exit (1); } else if (retVal == ERROR_ABORT) { exit (2); } /* ... call the global radlib system init function */ if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR) { radMsgLogInit (PROC_NAME_CWOP, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!"); radMsgLogExit (); exit (1); } /* ... call the radlib process init function */ if (radProcessInit (PROC_NAME_CWOP, cwopWork.fifoFile, PROC_NUM_TIMERS_CWOP, runAsDaemon, // TRUE for daemon msgHandler, evtHandler, NULL) == ERROR) { printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_CWOP); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } cwopWork.myPid = getpid (); pidfile = fopen (cwopWork.pidFile, "w"); if (pidfile == NULL) { radMsgLog (PRI_CATASTROPHIC, "lock file create failed!"); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } fprintf (pidfile, "%d", getpid ()); fclose (pidfile); alarmHandler = radProcessSignalGetHandler (SIGALRM); radProcessSignalCatchAll (defaultSigHandler); radProcessSignalCatch (SIGALRM, alarmHandler); radProcessSignalRelease(SIGABRT); // get our configuration values if (wvconfigInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "wvconfigInit failed!"); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Is the CWOP daemon enabled? iValue = wvconfigGetBooleanValue(configItem_ENABLE_CWOP); if (iValue == ERROR || iValue == 0) { wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "CWOP daemon is NOT enabled - exiting..."); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // get the wview verbosity setting if (wvutilsSetVerbosity (WV_VERBOSE_WVCWOPD) == ERROR) { wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "wvutilsSetVerbosity failed!"); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // get the APRS call sign sValue = wvconfigGetStringValue(configItemCWOP_APRS_CALL_SIGN); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_CALL_SIGN); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.callSign, sValue, sizeof(cwopWork.callSign)); if (sValue[strlen(sValue)-1] >= '0' && sValue[strlen(sValue)-1] <= '9') { cwopWork.callSignOffset = atoi(&sValue[strlen(sValue)-1]); } else { cwopWork.callSignOffset = (sValue[strlen(sValue)-1] % 10); } cwopWork.callSignOffset %= 10; } // get the primary APRS server sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER1); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER1); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.server1, sValue, sizeof(cwopWork.server1)); } // get the primary APRS port number iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO1); if (iValue < 0) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO1); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { cwopWork.portNo1 = iValue; } // get the secondary APRS server sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER2); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER2); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.server2, sValue, sizeof(cwopWork.server2)); } // get the primary APRS port number iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO2); if (iValue < 0) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO2); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { cwopWork.portNo2 = iValue; } // get the tertiary APRS server sValue = wvconfigGetStringValue(configItemCWOP_APRS_SERVER3); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_SERVER3); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.server3, sValue, sizeof(cwopWork.server3)); } // get the primary APRS port number iValue = wvconfigGetINTValue(configItemCWOP_APRS_PORTNO3); if (iValue < 0) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_APRS_PORTNO3); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { cwopWork.portNo3 = iValue; } // get the fine pitch latitude that APRS requires sValue = wvconfigGetStringValue(configItemCWOP_LATITUDE); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_LATITUDE); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.latitude, sValue, sizeof(cwopWork.latitude)); } // get the fine pitch longitude that APRS requires sValue = wvconfigGetStringValue(configItemCWOP_LONGITUDE); if (sValue == NULL) { // we can't do without this! wvconfigExit (); radMsgLog (PRI_CATASTROPHIC, "%s failed!", configItemCWOP_LONGITUDE); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy (cwopWork.longitude, sValue, sizeof(cwopWork.longitude)); } // get the WX packet logging preference iValue = wvconfigGetBooleanValue(configItemCWOP_LOG_WX_PACKET); if (iValue <= 0) { // just disable it cwopWork.logWXPackets = 0; } else { cwopWork.logWXPackets = iValue; } wvconfigExit (); if (statusInit(cwopWork.statusFile, cwopStatusLabels) == ERROR) { radMsgLog (PRI_HIGH, "statusInit failed - exiting..."); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } statusUpdate(STATUS_BOOTING); // wait a bit here before continuing radUtilsSleep (500); cwopWork.timer = radTimerCreate (NULL, timerHandler, NULL); if (cwopWork.timer == NULL) { statusUpdateMessage("radTimerCreate failed"); radMsgLog (PRI_HIGH, "radTimerCreate failed"); statusUpdate(STATUS_ERROR); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } radProcessTimerStart (cwopWork.timer, CWOP_MINUTE_INTERVAL); // register with the radlib message router if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR) { statusUpdateMessage("radMsgRouterInit failed"); radMsgLog (PRI_HIGH, "radMsgRouterInit failed!"); statusUpdate(STATUS_ERROR); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for SHUTDOWN msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_SHUTDOWN); // wait for the wview daemon to be ready if (waitForWviewDaemon () == ERROR) { radMsgLog (PRI_HIGH, "waitForWviewDaemon failed"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for archive notifications radMsgRouterMessageRegister (WVIEW_MSG_TYPE_ARCHIVE_NOTIFY); // enable message reception from the radlib router for POLL msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL); radMsgLog (PRI_STATUS, "CWOP: configured to submit station %s data to:", cwopWork.callSign); radMsgLog (PRI_STATUS, "CWOP: Primary: %s:%d", cwopWork.server1, cwopWork.portNo1); radMsgLog (PRI_STATUS, "CWOP: Secondary: %s:%d", cwopWork.server2, cwopWork.portNo2); radMsgLog (PRI_STATUS, "CWOP: Tertiary: %s:%d", cwopWork.server3, cwopWork.portNo3); radMsgLog (PRI_STATUS, "CWOP: Submitting every %d minutes at offset minute: %d", cwopWork.reportInterval, cwopWork.callSignOffset); // enter normal processing cwopWork.inMainLoop = TRUE; statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); radMsgLog (PRI_STATUS, "running..."); while (!cwopWork.exiting) { // wait on something interesting if (radProcessWait (0) == ERROR) { cwopWork.exiting = TRUE; } } statusUpdateMessage("exiting normally"); radMsgLog (PRI_STATUS, "exiting normally..."); statusUpdate(STATUS_SHUTDOWN); radMsgRouterExit (); radTimerDelete (cwopWork.timer); cwopSysExit (&cwopWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); }
static int daemonStationInitComplete (void *eventData) { struct tm locTime; time_t nowtime; ARCHIVE_PKT newestRecord; if (eventData != 0) { // failed startup! radMsgLog (PRI_HIGH, "daemonStationInitComplete: station startup failed!"); return ERROR; } if (!wviewdWork.runningFlag) { wviewdWork.runningFlag = TRUE; // set the positional data: if (stationGetPosition (&wviewdWork) == ERROR) { radMsgLog (PRI_HIGH, "daemonStationInitComplete: stationGetPosition failed!"); emailAlertSend(ALERT_TYPE_STATION_READ); return ERROR; } // !!! the order of these calls is very important !!! // Initialize the HILOW database interface: computedDataInit (&wviewdWork); stormRainInit (wviewdWork.stationRainStormTrigger, wviewdWork.stationRainStormIdleHours); computedDataClearInterval (&wviewdWork, 0, 0); // we know it just finished an initial sensor readings, it is a // REQUIREMENT of the stationInit API... daemonStationLoopComplete (); // do an initial update to propogate the initial readings // (so we have some data to start with) computedDataUpdate (&wviewdWork, NULL); // start the timers... stationStartArchiveTimerUniform (&wviewdWork); stationStartCDataTimerUniform (&wviewdWork); radProcessTimerStart (wviewdWork.pushTimer, 30000L); // first run stationStartSyncTimerUniform (&wviewdWork, TRUE); // first run radMsgLog (PRI_STATUS, "-- Station Init Complete --"); // get the newest archive file record date/time wviewdWork.archiveDateTime = dbsqliteArchiveGetNewestTime(&newestRecord); if ((int)wviewdWork.archiveDateTime == ERROR) { wviewdWork.archiveDateTime = time(NULL); radMsgLog (PRI_STATUS, "no archive records found in database!"); } else { radMsgLog (PRI_STATUS, "newest archive record: %4.4d-%2.2d-%2.2d %2.2d:%2.2d", wvutilsGetYear(wviewdWork.archiveDateTime), wvutilsGetMonth(wviewdWork.archiveDateTime), wvutilsGetDay(wviewdWork.archiveDateTime), wvutilsGetHour(wviewdWork.archiveDateTime), wvutilsGetMin(wviewdWork.archiveDateTime)); } // finally, answer all the WVIEW_RQST_TYPE_STATION_INFO requestors // so they can continue initialization - our data is ready: stationProcessInfoResponses(&wviewdWork); } return OK; }
// the main entry point for the wvpmond process int main (int argc, char *argv[]) { void (*alarmHandler)(int); int i, retVal, intValue, iValue; FILE *pidfile, *markerFile; struct stat fileStatus; char* subString; char markerPath[PMON_MAX_PATH], markerVal[32]; int runAsDaemon = TRUE; if (argc > 1) { if (!strcmp(argv[1], "-f")) { runAsDaemon = FALSE; } } memset (&procmonWork, 0, sizeof (procmonWork)); // initialize some system stuff first retVal = procmonSysInit (&procmonWork); if (retVal == ERROR) { radMsgLogInit (PROC_NAME_PMON, FALSE, TRUE); radMsgLog (PRI_CATASTROPHIC, "wvpmond init failed!\n"); radMsgLogExit (); exit (1); } else if (retVal == ERROR_ABORT) { exit (2); } // call the global radlib system init function if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR) { radMsgLogInit (PROC_NAME_PMON, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!"); radMsgLogExit (); exit (1); } // call the radlib process init function if (radProcessInit (PROC_NAME_PMON, procmonWork.fifoFile, PROC_NUM_TIMERS_PMON, runAsDaemon, // TRUE for daemon msgHandler, evtHandler, NULL) == ERROR) { printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_PMON); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } procmonWork.myPid = getpid (); pidfile = fopen (procmonWork.pidFile, "w"); if (pidfile == NULL) { radMsgLog (PRI_CATASTROPHIC, "lock file create failed!\n"); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } fprintf (pidfile, "%d", getpid ()); fclose (pidfile); alarmHandler = radProcessSignalGetHandler (SIGALRM); radProcessSignalCatchAll (defaultSigHandler); radProcessSignalCatch (SIGALRM, alarmHandler); radProcessSignalRelease(SIGABRT); if (wvconfigInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "wvconfigInit failed!\n"); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Is the procmon daemon enabled? iValue = wvconfigGetBooleanValue(configItem_ENABLE_PROCMON); if (iValue == ERROR || iValue == 0) { radMsgLog (PRI_CATASTROPHIC, "process monitor daemon is disabled - exiting..."); wvconfigExit (); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Close here; we'll re-open after waiting for the wviewd daemon to be ready: wvconfigExit(); if (statusInit(procmonWork.statusFile, pmonStatusLabels) == ERROR) { radMsgLog (PRI_HIGH, "statusInit failed - exiting..."); wvconfigExit (); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } statusUpdate(STATUS_BOOTING); // register with the radlib message router if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR) { radMsgLog (PRI_HIGH, "radMsgRouterInit failed!"); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for SHUTDOWN msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_SHUTDOWN); // wait for the wview daemon to be ready if (waitForWviewDaemon () == ERROR) { radMsgLog (PRI_HIGH, "waitForWviewDaemon failed"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } procmonWork.pollTimer = radProcessTimerCreate (NULL, pollTimerHandler, NULL); if (procmonWork.pollTimer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed"); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } procmonWork.tickTimer = radProcessTimerCreate (NULL, tickTimerHandler, NULL); if (procmonWork.tickTimer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed"); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } if (wvconfigInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "wvconfigInit failed!\n"); statusUpdateMessage("wvconfigInit failed"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Populate our process table: memset (procmonWork.process, 0, sizeof(PMON_PROCESS) * PMON_PROCESS_MAX); for (i = 0; i < PMON_PROCESS_MAX; i ++) { iValue = wvconfigGetINTValue(configIDs[i]); if (iValue < 0) { // we can't do without this! radMsgLog (PRI_CATASTROPHIC, "PMON: %s: failed!", configIDs[i]); statusUpdateMessage("wvconfigGetINTValue failed"); statusUpdate(STATUS_ERROR); wvconfigExit(); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { procmonWork.process[i].timeout = iValue; radMsgLog (PRI_STATUS, "PMON: %s: %d", procNames[i], procmonWork.process[i].timeout); } if (procmonWork.process[i].timeout <= 0) { radMsgLog (PRI_STATUS, "PMON: %s process monitoring is disabled", procNames[i]); procmonWork.process[i].ticks = -1; procmonWork.process[i].pid = -1; } else { // Populate the rest of the values: wvstrncpy (procmonWork.process[i].binFile, argv[0], PMON_MAX_PATH); subString = strstr (procmonWork.process[i].binFile, "wvpmond"); if (subString == NULL) { radMsgLog (PRI_CATASTROPHIC, "PMON: %s is invalid for bin path!", procmonWork.process[i].binFile); statusUpdateMessage("invalid for bin path"); statusUpdate(STATUS_ERROR); wvconfigExit(); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } if (! strcmp(procNames[i], "wviewd")) { // Get the process name from the marker file: sprintf(markerPath, "%s/wview-binary", WVIEW_CONFIG_DIR); if (stat (markerPath, &fileStatus) != 0) { radMsgLog (PRI_HIGH, "PMON: wview-binary file is missing - was 'make install' run?"); statusUpdateMessage("wview-binary file is missing"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } markerFile = fopen(markerPath, "r"); if (markerFile == NULL) { radMsgLog (PRI_HIGH, "PMON: failed to open wview-binary file - was 'make install' run?"); statusUpdateMessage("failed to open wview-binary file"); statusUpdate(STATUS_ERROR); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } if (fgets(markerVal, 32, markerFile) == NULL) { radMsgLog (PRI_HIGH, "PMON: failed to read wview-binary file - was 'make install' run?"); statusUpdateMessage("failed to read wview-binary file"); statusUpdate(STATUS_ERROR); fclose(markerFile); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Strip off CR/LF (caused by hand-editing of file!): stripEOLValues(markerVal); sprintf(subString, "%s", markerVal); fclose(markerFile); } else { sprintf (subString, "%s", procNames[i]); } sprintf (procmonWork.process[i].pidFile, "%s/%s.pid", WVIEW_RUN_DIR, procNames[i]); if (stat (procmonWork.process[i].pidFile, &fileStatus) == -1) { // Process is not running, mark it invalid radMsgLog (PRI_STATUS, "PMON: pid file %s not present, disable monitoring...", procmonWork.process[i].pidFile); procmonWork.process[i].timeout = 0; procmonWork.process[i].ticks = -1; procmonWork.process[i].pid = -1; } else { // Get his pid from the pidfile procmonWork.process[i].pid = pmonGetProcessPid (procmonWork.process[i].pidFile); if (procmonWork.process[i].pid == ERROR) { radMsgLog (PRI_CATASTROPHIC, "PMON: failed to READ %s!", procmonWork.process[i].pidFile); statusUpdateMessage("failed to read pid file"); statusUpdate(STATUS_ERROR); wvconfigExit(); radMsgRouterExit (); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } } // Setup the state machine procmonWork.process[i].stateMachine = radStatesInit (&procmonWork); radStatesAddHandler (procmonWork.process[i].stateMachine, PMON_STATE_IDLE, IdleStateHandler); radStatesAddHandler (procmonWork.process[i].stateMachine, PMON_STATE_WAIT_RESP, WaitRespStateHandler); radStatesAddHandler (procmonWork.process[i].stateMachine, PMON_STATE_WAIT_EXIT, WaitExitStateHandler); radStatesAddHandler (procmonWork.process[i].stateMachine, PMON_STATE_WAIT_START, WaitStartStateHandler); radStatesSetState (procmonWork.process[i].stateMachine, PMON_STATE_IDLE); } } wvconfigExit(); radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL_RESPONSE); // Start the timers: radProcessTimerStart (procmonWork.pollTimer, PMON_POLL_INTERVAL); radProcessTimerStart (procmonWork.tickTimer, PMON_TICK_INTERVAL); // enter normal processing procmonWork.inMainLoop = TRUE; statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); radMsgLog (PRI_STATUS, "running..."); while (!procmonWork.exiting) { // wait on something interesting if (radProcessWait (0) == ERROR) { procmonWork.exiting = TRUE; } } statusUpdateMessage("exiting normally"); radMsgLog (PRI_STATUS, "exiting normally..."); statusUpdate(STATUS_SHUTDOWN); radMsgRouterExit (); radProcessTimerDelete (procmonWork.pollTimer); radProcessTimerDelete (procmonWork.tickTimer); procmonSysExit (&procmonWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); }
/* ... the main entry point for the ssh process */ int main (int argc, char *argv[]) { void (*alarmHandler)(int); STIM stim; int i; int seconds; time_t ntime; struct tm locTime; int offset, retVal; long msOffset; FILE *pidfile; int runAsDaemon = TRUE; if (argc > 1) { if (!strcmp(argv[1], "-f")) { runAsDaemon = FALSE; } } memset (&sshWork, 0, sizeof (sshWork)); /* ... initialize some system stuff first */ retVal = sshSysInit (&sshWork); if (retVal == ERROR) { radMsgLogInit (PROC_NAME_SSH, FALSE, TRUE); radMsgLog (PRI_CATASTROPHIC, "ssh init failed!"); radMsgLogExit (); exit (1); } else if (retVal == ERROR_ABORT) { exit (2); } /* ... call the global radlib system init function */ if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR) { radMsgLogInit (PROC_NAME_SSH, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!"); radMsgLogExit (); exit (1); } /* ... call the radlib process init function */ if (radProcessInit (PROC_NAME_SSH, sshWork.fifoFile, PROC_NUM_TIMERS_SSH, runAsDaemon, // TRUE for daemon msgHandler, evtHandler, NULL) == ERROR) { printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_SSH); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } sshWork.myPid = getpid (); pidfile = fopen (sshWork.pidFile, "w"); if (pidfile == NULL) { radMsgLog (PRI_CATASTROPHIC, "lock file create failed!"); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } fprintf (pidfile, "%d", getpid ()); fclose (pidfile); alarmHandler = radProcessSignalGetHandler (SIGALRM); radProcessSignalCatchAll (SSHDefaultSigHandler); radProcessSignalCatch (SIGALRM, alarmHandler); radProcessSignalRelease(SIGABRT); sshWork.timer = radTimerCreate (NULL, timerHandler, NULL); if (sshWork.timer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed - exiting"); sshSysExit (&sshWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // ... initialize the ssh utilities retVal = sshUtilsInit (&sshWork.sshData); if (retVal != OK) { if (retVal == ERROR) { radMsgLog (PRI_HIGH, "sshUtilsInit failed - exiting"); } radTimerDelete (sshWork.timer); sshSysExit (&sshWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { sshWork.sshId = &sshWork.sshData; } if (statusInit(sshWork.statusFile, sshStatusLabels) == ERROR) { radMsgLog (PRI_HIGH, "statusInit failed - exiting..."); sshSysExit (&sshWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } statusUpdate(STATUS_BOOTING); statusUpdateStat(SSH_STATS_RULES_DEFINED, radListGetNumberOfNodes(&sshWork.sshData.rules)); // ... start THE timer ntime = time (NULL); localtime_r (&ntime, &locTime); seconds = locTime.tm_sec - 15; // start at 15 secs past /* ... start the ssh timer to go off 1 min past the next archive record */ offset = locTime.tm_min % 5; if (offset) offset = 6 - offset; else offset = 1; if (seconds < -60) { offset += 1; offset += 60; } radMsgLog (PRI_HIGH, "SSH: starting updates in %d mins %d secs", ((seconds > 0) ? ((offset > 0) ? offset-1 : offset) : offset), (seconds > 0) ? 60 - seconds : (-1) * seconds); msOffset = radTimeGetMSSinceEpoch () % 1000; msOffset -= 250; // land on 250 ms mark sshWork.msOffset = 0; radProcessTimerStart (sshWork.timer, ((((offset * 60) - seconds) * 1000)) - msOffset); statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); while (!sshWork.exiting) { /* ... wait on timers, events, file descriptors, msgs, everything! */ if (radProcessWait (0) == ERROR) { sshWork.exiting = TRUE; } } statusUpdateMessage("exiting normally"); radMsgLog (PRI_STATUS, "exiting normally..."); statusUpdate(STATUS_SHUTDOWN); if (sshWork.sshId != NULL) { sshUtilsExit (sshWork.sshId); } radTimerDelete (sshWork.timer); sshSysExit (&sshWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); }
static void processNewArchiveRecord (HTML_WORK *work, WVIEW_MSG_ARCHIVE_NOTIFY *armsg) { HISTORY_DATA data; ARCHIVE_PKT arcRecord; int currHour, currDay, currMonth, currYear; float gmtOffsetHours; int startmin, starthour, startday, startmonth, startyear; int i, DSTFlag; int16_t tempShort; time_t ntime, baseTime; struct tm locTime; int deltaArchiveIntervals; // ... generate the mesonet file htmlgenMesonetFile (work->mgrId, armsg); // ... check to see if a DST change has occured DSTFlag = wvutilsDetectDSTChange(); if (DSTFlag != WVUTILS_DST_NO_CHANGE) { radMsgLog (PRI_STATUS, "DST change: updating astronomical times for new local time..."); ntime = time (NULL); localtime_r (&ntime, &locTime); currDay = locTime.tm_mday; currMonth = locTime.tm_mon + 1; currYear = locTime.tm_year + 1900; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif // ... update the sun times: sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); // restart the generation timer as the change may leave it in limbo radProcessTimerStart (work->timer, 5000L); } baseTime = time (NULL); // ... update our data by adding the new sample //// Interval change: // ... determine time to start for last sample startmin = wvutilsGetMin(armsg->dateTime); starthour = wvutilsGetHour(armsg->dateTime); startday = wvutilsGetDay(armsg->dateTime); startmonth = wvutilsGetMonth(armsg->dateTime); startyear = wvutilsGetYear(armsg->dateTime); currHour = starthour; currDay = startday; currMonth = startmonth; currYear = startyear; if (work->LastArchiveDateTime != 0) { // compute the number of archive intervals since the last good record deltaArchiveIntervals = armsg->dateTime - work->LastArchiveDateTime; deltaArchiveIntervals /= 60; if (deltaArchiveIntervals < work->archiveInterval) { // this is odd, report and bail out radMsgLog (PRI_MEDIUM, "processNewArchiveRecord: " "minutes since last archive record (%d) " "less than archive interval (%d) - " "ignoring record...", deltaArchiveIntervals, work->archiveInterval); return; } deltaArchiveIntervals /= work->archiveInterval; } else { deltaArchiveIntervals = 1; } work->LastArchiveDateTime = armsg->dateTime; if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, armsg->dateTime, 1) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for sample..."); } wvutilsLogEvent (PRI_STATUS, "Adding %d minute sample for %4.4d-%2.2d-%2.2d %2.2d:%2.2d...", work->archiveInterval, startyear, startmonth, startday, starthour, startmin); // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_SAMPLE; // add the RX check value to the data here data.values[DATA_INDEX_rxCheckPercent] = armsg->rxPercent; htmlmgrAddSampleValue (work->mgrId, &data, deltaArchiveIntervals); // generate an ASCII entry in the day's browser file (if enabled) if (dbsqliteArchiveGetRecord(armsg->dateTime, &arcRecord) == OK) { arcrecGenerate(&arcRecord, work->mgrId->isMetricUnits); } //// Hour change? if (work->histLastHour != currHour) { // determine times to start for last hour: ntime = time (NULL); localtime_r (&ntime, &locTime); locTime.tm_sec = 0; locTime.tm_min = work->archiveInterval; locTime.tm_hour = currHour; locTime.tm_mday = currDay; locTime.tm_mon = currMonth - 1; locTime.tm_year = currYear - 1900; locTime.tm_isdst = -1; ntime = mktime (&locTime); ntime -= WV_SECONDS_IN_HOUR; localtime_r (&ntime, &locTime); starthour = locTime.tm_hour; if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, ntime, WV_SECONDS_IN_HOUR/SECONDS_IN_INTERVAL(work->archiveInterval)) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for last hour..."); } wvutilsLogEvent (PRI_STATUS, "Adding hour sample..."); // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_HOUR; htmlmgrAddHourValue (work->mgrId, &data); work->histLastHour = currHour; } //// Day change? if (work->histLastDay != currDay) { // determine times to start for last day: // normalize packed time: ntime = time (NULL); localtime_r (&ntime, &locTime); locTime.tm_sec = 0; locTime.tm_min = work->archiveInterval; locTime.tm_hour = 0; locTime.tm_mday = currDay; locTime.tm_mon = currMonth - 1; locTime.tm_year = currYear - 1900; locTime.tm_isdst = -1; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif ntime = mktime (&locTime); ntime -= WV_SECONDS_IN_DAY; localtime_r (&ntime, &locTime); if (dbsqliteArchiveGetAverages (work->mgrId->isMetricUnits, work->archiveInterval, &data, ntime, WV_SECONDS_IN_DAY/SECONDS_IN_INTERVAL(work->archiveInterval)) <= 0) { // populate history data with ARCHIVE_VALUE_NULL for (i = 0; i < DATA_INDEX_MAX(work->isExtendedData); i ++) { data.values[i] = ARCHIVE_VALUE_NULL; data.samples[i] = 0; } radMsgLog (PRI_MEDIUM, "no data found for last day..."); } else { // Add a day history record: wvutilsLogEvent(PRI_STATUS, "Storing day history for %s", ctime(&ntime)); dbsqliteHistoryInsertDay(&data); } // ... set the archiveAvailable flag for generation... work->mgrId->newArchiveMask |= NEW_ARCHIVE_DAY; wvutilsLogEvent(PRI_STATUS, "Adding day sample..."); htmlmgrAddDayValue (work->mgrId, &data); work->histLastDay = currDay; // Start the timeout to do NOAA updates: radProcessTimerStart(work->noaaTimer, HTML_NOAA_UPDATE_DELAY); // ... update the sun times sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); } return; }
int htmlStationInfoState (int state, void *stimulus, void *data) { STIM *stim = (STIM *)stimulus; HTML_WORK *work = (HTML_WORK *)data; int seconds; WVIEW_MSG_STATION_INFO *msg = (WVIEW_MSG_STATION_INFO *)stim->msg; time_t ntime; struct tm locTime; long offset, msOffset; long oldSecs, newSecs; int currDay, currMonth, currYear; float gmtOffsetHours; int16_t tempShort; FILE* indicateFile; ntime = time (NULL); localtime_r (&ntime, &locTime); currDay = locTime.tm_mday; currMonth = locTime.tm_mon + 1; currYear = locTime.tm_year + 1900; #ifdef HAVE_TM_GMTOFF gmtOffsetHours = locTime.tm_gmtoff/(60.0*60.0); #else gmtOffsetHours = gmtoffset()/(60.0*60.0); #endif switch (stim->type) { case STIM_QMSG: if (stim->msgType == WVIEW_MSG_TYPE_STATION_INFO) { radMsgRouterMessageDeregister(WVIEW_MSG_TYPE_STATION_INFO); ntime = msg->lastArcTime; localtime_r (&ntime, &locTime); radMsgLog (PRI_STATUS, "received station info from wviewd: " "%4.4d%2.2d%2.2d %2.2d:%2.2d:%2.2d", locTime.tm_year + 1900, locTime.tm_mon + 1, locTime.tm_mday, locTime.tm_hour, locTime.tm_min, locTime.tm_sec); work->archiveInterval = msg->archiveInterval; // Initialize the archive database interface: if (dbsqliteArchiveInit() == ERROR) { radMsgLog (PRI_HIGH, "dbsqliteArchiveInit failed"); statusUpdateMessage("dbsqliteArchiveInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the htmlMgr now that we know the archive interval: work->mgrId = htmlmgrInit (WVIEW_CONFIG_DIR, work->isMetricUnits, work->imagePath, work->htmlPath, work->archiveInterval, work->isExtendedData, work->stationName, work->stationCity, work->stationState, msg->elevation, msg->latitude, msg->longitude, work->mphaseIncrease, work->mphaseDecrease, work->mphaseFull, work->radarURL, work->forecastURL, work->dateFormat, work->isDualUnits); if (work->mgrId == NULL) { radMsgLog (PRI_HIGH, "htlmgrInit failed!"); statusUpdateMessage("htlmgrInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } wvstrncpy (work->mgrId->stationType, msg->stationType, sizeof(work->mgrId->stationType)); // ... initialize the sun times now sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_SUN, &work->mgrId->sunrise, &work->mgrId->sunset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_CIVIL, &work->mgrId->civilrise, &work->mgrId->civilset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_ASTRO, &work->mgrId->astrorise, &work->mgrId->astroset); sunTimesGetSunRiseSet (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, RS_TYPE_MIDDAY, &work->mgrId->midday, &tempShort); work->mgrId->dayLength = sunTimesGetDayLength (currYear, currMonth, currDay, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10); GetMoonRiseSetTimes (currYear, currMonth, currDay, (float)gmtOffsetHours, (float)work->mgrId->stationLatitude/10, (float)work->mgrId->stationLongitude/10, &work->mgrId->moonrise, NULL, &work->mgrId->moonset, NULL); // ... initialize the barometric pressure trend algorithm: radMsgLog (PRI_STATUS, "initializing barometric pressure trend"); if (htmlmgrBPTrendInit (work->mgrId, work->timerInterval/60000) == ERROR) { radMsgLog (PRI_HIGH, "htmlmgrBPTrendInit failed!"); statusUpdateMessage("htmlmgrBPTrendInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // ... load up our historical stores for the history charts: radMsgLog (PRI_STATUS, "initializing historical stores (this may take some time...)"); if (htmlmgrHistoryInit (work->mgrId) == ERROR) { radMsgLog (PRI_HIGH, "htmlStationInfoState: htmlmgrHistoryInit failed!"); statusUpdateMessage("htmlmgrHistoryInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // store the "last" values ntime = time(NULL); localtime_r (&ntime, &locTime); work->histLastHour = locTime.tm_hour; work->histLastDay = locTime.tm_mday; // Initialize the HILOW database interface: // (this cannot occur before wviewd sends us the archive time) if (dbsqliteHiLowInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "dbsqliteHiLowInit failed!"); statusUpdateMessage("dbsqliteHiLowInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the NOAA database: if (dbsqliteNOAAInit() == ERROR) { radMsgLog (PRI_CATASTROPHIC, "dbsqliteNOAAInit failed!"); statusUpdateMessage("dbsqliteNOAAInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the NOAA report generator radMsgLog (PRI_STATUS, "NOAA: initializing reports (this may take some time...)"); work->noaaId = noaaGenerateInit (work->mgrId->imagePath, work->isMetricUnits, msg->latitude, msg->longitude, msg->elevation, work->stationName, work->stationCity, work->stationState, msg->lastArcTime); if (work->noaaId == NULL) { radMsgLog (PRI_CATASTROPHIC, "noaaGenerateInit failed!"); statusUpdateMessage("noaaGenerateInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initialize the archive record browser generator radMsgLog (PRI_STATUS, "ARCREC: initializing archive browser files (this may take some time...)"); if (arcrecGenerateInit (work->mgrId->imagePath, work->arcrecDaysToKeep, work->isMetricUnits, work->archiveInterval) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "arcrecGenerateInit failed!"); statusUpdateMessage("arcrecGenerateInit failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } // initial data request then start the data acquisition timer if (requestDataPackets (work) == ERROR) { radMsgLog (PRI_HIGH, "htmlStationInfoState: requestDataPackets failed!"); statusUpdateMessage("requestDataPackets failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } radProcessTimerStart (work->rxTimer, HTML_RX_PACKETS_TIMEOUT); // wait here until a new second arrives ntime = time (NULL); localtime_r (&ntime, &locTime); oldSecs = newSecs = locTime.tm_sec; while (oldSecs == newSecs) { ntime = time (NULL); localtime_r (&ntime, &locTime); newSecs = locTime.tm_sec; } /* ... start the data timer to go off at the next 5 minute ... interval plus the user offset */ ntime = time (NULL); localtime_r (&ntime, &locTime); seconds = locTime.tm_sec - 10L; // start at 10 secs past offset = locTime.tm_min % 5L; // where are we in period? offset = 5 - offset; // how many mins to get to "0"? offset %= 5; // don't want "5" offset += work->startOffset; // user start in period if (offset == 0L) // prevent negative timeout seconds -= 60L; // make neg so timeout is pos if (seconds < -60L) { offset += 1L; seconds += 60L; } radMsgLog (PRI_STATUS, "starting html generation in %d mins %d secs", ((seconds > 0L) ? ((offset > 0L) ? offset - 1L : offset) : offset), (seconds > 0L) ? 60L - seconds : (-1L) * seconds); work->nextGenerationTime.tv_sec = (long)ntime + ((offset * 60L) - seconds); work->nextGenerationTime.tv_usec = 250L * 1000L; msOffset = 250L; // land on 250 ms mark radProcessTimerStart (work->timer, ((((offset * 60L) - seconds) * 1000L)) + msOffset); // 20041224 - Add an immediate generation cycle so longer // duration archive intervals don't have to wait up to 30 minutes // for the first generation radMsgLog (PRI_STATUS, "doing initial html generation now..."); work->numDataReceived = 0; statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); // Save an indicator in the run directory so web apps know when we are up: indicateFile = fopen (work->indicateFile, "w"); if (indicateFile == NULL) { radMsgLog (PRI_CATASTROPHIC, "indicator file create failed!"); statusUpdateMessage("indicator file create failed!"); statusUpdate(STATUS_ERROR); return HTML_STATE_ERROR; } fprintf (indicateFile, "%d", (int)msg->lastArcTime); fclose (indicateFile); return HTML_STATE_DATA; } break; } return state; }