Example #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;
}
Example #2
0
static void drawGrid (MULTICHART_ID id)
{
    register int    i;
    int             xlabelwidth = 0, ylabelwidth = 0;
    double          units, step;
    double          minR, stepR;
    int             dataPoints, xnumhash, xhashindexlen;
    double          hashwidth, xhashwidth;
    int             numhash, x, y;
    char            text[64][32], ylabelfmt[24];
    char            textR[64][32], ylabelfmtR[24];

    //  ... calculate the maximum number of hash marks and the units per hash
    //  ... for the x-axis
    //  build labels and calculate the maximum x-label width
    for (i = 0; i < id->numpoints; i ++)
    {
        if (strlen (id->pointnames[i]) > xlabelwidth)
            xlabelwidth = strlen (id->pointnames[i]);
    }

    xhashwidth = (xlabelwidth*gdFontSmall->h)/2;
    dataPoints = id->numpoints - 1;


    if (strlen (id->DualUnit) > 0)
    {
        // ((gdFontSmall->h/2) * strlen (id->DualUnit)))/2) - 2
        id->imbx -= (gdFontMediumBold->h);
        if ((strcmp(id->DualUnit,"inches") == 0) || 
            (strcmp(id->DualUnit,"knots") == 0) || 
            (strcmp(id->DualUnit,"m/s") == 0))
            id->imbx -= 7;
    }


    // see if a suggestion was given
    if (id->xnumhashes != 0)
    {
        xnumhash = id->xnumhashes;
    }
    else
    {
        xnumhash =  (id->imbx - id->imtx)/xhashwidth;

        // try to normalize the number of hashmarks
        // try with the endpoint removed
        for (i = 1; i < dataPoints/2; i ++)
        {
            if (dataPoints % i != 0)
                continue;

            if (dataPoints/i <= xnumhash)
            {
                xnumhash = dataPoints/i;
                break;
            }
        }
    }

    xhashwidth = (double)(id->imbx - id->imtx)/(double)xnumhash;
    id->pointpixels = (double)(id->imbx - id->imtx)/(double)dataPoints;
    xhashindexlen = dataPoints/xnumhash;


    //  ... calculate the maximum number of hash marks and the units per hash
    //  ... for the y-axis
    hashwidth = (gdFontSmall->h * 3)/2;
    numhash = (id->imby - id->imty)/hashwidth;
    if (numhash > 64)
        numhash = 64;

    units = (id->max - id->min)/id->ystepSize;
    step = id->ystepSize;
    i = 0;
    while ((int)units > numhash && i < MAX_STEP_MULTIPLIER)
    {
        step = id->ystepSize * stepSizeMultipliers[i];
        units = (id->max - id->min)/step;
        i ++;
    }

    id->ystepSize = step;
    numhash = (int)units;
    if ((id->min + (id->ystepSize * numhash)) < id->max)
    {
        numhash ++;
    }

    hashwidth = (double)(id->imby - id->imty)/(double)numhash;
    id->max = id->min + (id->ystepSize * numhash);
    id->ypixelconstant = (double)(id->imby - id->imty)/(double)(id->max - id->min);
    numhash ++;
    if (numhash > 64)
        numhash = 64;

    //  build labels and calculate the maximum y-label width
    sprintf (ylabelfmt, "%%.%1.1df", id->ydecPlaces);
    for (i = 0; i < numhash; i ++)
    {
        sprintf (text[i], ylabelfmt, id->min + (i * id->ystepSize));

        // now fill the right hand array with alternate scale @Rcm
        if (strlen(id->DualUnit) > 0)
        {
            textR[i][0] = ' ';
            if (strcmp(id->DualUnit,"C") == 0)
            {
                minR = wvutilsConvertFToC (id->min);
                stepR = ((id->ystepSize) * (5.0/9.0));
                sprintf (textR[i], "%.1f", minR + (i * stepR));
            }
            else if (strcmp(id->DualUnit,"F") == 0)
            {
                minR = wvutilsConvertCToF (id->min);
                stepR = ((id->ystepSize) * (9.0/5.0));
                sprintf (textR[i], "%.1f", minR + (i * stepR));
            }
            else if (strcmp(id->DualUnit,"mm") == 0)
            {
                minR = wvutilsConvertINToMM (id->min);
                stepR = wvutilsConvertINToMM (id->ystepSize);
                if (wvutilsConvertINToMM (id->max) >= 100)
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                else
                    sprintf (textR[i], "%.1f", minR + (i * stepR));
            }
            else if (strcmp(id->DualUnit,"inches") == 0)
            {
                minR = wvutilsConvertMMToIN (id->min);
                stepR = wvutilsConvertMMToIN (id->ystepSize);
                if (wvutilsConvertMMToIN (id->max) >= 100)
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                else
                    sprintf (textR[i], "%.1f", minR + (i * stepR));
            }
            else if (strcmp(id->DualUnit,"km/h") == 0)
            {
                minR = wvutilsConvertMilesToKilometers (id->min);
                stepR = wvutilsConvertMilesToKilometers (id->ystepSize);
                sprintf (textR[i], "%.0f", minR + (i * stepR));
            }
            else if (strcmp(id->DualUnit,"mph") == 0)
            {
                minR = wvutilsConvertKilometersToMiles (id->min);
                stepR = wvutilsConvertKilometersToMiles (id->ystepSize);
                sprintf (textR[i], "%.0f", minR + (i * stepR));
            }
            else if (strcmp(id->title,"m/s") == 0)
            {
                if (id->isMetric)
                {
                    minR = wvutilsConvertMPSToKPH (id->min);
                    stepR = wvutilsConvertMPSToKPH (id->ystepSize);
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                }
                else
                {
                    minR = wvutilsConvertMPSToMPH (id->min);
                    stepR = wvutilsConvertMPSToMPH (id->ystepSize);
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                }
            }
            else if (strcmp(id->title,"knots") == 0)
            {
                if (id->isMetric)
                {
                    minR = wvutilsConvertKnotsToKPH (id->min);
                    stepR = wvutilsConvertKnotsToKPH (id->ystepSize);
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                }
                else
                {
                    minR = wvutilsConvertKnotsToMPH (id->min);
                    stepR = wvutilsConvertKnotsToMPH (id->ystepSize);
                    sprintf (textR[i], "%.0f", minR + (i * stepR));
                }
            }
            else //all else: eg '%' or watts/m^2 (hum/ rad)
            {    // same value both sides
                minR = id->min * 25.4;
                stepR = id->ystepSize * 25.4;
                sprintf (textR[i], "%s", text[i]);
            }
            if (strlen (text[i]) > ylabelwidth)
                ylabelwidth = strlen (text[i])+2;
        }
        else
        {

            if (strlen (text[i]) > ylabelwidth)
                ylabelwidth = strlen (text[i]);
        }
    }

    //  ... now we know the chart area, draw it
    gdImageFilledRectangle (id->im,
                            id->imtx - GLC_CONTENTS_OFFSET,
                            id->imty - GLC_CONTENTS_OFFSET,
                            id->imbx + GLC_CONTENTS_OFFSET,
                            id->imby + GLC_CONTENTS_OFFSET,
                            id->chartcolor);

    gdImageRectangle (id->im,
                      id->imtx,
                      id->imty,
                      id->imbx,
                      id->imby,
                      id->gridcolor);

    //  ... draw the y-axis
    gdImageSetThickness (id->im, 1);
    for (i = 0; i < numhash; i ++)
    {
        y = id->imby - (i * hashwidth);

        gdImageLine (id->im,
                     id->imtx,
                     y,
                     id->imbx,
                     y,
                     id->gridcolor);

        y -= gdFontSmall->h/2;
        gdImageString (id->im,
                       gdFontSmall,
                       (id->imtx - 5) - (strlen(text[i]) * gdFontSmall->h/2),
                       y,
                       (UCHAR *)text[i],
                       id->textcolor);

        if (strlen(id->DualUnit) > 0 )
        {
            // right side
            x = id->imbx + (GLC_CONTENTS_OFFSET - 2);

            gdImageString (id->im,
                           gdFontSmall,
                           x + gdFontSmall->h/2,
                           y,
                           (UCHAR *)textR[i],
                           id->textcolor);
        }
    }

    //  ... draw the x-axis
    gdImageSetThickness (id->im, 1);

    for (i = 0; i <= xnumhash; i ++)            // one more for right-most
    {
        int         dataPoint = i * xhashindexlen;

        x = id->imtx + (i * xhashwidth);

        gdImageLine (id->im,
                     x,
                     id->imty,
                     x,
                     id->imby,
                     id->gridcolor);

        if (strlen(id->pointnames[dataPoint]) < 2)
            x -= gdFontSmall->h/4;

        gdImageString (id->im,
                       gdFontSmall,
                       x - ((gdFontSmall->h/2) *
                            (strlen(id->pointnames[dataPoint])/2)),
                       (id->height - (3 * gdFontMediumBold->h)) + 4,
                       (UCHAR *)id->pointnames[dataPoint],
                       id->textcolor);
    }


    //  ... finally, draw date
    gdImageString (id->im,
                   gdFontSmall,
                   ((id->width - ((gdFontSmall->h/2) * strlen (id->datetime)))/2) - 2,
                   id->height - (gdFontMediumBold->h + 2),
                   (UCHAR *)id->datetime,
                   id->textcolor);
}
Example #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;
}