static int waitForWviewDaemon (void) { WVIEW_MSG_REQUEST msg; char srcQName[QUEUE_NAME_LENGTH+1]; UINT msgType; UINT length; void *recvBfr; int retVal, done = FALSE; // enable message reception from the radlib router for the archive path radMsgRouterMessageRegister (WVIEW_MSG_TYPE_STATION_INFO); msg.requestType = WVIEW_RQST_TYPE_STATION_INFO; if (radMsgRouterMessageSend (WVIEW_MSG_TYPE_REQUEST, &msg, sizeof(msg)) == ERROR) { statusUpdateMessage("waitForWviewDaemon: radMsgRouterMessageSend failed!"); radMsgLog (PRI_HIGH, "waitForWviewDaemon: radMsgRouterMessageSend failed!"); radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO); return ERROR; } statusUpdate(STATUS_WAITING_FOR_WVIEW); // now wait for the response here while (!done) { radUtilsSleep (50); if ((retVal = radQueueRecv (radProcessQueueGetID (), srcQName, &msgType, &recvBfr, &length)) == FALSE) { continue; } else if (retVal == ERROR) { statusUpdateMessage("waitForWviewDaemon: queue is closed!"); radMsgLog (PRI_STATUS, "waitForWviewDaemon: queue is closed!"); radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO); return ERROR; } // is this what we want? if (msgType == WVIEW_MSG_TYPE_STATION_INFO) { // yes! done = TRUE; cwopWork.reportInterval = ((WVIEW_MSG_STATION_INFO*)recvBfr)->archiveInterval; if (cwopWork.reportInterval < 10) { cwopWork.reportInterval = 10; } } else if (msgType == WVIEW_MSG_TYPE_SHUTDOWN) { statusUpdateMessage("waitForWviewDaemon: received shutdown from wviewd"); radMsgLog (PRI_HIGH, "waitForWviewDaemon: received shutdown from wviewd"); radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO); return ERROR; } // release the received buffer radBufferRls (recvBfr); } // disable message reception from the radlib router for the archive path radMsgRouterMessageDeregister (WVIEW_MSG_TYPE_STATION_INFO); return OK; }
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; }