Exemplo n.º 1
0
// Returns:
// OK - if new record retrieved
// ERROR - if there was an interface error
// ERROR_ABORT - if there is no new record (WH1080 generates new records at 
//               best once a minute)
static int readStationData (WVIEWD_WORK *work)
{
    WH1080_IF_DATA*     ifWorkData = (WH1080_IF_DATA*)work->stationData;
    int                 currentPosition, readPosition, index, retVal;

    if ((*(work->medium.usbhidInit))(&work->medium) != OK)
    {
        return ERROR;
    }

    // Read the WH1080 fixed block:
    retVal = readFixedBlock(work, &wh1080Work.controlBlock[0]);
    if (retVal == ERROR_ABORT)
    {
        // Try again later (bad magic number):
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR_ABORT;
    }
    else if (retVal == ERROR)
    {
        // USB interface error:
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    // Get the current record position; the WH1080 reports the record it is 
    // building, thus if it changes we need the prior just finished record:
    currentPosition = (int)getUSHORT(&wh1080Work.controlBlock[WH1080_CURRENT_POS]);

    // Make sure the index is aligned on 16-byte boundary:
    if ((currentPosition % 16) != 0)
    {
        // bogus, try again later:
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR_ABORT;
    }

    // Is this the first time?
    if (wh1080Work.lastRecord == -1)
    {
        // Yes.
        wh1080Work.lastRecord = currentPosition;
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR_ABORT;
    }

    // Is there a new record?
    if (currentPosition == wh1080Work.lastRecord)
    {
        // No, wait till it is finished.
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR_ABORT;
    }

    // Read last record that is now complete:
    if (readBlock(work, wh1080Work.lastRecord, &wh1080Work.recordBlock[0]) == ERROR)
    {
        radMsgLog (PRI_HIGH, "WH1080: read data block at index %d failed!",
                   wh1080Work.lastRecord);
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    (*(work->medium.usbhidExit))(&work->medium);

    readPosition = wh1080Work.lastRecord;
    wh1080Work.lastRecord = currentPosition;

//radMsgLogData(wh1080Work.recordBlock, 32);

    // Is the record valid? Check for unpopulated record or no sensor data
    // received status bit:
    if ((wh1080Work.recordBlock[WH1080_STATUS] & 0x40) != 0)
    {
        // No!
        radMsgLog (PRI_HIGH, 
                   "WH1080: data block at index %d has bad status, ignoring the record",
                   readPosition);
        return ERROR_ABORT;
    }

    // Parse the data received:
    for (index = 0; index < WH1080_NUM_SENSORS; index ++)
    {
        if (decodeSensor(&wh1080Work.recordBlock[decodeVals[index].pos],
                         decodeVals[index].ws_type,
                         decodeVals[index].scale,
                         decodeVals[index].var)
            != OK)
        {
            // Bad sensor data, abort this cycle:
            radMsgLog (PRI_HIGH, 
                       "WH1080: data block at index %d has bad sensor value, ignoring the record",
                       readPosition);
            return ERROR_ABORT;
        }
    }

    // Convert to Imperial units:
    wh1080Work.sensorData.intemp        = wvutilsConvertCToF(wh1080Work.sensorData.intemp);
    wh1080Work.sensorData.outtemp       = wvutilsConvertCToF(wh1080Work.sensorData.outtemp);
    wh1080Work.sensorData.pressure      = wvutilsConvertHPAToINHG(wh1080Work.sensorData.pressure);
    wh1080Work.sensorData.windAvgSpeed  = wvutilsConvertMPSToMPH(wh1080Work.sensorData.windAvgSpeed);
    wh1080Work.sensorData.windGustSpeed = wvutilsConvertMPSToMPH(wh1080Work.sensorData.windGustSpeed);
    wh1080Work.sensorData.rain          = wvutilsConvertMMToIN(wh1080Work.sensorData.rain);

    return OK;
}
Exemplo n.º 2
0
int wh1080Init (WVIEWD_WORK *work)
{
    WH1080_IF_DATA*     ifWorkData = (WH1080_IF_DATA*)work->stationData;
    fd_set              rfds;
    struct timeval      tv;
    int                 ret;
    time_t              nowTime = time(NULL) - (WV_SECONDS_IN_HOUR/(60/WH1080_RAIN_RATE_PERIOD));
    ARCHIVE_PKT         recordStore;
    unsigned char       controlBlock[WH1080_BUFFER_CHUNK];

    memset (&wh1080Work, 0, sizeof(wh1080Work));

    // Create the rain accumulator (WH1080_RAIN_RATE_PERIOD minute age)
    // so we can compute rain rate:
    ifWorkData->rainRateAccumulator = sensorAccumInit(WH1080_RAIN_RATE_PERIOD);

    // Populate the accumulator with the last WH1080_RAIN_RATE_PERIOD minutes:
    while ((nowTime = dbsqliteArchiveGetNextRecord(nowTime, &recordStore)) != ERROR)
    {
        sensorAccumAddSample(ifWorkData->rainRateAccumulator,
                             recordStore.dateTime,
                             recordStore.value[DATA_INDEX_rain]);
    }

    if ((*(work->medium.usbhidInit))(&work->medium) != OK)
    {
        return ERROR;
    }

    // Set the station to log data once per minute:
    while ((!work->exiting) && (readFixedBlock(work, controlBlock) != OK))
    {
        radMsgLog (PRI_HIGH, "WH1080: Initial fixed block read failed");
        (*(work->medium.usbhidExit))(&work->medium);
        radUtilsSleep(5000);
        (*(work->medium.usbhidInit))(&work->medium);
        radMsgLog (PRI_HIGH, "WH1080: Retrying initial fixed block read");
    }

    // For some reason the WH1080 wants the IF closed between a read and a write:
    (*(work->medium.usbhidExit))(&work->medium);
    if (work->exiting)
    {
        return ERROR;
    }

    controlBlock[WH1080_SAMPLING_INTERVAL] = 1;
    (*(work->medium.usbhidInit))(&work->medium);

    if (writeFixedBlock(work, controlBlock) == ERROR)
    {
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    radUtilsSleep(2000);

    (*(work->medium.usbhidExit))(&work->medium);

    radUtilsSleep(1000);

    wh1080Work.lastRecord = -1;

    // populate the LOOP structure:
    radMsgLog (PRI_HIGH, "Waiting for the next weather record to be ready "
                         "in the console to populate initial wview sensor readings "
                         "(this could take some time);");
    radMsgLog (PRI_HIGH, "While waiting be sure you are receiving all sensors on the console;");
    radMsgLog (PRI_HIGH, "if not, you may need to relocate the sensors or the console.");
    while ((!work->exiting) && (readStationData(work) != OK))
    {
        radUtilsSleep(1000);
    }
    if (work->exiting)
    {
        return ERROR;
    }

    ifWorkData->wh1080Readings = wh1080Work.sensorData;
    storeLoopPkt (work, &work->loopPkt, &ifWorkData->wh1080Readings);

    // 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;
}
Exemplo n.º 3
0
// Returns:
// OK - if new record retrieved
// ERROR - if there was an interface error
// ERROR_ABORT - if there is no new record (WH1080 generates new records at 
//               best once a minute)
static int readStationData (WVIEWD_WORK *work)
{
    WH1080_IF_DATA*     ifWorkData = (WH1080_IF_DATA*)work->stationData;
    int                 currentPosition, index;

    if ((*(work->medium.usbhidInit))(&work->medium) != OK)
    {
        return ERROR;
    }

    // Read the WH1080 fixed block:
    if (readFixedBlock(work, &wh1080Work.controlBlock[0]) == ERROR)
    {
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    // Get the current record position; the WH1080 reports the record it is 
    // building, thus if it changes we need the prior just finished record:
    currentPosition = (int)getUSHORT(&wh1080Work.controlBlock[WH1080_CURRENT_POS]);
    currentPosition -= WH1080_BUFFER_RECORD;
    if (currentPosition < WH1080_BUFFER_START)
    {
        // wrap back around to the end of the memory block:
        currentPosition = WH1080_BUFFER_END;
    }

    // Is there a new record?
    if (currentPosition == wh1080Work.lastRecord)
    {
        // No!
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR_ABORT;
    }

    // Read current and next record on first read on even position
    if (readBlock(work, currentPosition, &wh1080Work.recordBlock[0]) == ERROR)
    {
        radMsgLog (PRI_HIGH, "WH1080: read data block at index %d failed!",
                   currentPosition);
        (*(work->medium.usbhidExit))(&work->medium);
        return ERROR;
    }

    (*(work->medium.usbhidExit))(&work->medium);

    wh1080Work.lastRecord = currentPosition;

//radMsgLogData(wh1080Work.recordBlock, 32);

    // Is the record valid? Check for unpopulated record or no sensor data
    // received status bit:
    if (((wh1080Work.recordBlock[0] != 1)) ||
        ((wh1080Work.recordBlock[WH1080_STATUS] & 0x40) != 0))
    {
        // No!
        return ERROR_ABORT;
    }

    // Parse the data received:
    for (index = 0; index < WH1080_NUM_SENSORS; index ++)
    {
        if (decodeSensor(&wh1080Work.recordBlock[decodeVals[index].pos],
                         decodeVals[index].ws_type,
                         decodeVals[index].scale,
                         decodeVals[index].var)
            != OK)
        {
            // Bad sensor data, abort this cycle:
            return ERROR_ABORT;
        }
    }

    // Convert to Imperial units:
    wh1080Work.sensorData.intemp        = wvutilsConvertCToF(wh1080Work.sensorData.intemp);
    wh1080Work.sensorData.outtemp       = wvutilsConvertCToF(wh1080Work.sensorData.outtemp);
    wh1080Work.sensorData.pressure      = wvutilsConvertHPAToINHG(wh1080Work.sensorData.pressure);
    wh1080Work.sensorData.windAvgSpeed  = wvutilsConvertMPSToMPH(wh1080Work.sensorData.windAvgSpeed);
    wh1080Work.sensorData.windGustSpeed = wvutilsConvertMPSToMPH(wh1080Work.sensorData.windGustSpeed);
    wh1080Work.sensorData.rain          = wvutilsConvertMMToIN(wh1080Work.sensorData.rain);

    return OK;
}