Пример #1
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;
}
Пример #2
0
static void daemonStoreArchiveRecord (ARCHIVE_PKT *newRecord)
{
    float           carryOverRain, carryOverET, sampleRain, tempf;
    int             deltaTime, tempInt;
    USHORT          tempRainBits;

    if (newRecord == NULL)
    {
        radMsgLog (PRI_MEDIUM, "daemonStoreArchiveRecord: record is NULL!");
        return;
    }

    deltaTime = newRecord->dateTime - wviewdWork.archiveDateTime;
    if (deltaTime == 0)
    {
        // discard it, same as previous record
        radMsgLog (PRI_MEDIUM,
                   "daemonStoreArchiveRecord: record has same timestamp as previous!");
        return;
    }
    else if (deltaTime < 0)
    {
        // chunk it, it is just wrong
        radMsgLog (PRI_MEDIUM,
                   "StoreArchiveRecord: record has earlier timestamp than previous (DST change?)");
        return;
    }

    wviewdWork.archiveDateTime = newRecord->dateTime;

    wvutilsLogEvent (PRI_STATUS, "storing record for %4.4d-%2.2d-%2.2d %2.2d:%2.2d",
                     wvutilsGetYear(newRecord->dateTime),
                     wvutilsGetMonth(newRecord->dateTime),
                     wvutilsGetDay(newRecord->dateTime),
                     wvutilsGetHour(newRecord->dateTime),
                     wvutilsGetMin(newRecord->dateTime));

    if (dbsqliteArchiveStoreRecord(newRecord) == ERROR)
    {
        radMsgLog (PRI_MEDIUM, "daemonStoreArchiveRecord: dbsqliteArchiveStoreRecord failed!!!");
        emailAlertSend(ALERT_TYPE_FILE_IO);
        return;
    }

    // if we are running normally (out of init), do normal activities:
    if (wviewdWork.runningFlag)
    {
        // Check to see if a DST change has occured:
        // Note: wvutilsDetectDSTChange can only be called once per process per
        //       DST event.
        if (wvutilsDetectDSTChange() != WVUTILS_DST_NO_CHANGE)
        {
            radMsgLog (PRI_STATUS, 
                       "DST change: scheduling station time update (if supported)");

            // Update the time zone info:
            tzset();

            // Adjust station time:
            stationSyncTime(&wviewdWork);
        }

        // save trace accumulator amounts:
        if (newRecord->value[DATA_INDEX_rain] > ARCHIVE_VALUE_NULL)
        {
            sampleRain = (float)newRecord->value[DATA_INDEX_rain];
            carryOverRain = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_INTERVAL][SENSOR_RAIN]);
            carryOverRain -= sampleRain;
            if (carryOverRain < 0)
            {
                carryOverRain = 0;
            }
        }

        if (newRecord->value[DATA_INDEX_ET] > ARCHIVE_VALUE_NULL)
        {
            carryOverET = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_INTERVAL][SENSOR_ET]);
            carryOverET -= (float)newRecord->value[DATA_INDEX_ET];
            if (carryOverET < 0)
            {
                carryOverET = 0;
            }
        }

        // compute HILOW data:
        computedDataUpdate (&wviewdWork, newRecord);

        // clear for the next archive period (saving trace amounts):
        computedDataClearInterval (&wviewdWork, carryOverRain, carryOverET);

        // compute storm rain:
        if (newRecord->value[DATA_INDEX_rain] > ARCHIVE_VALUE_NULL &&
            newRecord->value[DATA_INDEX_rainRate] > ARCHIVE_VALUE_NULL)
        {
            stormRainUpdate ((float)newRecord->value[DATA_INDEX_rainRate],
                             (float)newRecord->value[DATA_INDEX_rain]);
        }

        // sync to sensors:
        wviewdWork.loopPkt.stormRain  = stormRainGet();
        wviewdWork.loopPkt.stormStart = stormRainGetStartTimeT();
        wviewdWork.loopPkt.dayRain    = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_DAY][SENSOR_RAIN]);
        wviewdWork.loopPkt.monthRain  = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_MONTH][SENSOR_RAIN]);
        wviewdWork.loopPkt.yearRain   = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_YEAR][SENSOR_RAIN]);
        wviewdWork.loopPkt.dayET      = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_DAY][SENSOR_ET]);
        wviewdWork.loopPkt.monthET    = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_MONTH][SENSOR_ET]);
        wviewdWork.loopPkt.yearET     = sensorGetCumulative(&wviewdWork.sensors.sensor[STF_YEAR][SENSOR_ET]);

        // send archive notification:
        stationSendArchiveNotifications (&wviewdWork, sampleRain);
    }

    statusIncrementStat(WVIEW_STATS_ARCHIVE_PKTS_RX);
    return;
}
Пример #3
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;
}