void multiChartAddPoint (MULTICHART_ID id, double *values, char *name) { int i; if (id->numpoints >= MAX_GRAPH_POINTS) { return; } for (i = 0; i < id->numdatasets; i ++) { id->dataset[i].valueset[id->numpoints] = values[i]; if (values[i] > ARCHIVE_VALUE_NULL) { if (values[i] < id->min) normalizeMinMax (id, values[i], id->max); else if (values[i] > id->max) normalizeMinMax (id, id->min, values[i]); } } wvstrncpy (id->pointnames[id->numpoints], name, sizeof(id->pointnames[id->numpoints])); id->numpoints ++; return; }
MULTICHART_ID multiChartCreate ( int width, int height, char *title, int numDataSets, char *legends[] ) { int i; register MULTICHART_ID newId; newId = &nonReentrantMultiChart; memset (newId, 0, sizeof (*newId)); if (numDataSets > MC_MAX_DATA_SETS) numDataSets = MC_MAX_DATA_SETS; newId->numdatasets = numDataSets; for (i = 0; i < numDataSets; i ++) { wvstrncpy (newId->dataset[i].legend, legends[i], sizeof(newId->dataset[i].legend)); } newId->width = width; newId->height = height; wvstrncpy (newId->title, title, sizeof(newId->title)); // ... now set the contents coords newId->imtx = 5 * gdFontSmall->h/2; // ... SSM: move the right edge of the graph 5 pixels left to make // ... room for last label newId->imbx = (newId->width - 1) - gdFontMediumBold->h - 5; newId->imty = 2 * gdFontMediumBold->h; newId->imby = newId->height - (3 * gdFontMediumBold->h); newId->bgcolor = GLC_DFLT_BG; newId->chartcolor = GLC_DFLT_CHART; newId->gridcolor = GLC_DFLT_GRID; newId->titleFGcolor = GLC_DFLT_TITLEFG; newId->titleBGcolor = GLC_DFLT_TITLEBG; newId->textcolor = GLC_DFLT_TEXT; return newId; }
static int readHtmlTemplateFile (HTML_MGR *mgr, char *filename) { HTML_TMPL *html; FILE *file; char *token; char temp[HTML_MAX_LINE_LENGTH]; file = fopen (filename, "r"); if (file == NULL) { radMsgLog (PRI_HIGH, "htmlmgrInit: %s does not exist!", filename); return ERROR_ABORT; } while (fgets (temp, HTML_MAX_LINE_LENGTH, file) != NULL) { if (temp[0] == ' ' || temp[0] == '\n' || temp[0] == '#') { // comment or whitespace continue; } html = (HTML_TMPL *)malloc (sizeof (*html)); if (html == NULL) { for (html = (HTML_TMPL *)radListRemoveFirst (&mgr->templateList); html != NULL; html = (HTML_TMPL *)radListRemoveFirst (&mgr->templateList)) { free (html); } fclose (file); return ERROR; } // do the template file name token = strtok (temp, " \t\n"); if (token == NULL) { free (html); continue; } wvstrncpy (html->fname, token, sizeof(html->fname)); radListAddToEnd (&mgr->templateList, (NODE_PTR)html); } fclose (file); return OK; }
static int executeScript (WVIEW_ALARM *alarm) { int retVal; char *args[5]; char path[_MAX_PATH]; char type[64]; char thresh[64]; char trigVal[64]; wvstrncpy (path, alarm->scriptToRun, _MAX_PATH); args[0] = path; sprintf (type, "%d", alarm->type); args[1] = type; sprintf (thresh, "%.3f", alarm->bound); args[2] = thresh; sprintf (trigVal, "%.3f", alarm->triggerValue); args[3] = trigVal; args[4] = 0; retVal = fork (); if (retVal == -1) { return -1; } else if (retVal == 0) { // we are the child! if (execv (path, args) == -1) { radMsgLog(PRI_HIGH, "executeScript: execv(%s) failed: %s", path, strerror(errno)); exit(-1); } exit(0); } else { // we are the parent, pause a bit to let the script run // and avoid a process "storm" radUtilsSleep (50); // 50 ms } return 0; }
/* ... 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); }
/* ... the main entry point for the daemon process */ int main (int argc, char *argv[]) { void (*alarmHandler)(int); FILE *pidfile; int iValue; double dValue; const char* sValue; int runAsDaemon = TRUE; if (argc > 1) { if (!strcmp(argv[1], "-f")) { runAsDaemon = FALSE; } } /* ... start with a clean slate */ memset (&wviewdWork, 0, sizeof (wviewdWork)); /* ... initialize some system stuff first */ if (daemonSysInit (&wviewdWork) == -1) { radMsgLogInit (PROC_NAME_DAEMON, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "system init failed!\n"); radMsgLogExit (); exit (1); } /* ... call the global radlib system init function */ if (radSystemInit (WVIEW_SYSTEM_ID) == ERROR) { radMsgLogInit (PROC_NAME_DAEMON, TRUE, TRUE); radMsgLog (PRI_CATASTROPHIC, "radSystemInit failed!"); radMsgLogExit (); exit (1); } /* ... call the radlib process init function */ if (radProcessInit (PROC_NAME_DAEMON, wviewdWork.fifoFile, PROC_NUM_TIMERS_DAEMON, runAsDaemon, // TRUE for daemon msgHandler, evtHandler, NULL) == ERROR) { printf ("\nradProcessInit failed: %s\n\n", PROC_NAME_DAEMON); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } wviewdWork.myPid = getpid (); pidfile = fopen (wviewdWork.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); radMsgLog (PRI_STATUS, "%s starting ...", globalWviewVersionStr); radTimeGetMSSinceEpoch(); wvutilsDetectDSTInit(); // get our configuration values: if (wvconfigInit(TRUE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "config database is missing!!!\n"); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // get the wview verbosity setting if (wvutilsSetVerbosity (WV_VERBOSE_WVIEWD) == ERROR) { wvconfigExit(); radMsgLog (PRI_CATASTROPHIC, "wvutilsSetVerbosity failed!"); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } ///// STATION_INTERFACE PROCESSING BEGIN ///// sValue = wvconfigGetStringValue(configItem_STATION_STATION_TYPE); if (sValue == NULL) { radMsgLog (PRI_MEDIUM, "no station type given, defaulting to 'VantagePro'..."); strcpy (wviewdWork.stationType, "VantagePro"); } else { wvstrncpy(wviewdWork.stationType, sValue, sizeof(wviewdWork.stationType)); } if ((!strcmp(wviewdWork.stationType, "WMRUSB")) || (!strcmp(wviewdWork.stationType, "WH1080"))) { // USB stations: radMsgLog (PRI_MEDIUM, "station interface: native USB ..."); } else { sValue = wvconfigGetStringValue(configItem_STATION_STATION_INTERFACE); if (sValue == NULL) { radMsgLog (PRI_MEDIUM, "no station interface given, defaulting to 'serial'..."); strcpy (wviewdWork.stationInterface, "serial"); } else { wvstrncpy(wviewdWork.stationInterface, sValue, sizeof(wviewdWork.stationInterface)); } // process the interface type if (!strcmp (wviewdWork.stationInterface, "serial")) { radMsgLog (PRI_MEDIUM, "station interface: serial ..."); // we need a device name for serial IFs sValue = wvconfigGetStringValue(configItem_STATION_STATION_DEV); if (sValue == NULL) { wvconfigExit(); radMsgLog (PRI_CATASTROPHIC, "no serial device given, aborting..."); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy(wviewdWork.stationDevice, sValue, sizeof(wviewdWork.stationDevice)); } // grab the DTR toggle flag: iValue = wvconfigGetBooleanValue(configItem_STATION_STATION_DTR); if (iValue >= 0) { wviewdWork.stationToggleDTR = iValue; } else { wviewdWork.stationToggleDTR = TRUE; } } else if (!strcmp (wviewdWork.stationInterface, "ethernet")) { radMsgLog (PRI_MEDIUM, "station interface: ethernet ..."); // we need host and port for ethernet sValue = wvconfigGetStringValue(configItem_STATION_STATION_HOST); if (sValue == NULL) { wvconfigExit(); radMsgLog (PRI_CATASTROPHIC, "no hostname given, aborting..."); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wvstrncpy(wviewdWork.stationHost, sValue, sizeof(wviewdWork.stationHost)); iValue = wvconfigGetINTValue(configItem_STATION_STATION_PORT); if (iValue <= 0) { wvconfigExit(); radMsgLog (PRI_CATASTROPHIC, "no port given, aborting..."); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } else { wviewdWork.stationPort = iValue; // grab the Weatherlink IP flag: iValue = wvconfigGetBooleanValue(configItem_STATION_STATION_WLIP); if (iValue >= 0) { wviewdWork.stationIsWLIP = iValue; } else { wviewdWork.stationIsWLIP = FALSE; } } } } else { // invalid type specified - abort wvconfigExit(); radMsgLog (PRI_CATASTROPHIC, "invalid STATION_INTERFACE %s given, aborting...", wviewdWork.stationInterface); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } } ///// STATION_INTERFACE PROCESSING END ///// iValue = wvconfigGetINTValue(configItem_STATION_STATION_RAIN_SEASON_START); if (iValue <= 0) { radMsgLog (PRI_MEDIUM, "Rain Season Start Month not found - defaulting to 1 (JAN)...\n"); wviewdWork.stationRainSeasonStart = 1; } else { wviewdWork.stationRainSeasonStart = iValue; if (wviewdWork.stationRainSeasonStart < 1 || wviewdWork.stationRainSeasonStart > 12) { radMsgLog (PRI_MEDIUM, "Invalid Rain Season Start Month %d found - defaulting to 1 (JAN)...\n", wviewdWork.stationRainSeasonStart); wviewdWork.stationRainSeasonStart = 1; } else { radMsgLog (PRI_STATUS, "Rain Season Start Month set to %d\n", wviewdWork.stationRainSeasonStart); } } dValue = wvconfigGetDOUBLEValue(configItem_STATION_STATION_RAIN_STORM_TRIGGER_START); if (dValue <= 0.0) { radMsgLog (PRI_MEDIUM, "no rain storm start trigger given, defaulting to 0.05 in/hr..."); wviewdWork.stationRainStormTrigger = 0.05; } else { wviewdWork.stationRainStormTrigger = (float)dValue; radMsgLog (PRI_STATUS, "Rain Storm Start Trigger set to %5.2f in/hr\n", wviewdWork.stationRainStormTrigger); } iValue = wvconfigGetINTValue(configItem_STATION_STATION_RAIN_STORM_IDLE_STOP); if (iValue <= 0) { radMsgLog (PRI_MEDIUM, "no rain storm idle stop time given, defaulting to 12 hours..."); wviewdWork.stationRainStormIdleHours = 12; } else { wviewdWork.stationRainStormIdleHours = iValue; radMsgLog (PRI_STATUS, "Rain Storm Stop Time set to %d hours\n", wviewdWork.stationRainStormIdleHours); } dValue = wvconfigGetDOUBLEValue(configItem_STATION_STATION_RAIN_YTD); if (dValue < 0.0) { radMsgLog (PRI_MEDIUM, "no rain YTD preset given, defaulting to 0.00 inches..."); wviewdWork.stationRainStormIdleHours = 12; } else { wviewdWork.stationRainYTDPreset = (float)dValue; radMsgLog (PRI_STATUS, "Rain YTD preset set to %.2f inches\n", wviewdWork.stationRainYTDPreset); } dValue = wvconfigGetDOUBLEValue(configItem_STATION_STATION_ET_YTD); if (dValue < 0.0) { radMsgLog (PRI_MEDIUM, "no ET YTD preset given, defaulting to 0.000 inches..."); wviewdWork.stationETYTDPreset = 0; } else { wviewdWork.stationETYTDPreset = (float)dValue; radMsgLog (PRI_STATUS, "ET YTD preset set to %.3f inches\n", wviewdWork.stationETYTDPreset); } iValue = wvconfigGetINTValue(configItem_STATION_STATION_RAIN_ET_YTD_YEAR); if (iValue < 0) { radMsgLog (PRI_MEDIUM, "no rain/ET YTD Year given, disabling..."); wviewdWork.stationRainETPresetYear = 0; } else { wviewdWork.stationRainETPresetYear = iValue; if (wviewdWork.stationRainETPresetYear < 2000 || wviewdWork.stationRainETPresetYear > 3000) { radMsgLog (PRI_MEDIUM, "bad rain/ET YTD Year given, disabling..."); wviewdWork.stationRainETPresetYear = 0; } else { radMsgLog (PRI_STATUS, "rain/ET YTD preset Year set to %d\n", wviewdWork.stationRainETPresetYear); } } iValue = wvconfigGetINTValue(configItem_STATION_POLL_INTERVAL); if (iValue < 0) { radMsgLog (PRI_MEDIUM, "no POLL_INTERVAL retrieved, setting to 30 seconds..."); wviewdWork.cdataInterval = 30000; } else { wviewdWork.cdataInterval = iValue * 1000; } if (((wviewdWork.cdataInterval % 1000) != 0) || ((wviewdWork.cdataInterval/1000) > 60) || ((60 % (wviewdWork.cdataInterval/1000)) != 0)) { radMsgLog (PRI_MEDIUM, "station polling interval %d found in wview.conf is invalid:", wviewdWork.cdataInterval); radMsgLog (PRI_MEDIUM, "defaulting to 30 seconds ..."); radMsgLog (PRI_MEDIUM, "Note: station polling interval must be less than 60 seconds"); radMsgLog (PRI_MEDIUM, " and an even divisor of 60 seconds (10000, 15000, 30000)"); wviewdWork.cdataInterval = 30 * 1000; } else { radMsgLog (PRI_STATUS, "station polling interval set to %d seconds", (wviewdWork.cdataInterval/1000)); } iValue = wvconfigGetINTValue(configItem_STATION_PUSH_INTERVAL); if (iValue < 0) { radMsgLog (PRI_MEDIUM, "no PUSH_INTERVAL retrieved, setting to 60 seconds..."); wviewdWork.pushInterval = 60000; } else { wviewdWork.pushInterval = iValue * 1000; } // Calibration configuration: dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_BAROMETER); if (dValue <= 0.0) { wviewdWork.calMBarometer = 1.00; } else { wviewdWork.calMBarometer = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_BAROMETER); wviewdWork.calCBarometer = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_PRESSURE); if (dValue <= 0.0) { wviewdWork.calMPressure = 1.00; } else { wviewdWork.calMPressure = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_PRESSURE); wviewdWork.calCPressure = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_ALTIMETER); if (dValue <= 0.0) { wviewdWork.calMAltimeter = 1.00; } else { wviewdWork.calMAltimeter = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_ALTIMETER); wviewdWork.calCAltimeter = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_INTEMP); if (dValue <= 0.0) { wviewdWork.calMInTemp = 1.00; } else { wviewdWork.calMInTemp = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_INTEMP); wviewdWork.calCInTemp = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_OUTTEMP); if (dValue <= 0.0) { wviewdWork.calMOutTemp = 1.00; } else { wviewdWork.calMOutTemp = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_OUTTEMP); wviewdWork.calCOutTemp = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_INHUMIDITY); if (dValue <= 0.0) { wviewdWork.calMInHumidity = 1.00; } else { wviewdWork.calMInHumidity = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_INHUMIDITY); wviewdWork.calCInHumidity = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_OUTHUMIDITY); if (dValue <= 0.0) { wviewdWork.calMOutHumidity = 1.00; } else { wviewdWork.calMOutHumidity = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_OUTHUMIDITY); wviewdWork.calCOutHumidity = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_WINDSPEED); if (dValue <= 0.0) { wviewdWork.calMWindSpeed = 1.00; } else { wviewdWork.calMWindSpeed = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_WINDSPEED); wviewdWork.calCWindSpeed = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_WINDDIR); if (dValue <= 0.0) { wviewdWork.calMWindDir = 1.00; } else { wviewdWork.calMWindDir = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_WINDDIR); wviewdWork.calCWindDir = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_RAIN); if (dValue <= 0.0) { wviewdWork.calMRain = 1.00; } else { wviewdWork.calMRain = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_RAIN); wviewdWork.calCRain = dValue; dValue = wvconfigGetDOUBLEValue(configItemCAL_MULT_RAINRATE); if (dValue <= 0.0) { wviewdWork.calMRainRate = 1.00; } else { wviewdWork.calMRainRate = dValue; } dValue = wvconfigGetDOUBLEValue(configItemCAL_CONST_RAINRATE); wviewdWork.calCRainRate = dValue; iValue = wvconfigGetBooleanValue(configItem_ENABLE_EMAIL); if (iValue >= 0) { wviewdWork.IsAlertEmailsEnabled = iValue; } if (wviewdWork.IsAlertEmailsEnabled) { sValue = wvconfigGetStringValue(configItem_TO_EMAIL_ADDRESS); if (sValue == NULL) { radMsgLog (PRI_HIGH, "NO alert email TO address given - disabling email alerts..."); wviewdWork.IsAlertEmailsEnabled = 0; } else { wvstrncpy (wviewdWork.alertEmailToAdrs, sValue, sizeof(wviewdWork.alertEmailToAdrs)); } sValue = wvconfigGetStringValue(configItem_FROM_EMAIL_ADDRESS); if (sValue == NULL) { radMsgLog (PRI_HIGH, "NO alert email FROM address given - disabling email alerts..."); wviewdWork.IsAlertEmailsEnabled = 0; } else { wvstrncpy (wviewdWork.alertEmailFromAdrs, sValue, sizeof(wviewdWork.alertEmailFromAdrs)); } iValue = wvconfigGetBooleanValue(configItem_SEND_TEST_EMAIL); if (iValue >= 0) { wviewdWork.IsTestEmailEnabled = iValue; } } iValue = wvconfigGetBooleanValue(configItem_HTMLGEN_STATION_SHOW_IF); if (iValue >= 0) { wviewdWork.showStationIF = iValue; } else { wviewdWork.showStationIF = TRUE; } wvconfigExit (); if (statusInit(wviewdWork.statusFile, wviewStatusLabels) == ERROR) { radMsgLog (PRI_HIGH, "statusInit failed - exiting..."); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } statusUpdate(STATUS_BOOTING); // ... Initialize the archive database interface: if (dbsqliteArchiveInit() == ERROR) { radMsgLog (PRI_HIGH, "dbsqliteArchiveInit failed"); statusUpdateMessage("dbsqliteArchiveInit failed"); statusUpdate(STATUS_ERROR); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // Initialize timers: wviewdWork.archiveTimer = radTimerCreate (NULL, archiveTimerHandler, NULL); if (wviewdWork.archiveTimer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed"); statusUpdateMessage("radTimerCreate failed"); statusUpdate(STATUS_ERROR); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } wviewdWork.cdataTimer = radTimerCreate (NULL, cdtimerHandler, NULL); if (wviewdWork.cdataTimer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed"); statusUpdateMessage("radTimerCreate failed"); statusUpdate(STATUS_ERROR); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } wviewdWork.pushTimer = radTimerCreate (NULL, pushTimerHandler, NULL); if (wviewdWork.pushTimer == NULL) { radMsgLog (PRI_HIGH, "radTimerCreate failed"); statusUpdateMessage("radTimerCreate failed"); statusUpdate(STATUS_ERROR); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } wviewdWork.syncTimer = radTimerCreate (NULL, syncTimerHandler, NULL); if (wviewdWork.syncTimer == NULL) { radMsgLog (PRI_HIGH, "sync radTimerCreate failed"); statusUpdateMessage("radTimerCreate failed"); statusUpdate(STATUS_ERROR); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } wviewdWork.ifTimer = radTimerCreate (NULL, ifTimerHandler, NULL); if (wviewdWork.ifTimer == NULL) { radMsgLog (PRI_HIGH, "sync radTimerCreate failed"); statusUpdateMessage("radTimerCreate failed"); statusUpdate(STATUS_ERROR); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } radProcessEventsAdd (STATION_INIT_COMPLETE_EVENT); radProcessEventsAdd (STATION_LOOP_COMPLETE_EVENT); // register with the radlib message router if (radMsgRouterInit (WVIEW_RUN_DIR) == ERROR) { radMsgLog (PRI_HIGH, "radMsgRouterInit failed!"); statusUpdateMessage("radMsgRouterInit failed"); statusUpdate(STATUS_ERROR); radTimerDelete (wviewdWork.ifTimer); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // enable message reception from the radlib router for worker requests radMsgRouterMessageRegister (WVIEW_MSG_TYPE_REQUEST); // enable message reception from the radlib router for POLL msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_POLL); // enable message reception from the radlib router for ALERT msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_ALERT); // enable message reception from the radlib router for STATION_DATA msgs radMsgRouterMessageRegister (WVIEW_MSG_TYPE_STATION_DATA); // Initialize the HILOW database interface: // (this cannot occur before the MsgRouter is initialized) if (dbsqliteHiLowInit(TRUE) == ERROR) { radMsgLog (PRI_HIGH, "dbsqliteHiLowInit failed"); statusUpdateMessage("dbsqliteHiLowInit failed"); statusUpdate(STATUS_ERROR); stationSendShutdown(&wviewdWork); radMsgRouterExit (); radTimerDelete (wviewdWork.ifTimer); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // initialize the station abstraction radMsgLog (PRI_STATUS, "-- Station Init Start --"); if (stationInit (&wviewdWork, daemonArchiveIndication) == ERROR) { radMsgLog (PRI_HIGH, "stationInit failed!"); statusUpdateMessage("stationInit failed"); statusUpdate(STATUS_ERROR); stationSendShutdown(&wviewdWork); radMsgRouterExit (); radTimerDelete (wviewdWork.ifTimer); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } // register the station interface if it is device-based: if (wviewdWork.medium.type == MEDIUM_TYPE_DEVICE) { if (radProcessIORegisterDescriptor (wviewdWork.medium.fd, stationDataCallback, NULL) == ERROR) { radMsgLog (PRI_HIGH, "IORegDescriptor failed"); statusUpdateMessage("IORegDescriptor failed"); statusUpdate(STATUS_ERROR); stationSendShutdown(&wviewdWork); radMsgRouterExit (); radTimerDelete (wviewdWork.ifTimer); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.archiveTimer); stationExit (&wviewdWork); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (1); } } // Send test email if it is enabled: if (wviewdWork.IsTestEmailEnabled) { radMsgLog(PRI_STATUS, "Sending test email..."); emailAlertSend(ALERT_TYPE_TEST); } statusUpdate(STATUS_RUNNING); statusUpdateMessage("Normal operation"); radMsgLog (PRI_STATUS, "running..."); while (!wviewdWork.exiting) { // wait on timers, events, file descriptors, msgs if (radProcessWait (0) == ERROR) { wviewdWork.exiting = TRUE; } } statusUpdateMessage("exiting normally"); radMsgLog (PRI_STATUS, "exiting normally..."); statusUpdate(STATUS_SHUTDOWN); computedDataExit (&wviewdWork); radMsgRouterExit (); radTimerDelete (wviewdWork.ifTimer); radTimerDelete (wviewdWork.syncTimer); radTimerDelete (wviewdWork.pushTimer); radTimerDelete (wviewdWork.cdataTimer); radTimerDelete (wviewdWork.archiveTimer); stationExit (&wviewdWork); dbsqliteHiLowExit(); dbsqliteArchiveExit(); daemonSysExit (&wviewdWork); radProcessExit (); radSystemExit (WVIEW_SYSTEM_ID); exit (0); }
// station-supplied init function // -- Can Be Asynchronous - event indication required -- // // MUST: // - set the 'stationGeneratesArchives' flag in WVIEWD_WORK: // if the station generates archive records (TRUE) or they should be // generated automatically by the daemon from the sensor readings (FALSE) // - Initialize the 'stationData' store for station work area // - Initialize the interface medium // - do initial LOOP acquisition // - do any catch-up on archive records if there is a data logger // - 'work->runningFlag' can be used for start up synchronization but should // not be modified by the station interface code // - indicate init is done by sending the STATION_INIT_COMPLETE_EVENT event to // this process (radProcessEventsSend (NULL, STATION_INIT_COMPLETE_EVENT, 0)) // // OPTIONAL: // - Initialize a state machine or any other construct required for the // station interface - these should be stored in the 'stationData' store // // 'archiveIndication' - indication callback used to pass back an archive record // generated as a result of 'stationGetArchive' being called; should receive a // NULL pointer for 'newRecord' if no record available; only used if // 'stationGeneratesArchives' flag is set to TRUE by the station interface // // Returns: OK or ERROR // int stationInit ( WVIEWD_WORK *work, void (*archiveIndication)(ARCHIVE_PKT* newRecord) ) { int i; time_t nowTime = time(NULL) - (WV_SECONDS_IN_HOUR * 12); ARCHIVE_PKT recordStore; ARCHIVE_PKT newestRecord; char tempStr[WVIEW_MAX_PATH]; memset (&virtualWorkData, 0, sizeof(virtualWorkData)); // save the archive indication callback (we should never need it) ArchiveIndicator = archiveIndication; // set our work data pointer work->stationData = &virtualWorkData; // set the Archive Generation flag to indicate the VIRTUAL DOES NOT // generate them work->stationGeneratesArchives = TRUE; // initialize the medium abstraction based on user configuration if (!strcmp (work->stationInterface, "serial")) { radMsgLog (PRI_HIGH, "stationInit: serial medium not supported for virtual station!"); return ERROR; } else if (!strcmp (work->stationInterface, "ethernet")) { if (ethernetMediumInit (&work->medium, work->stationHost, work->stationPort) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: ethernet MediumInit failed"); return ERROR; } } else { radMsgLog (PRI_HIGH, "stationInit: medium %s not supported", work->stationInterface); return ERROR; } // initialize the interface using the media specific routine if ((*(work->medium.init))(&work->medium, work->stationDevice) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: medium setup failed"); return ERROR; } // Make the socket blocking: radSocketSetBlocking ((*(work->medium.getsocket))(&work->medium), TRUE); // Reset the stationType to include the host:port: sprintf(tempStr, "%s:%s:%d", work->stationType, work->stationHost, work->stationPort); wvstrncpy(work->stationType, tempStr, sizeof(work->stationType)); if (!strcmp (work->stationInterface, "ethernet")) { radMsgLog (PRI_STATUS, "VIRTUAL on %s:%d opened ...", work->stationHost, work->stationPort); } // grab the station configuration now if (stationGetConfigValueInt (work, STATION_PARM_ELEVATION, &virtualWorkData.elevation) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ELEV failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LATITUDE, &virtualWorkData.latitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LAT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueFloat (work, STATION_PARM_LONGITUDE, &virtualWorkData.longitude) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt LONG failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } if (stationGetConfigValueInt (work, STATION_PARM_ARC_INTERVAL, &virtualWorkData.archiveInterval) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: stationGetConfigValueInt ARCINT failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // set the work archive interval now work->archiveInterval = virtualWorkData.archiveInterval; // sanity check the archive interval against the most recent record if (stationVerifyArchiveInterval (work) == ERROR) { // bad magic! radMsgLog (PRI_HIGH, "stationInit: stationVerifyArchiveInterval failed!"); radMsgLog (PRI_HIGH, "You must either move old archive data out of the way -or-"); radMsgLog (PRI_HIGH, "fix the interval setting..."); (*(work->medium.exit)) (&work->medium); return ERROR; } else { radMsgLog (PRI_STATUS, "station archive interval: %d minutes", work->archiveInterval); } radMsgLog (PRI_STATUS, "Starting station interface: VIRTUAL"); // This must be done here: work->archiveDateTime = dbsqliteArchiveGetNewestTime(&newestRecord); if ((int)work->archiveDateTime == ERROR) { work->archiveDateTime = 0; radMsgLog (PRI_STATUS, "stationInit: no archive records found in database!"); } // initialize the station interface if (virtualProtocolInit(work) == ERROR) { radMsgLog (PRI_HIGH, "stationInit: virtualProtocolInit failed!"); (*(work->medium.exit)) (&work->medium); return ERROR; } // do the initial GetReadings now if (virtualProtocolGetReadings(work, &virtualWorkData.virtualReadings) != OK) { radMsgLog (PRI_HIGH, "stationInit: initial virtualProtocolGetReadings failed!"); virtualProtocolExit (work); (*(work->medium.exit)) (&work->medium); return ERROR; } // populate the LOOP structure storeLoopPkt (&work->loopPkt, &virtualWorkData); // we must indicate successful completion here - // even though we are synchronous, the daemon wants to see this event radProcessEventsSend(NULL, STATION_INIT_COMPLETE_EVENT, 0); 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); }
void multiChartSetDateTime (MULTICHART_ID id, char *datetime) { wvstrncpy (id->datetime, datetime, sizeof(id->datetime)); return; }
static void drawTitle (MULTICHART_ID id) { int i, totalLen = 0; char xtitle[WVIEW_STRING1_SIZE]; gdImageFilledRectangle (id->im, 0, 0, id->width, gdFontMediumBold->h, id->titleBGcolor); if (strlen(id->DualUnit) != 0) { wvstrncpy (xtitle, id->title, sizeof(xtitle)); if ((strcmp(id->title,"knots") == 0) || (strcmp(id->title,"m/s") == 0)) { if (id->isMetric) { strcpy (xtitle, "km/h"); } else { strcpy (xtitle, "mph"); } } for (i = 0; i < id->numdatasets; i ++) { totalLen += 2; totalLen += (((gdFontMediumBold->h/2)+2) * strlen (id->dataset[i].legend)); } totalLen = (id->width - totalLen) - 3; totalLen /= 2; // totalLen = (((gdFontMediumBold->h/2)+2) * strlen (xtitle))+2; for (i = 0; i < id->numdatasets; i ++) { totalLen += 2; gdImageString (id->im, gdFontMediumBold, totalLen, 0, (UCHAR *)id->dataset[i].legend, id->dataset[i].lineColor); totalLen += (((gdFontMediumBold->h/2)+2) * strlen (id->dataset[i].legend)); } gdImageString (id->im, gdFontMediumBold, id->width - (((gdFontMediumBold->h/2)+2) * strlen (id->DualUnit)), 0, (UCHAR *)id->DualUnit, id->titleFGcolor); gdImageString (id->im, gdFontMediumBold, 2, 0, (UCHAR *)xtitle, id->titleFGcolor); } else { for (i = 0; i < id->numdatasets; i ++) { totalLen += 2; gdImageString (id->im, gdFontMediumBold, totalLen, 0, (UCHAR *)id->dataset[i].legend, id->dataset[i].lineColor); totalLen += (((gdFontMediumBold->h/2)+2) * strlen (id->dataset[i].legend)); } gdImageString (id->im, gdFontMediumBold, id->width - (((gdFontMediumBold->h/2)+2) * strlen (id->title)), 0, (UCHAR *)id->title, id->titleFGcolor); } }
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; }
static int readImageConfFile (HTML_MGR *mgr, char *filename, int isUser) { HTML_IMG *img; FILE *file; int i, done; char *token; char temp[1536]; file = fopen (filename, "r"); if (file == NULL) { radMsgLog (PRI_HIGH, "htmlmgrInit: %s does not exist!", filename); return ERROR_ABORT; } while (fgets (temp, 1536, file) != NULL) { if (temp[0] == ' ' || temp[0] == '\n' || temp[0] == '#') { // comment or whitespace continue; } token = strtok (temp, " \t"); if (token == NULL) { continue; } img = (HTML_IMG *)malloc (sizeof (*img)); if (img == NULL) { for (img = (HTML_IMG *)radListRemoveFirst (&mgr->imgList); img != NULL; img = (HTML_IMG *)radListRemoveFirst (&mgr->imgList)) { free (img); } fclose (file); return ERROR; } memset (img, 0, sizeof (*img)); img->mgrWork = mgr; // ... if legacy image type is found, skip it if (!strncmp (token, "IMG_TYPE_", 9)) { // get the next token token = strtok (NULL, " \t"); if (token == NULL) { free (img); goto line_loop_end; } } // ... do the file name wvstrncpy (img->fname, token, sizeof(img->fname)); // ... now the label token = strtok (NULL, " \t"); if (token == NULL) { free (img); goto line_loop_end; } if (token[strlen(token)-1] == '"') { // we're done! strncpy (img->title, &token[1], strlen(token)-2); // lose quotes } else { done = FALSE; wvstrncpy (img->title, &token[1], sizeof(img->title)); while (!done) { token = strtok (NULL, " "); if (token == NULL) { free(img); goto line_loop_end; } else { if (token[strlen(token)-1] == '"') { done = TRUE; token[strlen(token)-1] = 0; } strcat (img->title, " "); strcat (img->title, token); } } } // ... now the units label (no spaces allowed) token = strtok (NULL, " \t"); if (token == NULL) { free (img); goto line_loop_end; } wvstrncpy (img->units, token, sizeof(img->units)); // ... now the decimal places token = strtok (NULL, " \t"); if (token == NULL) { free (img); goto line_loop_end; } img->decimalPlaces = atoi (token); // ... finally, the generator index token = strtok (NULL, " \t\n"); if (token == NULL) { free (img); goto line_loop_end; } i = atoi (token); if (isUser) { img->generator = user_generators[i]; } else { img->generator = images_generators[i]; } radListAddToEnd (&mgr->imgList, (NODE_PTR)img); // Loop end label: line_loop_end: continue; } fclose (file); return OK; }
HTML_MGR_ID htmlmgrInit ( char *installPath, int isMetricUnits, char *imagePath, char *htmlPath, int arcInterval, int isExtendedData, char *name, char *city, char *state, int16_t elevation, int16_t latitude, int16_t longitude, char *mphaseIncrease, char *mphaseDecrease, char *mphaseFull, char *radarURL, char *forecastURL, char *dateFormat, int isDualUnits ) { HTML_MGR_ID newId; int i, numNodes, numImages, numTemplates; char confFilePath[256]; newId = &mgrWork; memset (newId, 0, sizeof (mgrWork)); radListReset (&newId->imgList); radListReset (&newId->templateList); newId->isMetricUnits = isMetricUnits; newId->archiveInterval = arcInterval; newId->isExtendedData = isExtendedData; newId->imagePath = imagePath; newId->htmlPath = htmlPath; newId->stationElevation = elevation; newId->stationLatitude = latitude; newId->stationLongitude = longitude; wvstrncpy (newId->stationName, name, sizeof(newId->stationName)); wvstrncpy (newId->stationCity, city, sizeof(newId->stationCity)); wvstrncpy (newId->stationState, state, sizeof(newId->stationState)); wvstrncpy (newId->mphaseIncrease, mphaseIncrease, sizeof(newId->mphaseIncrease)); wvstrncpy (newId->mphaseDecrease, mphaseDecrease, sizeof(newId->mphaseDecrease)); wvstrncpy (newId->mphaseFull, mphaseFull, sizeof(newId->mphaseFull)); wvstrncpy (newId->radarURL, radarURL, sizeof(newId->radarURL)); wvstrncpy (newId->forecastURL, forecastURL, sizeof(newId->forecastURL)); wvstrncpy (newId->dateFormat, dateFormat, sizeof(newId->dateFormat)); newId->isDualUnits = isDualUnits; // ... initialize the newArchiveMask newId->newArchiveMask = NEW_ARCHIVE_ALL; // ... first, the built-in generators sprintf (confFilePath, "%s/images.conf", installPath); if (readImageConfFile (newId, confFilePath, FALSE) != OK) { return NULL; } else { numNodes = radListGetNumberOfNodes (&newId->imgList); radMsgLog (PRI_STATUS, "htmlmgrInit: %d built-in image definitions added", numNodes); numImages = numNodes; } // ... next, the user-defined generators sprintf (confFilePath, "%s/images-user.conf", installPath); i = readImageConfFile (newId, confFilePath, TRUE); if (i == ERROR_ABORT) { radMsgLog (PRI_STATUS, "htmlmgrInit: no user image definitions found"); } else if (i == ERROR) { return NULL; } else { numImages = radListGetNumberOfNodes (&newId->imgList); radMsgLog (PRI_STATUS, "htmlmgrInit: %d user image definitions added", radListGetNumberOfNodes (&newId->imgList) - numNodes); } // ... now initialize our html template list sprintf (confFilePath, "%s/html-templates.conf", installPath); if (readHtmlTemplateFile (newId, confFilePath) != OK) { return NULL; } else { numTemplates = radListGetNumberOfNodes (&newId->templateList); radMsgLog (PRI_STATUS, "htmlmgrInit: %d templates added", numTemplates); } // ... now initialize our forecast rule text list sprintf (confFilePath, "%s/forecast.conf", installPath); if (readForecastRuleConfigFile (newId, confFilePath) != OK) { radMsgLog (PRI_STATUS, "htmlmgrInit: forecast html tags are disabled - %s not found...", confFilePath); } // ... initialize the sample label array htmlmgrSetSampleLabels(newId); // ... initialize our dial palette to conserve CPU cycles if (htmlGenPngDialInit (newId->imagePath) == ERROR) { radMsgLog (PRI_HIGH, "htmlmgrInit: htmlGenPngDialInit failed!"); return NULL; } statusUpdateStat(HTML_STATS_IMAGES_DEFINED, numImages); statusUpdateStat(HTML_STATS_TEMPLATES_DEFINED, numTemplates); return newId; }
static int readForecastRuleConfigFile (HTML_MGR *mgr, char *filename) { FILE *file; char *token; char temp[HTML_MAX_LINE_LENGTH]; int iconNo = 1, ruleNo = 0; file = fopen (filename, "r"); if (file == NULL) { return ERROR_ABORT; } // read each line starting with "ICON", assigning to the corresponding // forecast icon while (fgets (temp, HTML_MAX_LINE_LENGTH-1, file) != NULL) { // does the line begin with "ICON"? if (strncmp (temp, "ICON", 4)) { // nope continue; } // get the memory to store the string mgr->ForecastIconFile[iconNo] = (char *) malloc (FORECAST_ICON_FN_MAX); if (mgr->ForecastIconFile[iconNo] == NULL) { radMsgLog (PRI_HIGH, "readForecastRuleConfigFile: cannot allocate memory for forecast icon #%d!", iconNo); cleanupForecastRules (mgr); fclose(file); return ERROR; } // skip the ICON keyword token = strtok (temp, " \t"); if (token == NULL) { free (mgr->ForecastIconFile[iconNo]); mgr->ForecastIconFile[iconNo] = NULL; continue; } token = strtok (NULL, " \t\n"); if (token == NULL) { free (mgr->ForecastIconFile[iconNo]); mgr->ForecastIconFile[iconNo] = NULL; continue; } wvstrncpy (mgr->ForecastIconFile[iconNo], token, FORECAST_ICON_FN_MAX); if (mgr->ForecastIconFile[iconNo][strlen(mgr->ForecastIconFile[iconNo]) - 1] == '\n') mgr->ForecastIconFile[iconNo][strlen(mgr->ForecastIconFile[iconNo]) - 1] = 0; if (++iconNo == (VP_FCAST_ICON_MAX + 1)) { // we're done! break; } } // reset to the beginning of the file fseek (file, 0, SEEK_SET); // throw away all lines until we hit the keyword "RULES" while (fgets (temp, HTML_MAX_LINE_LENGTH-1, file) != NULL) { if (!strncmp (temp, "<RULES>", 7)) { // begin the rule dance break; } } // read each line, assigning to the corresponding forecast rule while (fgets (temp, HTML_MAX_LINE_LENGTH-1, file) != NULL) { // get the memory to store the string mgr->ForecastRuleText[ruleNo] = (char *) malloc (strlen(temp) + 1); if (mgr->ForecastRuleText[ruleNo] == NULL) { radMsgLog (PRI_HIGH, "readForecastRuleConfigFile: cannot allocate memory for forecast rule #%d!", ruleNo); cleanupForecastRules (mgr); fclose(file); return ERROR; } // copy the string (we know temp is bounded and we allocated for its length): strcpy (mgr->ForecastRuleText[ruleNo], temp); if (mgr->ForecastRuleText[ruleNo][strlen(temp) - 1] == '\n') mgr->ForecastRuleText[ruleNo][strlen(temp) - 1] = 0; if (++ruleNo == (HTML_MAX_FCAST_RULE + 1)) { // we're done! break; } } // did we find them all? if (ruleNo != (HTML_MAX_FCAST_RULE + 1)) { // nope, let's fuss about it radMsgLog (PRI_MEDIUM, "readForecastRuleConfigFile: NOT all forecast rules are assigned in %s: " "the last %d are missing and will be empty ...", filename, (HTML_MAX_FCAST_RULE + 1) - ruleNo); } if (iconNo != (VP_FCAST_ICON_MAX + 1)) { // nope, let's fuss about it radMsgLog (PRI_MEDIUM, "readForecastRuleConfigFile: NOT all forecast icons are assigned in %s: " "the last %d are missing and will be empty ...", filename, (VP_FCAST_ICON_MAX + 1) - iconNo); } radMsgLog (PRI_STATUS, "%d icon definitions, %d forecast rules found ...", iconNo - 1, ruleNo); fclose (file); return OK; }
static int readAlarmsConfig (void) { WVIEW_ALARM *alarm; int i, numAlarms = 0; int iValue; char type[_MAX_PATH]; int boolMAX; double thresh; int abate; char exec[_MAX_PATH]; char conftype[64]; const char* temp; if (wvconfigInit(FALSE) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "wvconfigInit failed!"); return ERROR; } // Is the alarms daemon enabled? iValue = wvconfigGetBooleanValue(configItem_ENABLE_ALARMS); if (iValue == ERROR || iValue == 0) { wvconfigExit (); return ERROR_ABORT; } // set the wview verbosity setting if (wvutilsSetVerbosity (WV_VERBOSE_WVALARMD) == ERROR) { radMsgLog (PRI_CATASTROPHIC, "wvutilsSetVerbosity failed!"); wvconfigExit (); return ERROR_ABORT; } // get the metric units flag: iValue = wvconfigGetBooleanValue(configItem_ALARMS_STATION_METRIC); if (iValue == ERROR) { alarmsWork.isMetric = 0; } else { alarmsWork.isMetric = iValue; } // get the do test flag: iValue = wvconfigGetBooleanValue(configItem_ALARMS_DO_TEST); if (iValue <= 0) { alarmsWork.doTest = FALSE; } else { alarmsWork.doTest = TRUE; alarmsWork.doTestNumber = wvconfigGetINTValue(configItem_ALARMS_DO_TEST_NUMBER); } for (i = 1; i <= ALARMS_MAX; i ++) { sprintf (conftype, "ALARMS_%1.1d_TYPE", i); temp = wvconfigGetStringValue(conftype); if (temp == NULL) { // No type defined - continue: continue; } wvstrncpy(type, temp, _MAX_PATH); sprintf (conftype, "ALARMS_%1.1d_MAX", i); boolMAX = wvconfigGetBooleanValue(conftype); if (boolMAX == ERROR) { continue; } sprintf (conftype, "ALARMS_%1.1d_THRESHOLD", i); thresh = wvconfigGetDOUBLEValue(conftype); sprintf (conftype, "ALARMS_%1.1d_ABATEMENT", i); abate = wvconfigGetINTValue(conftype); sprintf (conftype, "ALARMS_%1.1d_EXECUTE", i); temp = wvconfigGetStringValue(conftype); if (temp == NULL) { // No type defined - continue: continue; } wvstrncpy(exec, temp, _MAX_PATH); alarm = (WVIEW_ALARM *) malloc (sizeof (*alarm)); if (alarm == NULL) { for (alarm = (WVIEW_ALARM *)radListRemoveFirst (&alarmsWork.alarmList); alarm != NULL; alarm = (WVIEW_ALARM *)radListRemoveFirst (&alarmsWork.alarmList)) { free (alarm); } return ERROR; } memset (alarm, 0, sizeof (*alarm)); // get the type if (!strcmp (type, "Barometer")) { alarm->type = Barometer; } else if (!strcmp (type, "InsideTemp")) { alarm->type = InsideTemp; } else if (!strcmp (type, "InsideHumidity")) { alarm->type = InsideHumidity; } else if (!strcmp (type, "OutsideTemp")) { alarm->type = OutsideTemp; } else if (!strcmp (type, "WindSpeed")) { alarm->type = WindSpeed; } else if (!strcmp (type, "TenMinuteAvgWindSpeed")) { alarm->type = TenMinuteAvgWindSpeed; } else if (!strcmp (type, "WindDirection")) { alarm->type = WindDirection; } else if (!strcmp (type, "OutsideHumidity")) { alarm->type = OutsideHumidity; } else if (!strcmp (type, "RainRate")) { alarm->type = RainRate; } else if (!strcmp (type, "StormRain")) { alarm->type = StormRain; } else if (!strcmp (type, "DayRain")) { alarm->type = DayRain; } else if (!strcmp (type, "MonthRain")) { alarm->type = MonthRain; } else if (!strcmp (type, "YearRain")) { alarm->type = YearRain; } else if (!strcmp (type, "TxBatteryStatus")) { alarm->type = TxBatteryStatus; } else if (!strcmp (type, "ConsoleBatteryVoltage")) { alarm->type = ConsoleBatteryVoltage; } else if (!strcmp (type, "DewPoint")) { alarm->type = DewPoint; } else if (!strcmp (type, "WindChill")) { alarm->type = WindChill; } else if (!strcmp (type, "HeatIndex")) { alarm->type = HeatIndex; } else if (!strcmp (type, "Radiation")) { alarm->type = Radiation; } else if (!strcmp (type, "UV")) { alarm->type = UV; } else if (!strcmp (type, "ET")) { alarm->type = ET; } else if (!strcmp (type, "ExtraTemp1")) { alarm->type = ExtraTemp1; } else if (!strcmp (type, "ExtraTemp2")) { alarm->type = ExtraTemp2; } else if (!strcmp (type, "ExtraTemp3")) { alarm->type = ExtraTemp3; } else if (!strcmp (type, "SoilTemp1")) { alarm->type = SoilTemp1; } else if (!strcmp (type, "SoilTemp2")) { alarm->type = SoilTemp2; } else if (!strcmp (type, "SoilTemp3")) { alarm->type = SoilTemp3; } else if (!strcmp (type, "SoilTemp4")) { alarm->type = SoilTemp4; } else if (!strcmp (type, "LeafTemp1")) { alarm->type = LeafTemp1; } else if (!strcmp (type, "LeafTemp2")) { alarm->type = LeafTemp2; } else if (!strcmp (type, "ExtraHumid1")) { alarm->type = ExtraHumid1; } else if (!strcmp (type, "ExtraHumid2")) { alarm->type = ExtraHumid2; } else if (!strcmp (type, "Wxt510Hail")) { alarm->type = Wxt510Hail; } else if (!strcmp (type, "Wxt510Hailrate")) { alarm->type = Wxt510Hailrate; } else if (!strcmp (type, "Wxt510HeatingTemp")) { alarm->type = Wxt510HeatingTemp; } else if (!strcmp (type, "Wxt510HeatingVoltage")) { alarm->type = Wxt510HeatingVoltage; } else if (!strcmp (type, "Wxt510SupplyVoltage")) { alarm->type = Wxt510SupplyVoltage; } else if (!strcmp (type, "Wxt510ReferenceVoltage")) { alarm->type = Wxt510ReferenceVoltage; } else { free (alarm); radMsgLog (PRI_MEDIUM, "invalid alarm type %s - skipping...", type); continue; } // do the max/min flag alarm->isMax = boolMAX; // now the bounding value alarm->bound = (float)thresh; // now the abatement seconds alarm->abateSecs = abate; // finally, the alarm script wvstrncpy (alarm->scriptToRun, exec, WVIEW_ALARM_SCRIPT_LENGTH); radListAddToEnd (&alarmsWork.alarmList, (NODE_PTR)alarm); } wvconfigExit (); return (radListGetNumberOfNodes (&alarmsWork.alarmList)); }