//---------------------------------------------------------------------------------------------------
//
// processSensor
//
// Depending on the device type call a subroutine to process the payload data and put
// the result string into the outBuffer.
//
// Parameters:
//    int             deviceType        IN   Device type (SPCAD, SPEED, CADENCE, HRM, AERO, POWER).
//    const amString &deviceID          IN   Device ID (number).
//    const amString &timeStampBuffer   IN   Time stamp.
//    BYTE            payLoad[]         IN   Array of bytes with the data to be converted.
//
// Return amDeviceType SPEED_SENSOR, CADENCE_SENSOR, POWER_METER, AERO_SENSOR, or HEART_RATE_METER
//             if successful.
//        amDeviceType OTHER_DEVICE otherwise (device type ot recognized)
//
//---------------------------------------------------------------------------------------------------
amDeviceType antSpeedOnlyProcessing::processSensor
(
    int             deviceType,
    const amString &deviceIDNo,
    const amString &timeStampBuffer,
    BYTE            payLoad[]
)
{
    amDeviceType result = OTHER_DEVICE;

    if ( deviceType == C_SPEED_TYPE )
    {
        result = processBikeSpeedSensor( deviceIDNo, timeStampBuffer, payLoad );
    }

    if ( deviceType == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            int deviceIDNoAsInt = deviceIDNo.toInt();
            createUnknownDeviceTypeString( deviceType, deviceIDNoAsInt, timeStampBuffer, payLoad );
        }
    }

    return result;
}
//---------------------------------------------------------------------------------------------------
//
// processSensor
//
// Depending on the device type call a subroutine to process the payload data and put
// the result string into the outBuffer.
//
// Parameters:
//    int             deviceType        IN   Device type
//    const amString &deviceID          IN   Device ID (number).
//    const amString &timeStampBuffer   IN   Time stamp.
//    BYTE            payLoad[]         IN   Array of bytes with the data to be converted.
//
// Return amDeviceType SPEED_SENSOR, CADENCE_SENSOR, POWER_METER, AERO_SENSOR, or HEART_RATE_METER
//             if successful.
//        amDeviceType OTHER_DEVICE otherwise (device type ot recognized)
//
//---------------------------------------------------------------------------------------------------
amDeviceType antEnvironmentProcessing::processSensor
(
    int             deviceType,
    const amString &deviceIDNo,
    const amString &timeStampBuffer,
    BYTE            payLoad[]
)
{
    amDeviceType result = OTHER_DEVICE;

    if ( deviceType == C_ENV_TYPE )
    {
        result = processEnvironmentSensor( deviceIDNo, timeStampBuffer, payLoad );
    }
    else if ( outputUnknown )
    {
        int deviceIDNoAsInt = deviceIDNo.toInt();
        createUnknownDeviceTypeString( deviceType, deviceIDNoAsInt, timeStampBuffer, payLoad );
    }
    else
    {
        resetOutBuffer();
    }

    return result;
}
amDeviceType antSpeedOnlyProcessing::processSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType result = OTHER_DEVICE;
    if ( !inputBuffer.empty() )
    {
        if ( isSpeedOnlySensor( inputBuffer ) )
        {
            result = processBikeSpeedSensorSemiCooked( inputBuffer );
        }
        else
        {
            resetOutBuffer();
            if ( outputUnknown )
            {
                setOutBuffer( inputBuffer );
            }
        }
    }
    return result;
}
示例#4
0
amDeviceType antHRMProcessing::processSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType result = OTHER_DEVICE;
    if ( !inputBuffer.empty() )
    {
        if ( isHeartRateSensor( inputBuffer ) )
        {
            result = processHRMSensorSemiCooked( inputBuffer );
        }
        else
        {
            resetOutBuffer();
            if ( outputUnknown )
            {
                setOutBuffer( inputBuffer );
            }
        }
    }
    return result;
}
amDeviceType antEnvironmentProcessing::processSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType result = OTHER_DEVICE;
    if ( !inputBuffer.empty() )
    {
        if ( isEnvironmentSensor( inputBuffer ) )
        {
            result = processEnvironmentSensorSemiCooked( inputBuffer );
        }
        else
        {
            resetOutBuffer();
            if ( getOutputUnknown() )
            {
                setOutBuffer( inputBuffer );
            }
        }
    }

    return result;
}
示例#6
0
Osc::Osc( )
{
	resetOutBuffer( );
	preamble = NULL;
	packetInterface = NULL;
}
// ---------------------------------------------------------------------------------------------------
//
// processBikeSpeedSensorSemiCooked
//
// Convert the raw ant data into semi-cooked text data and put the result string into the outBuffer.
// The output string has the form
//     "SPB7_<device_ID> <data_page> <bike_speed_event_time> <wheel_revolution_count> ..."
// Depending on the value of <data_page> & 127:
//    1: "SPB7_<device_ID> <data_page> <bike_speed_event_time> <wheel_revolution_count> <operating_time>"
//    2: "SPB7_<device_ID> <data_page> <bike_speed_event_time> <wheel_revolution_count> <manufacturer_ID> <serial_number>"
//    3: "SPB7_<device_ID> <data_page> <bike_speed_event_time> <wheel_revolution_count> <hardware_version> <software_version> <model_number>"
//
// ---------------------------------------------------------------------------------------------------
amDeviceType antSpeedOnlyProcessing::processBikeSpeedSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType  result = OTHER_DEVICE;
    amString      curVersion                = getVersion();
    amString      semiCookedString;
    amString      sensorID;
    amString      timeStampBuffer;
    amSplitString words;
    unsigned int  nbWords                   = 0;
    unsigned int  counter                   = 0;
    unsigned int  startCounter              = 0;
    unsigned int  dataPage                  = 0;
    unsigned int  deltaBikeSpeedEventTime   = 0;
    unsigned int  deltaWheelRevolutionCount = 0;
    unsigned int  additionalData1           = 0;
    unsigned int  additionalData2           = 0;
    unsigned int  additionalData3           = 0;
    bool          commonPage                = false;
    bool          outputPageNo              = true;

    if ( isSemiCookedFormat137( inputBuffer ) )
    {
        nbWords = splitFormat137_SPB7( inputBuffer, words );
    }
    else
    {
        nbWords = words.split( inputBuffer );
    }

    if ( nbWords > 5 )
    {
        sensorID         = words[ counter++ ];                            // 0
        timeStampBuffer  = words[ counter++ ];                            // 1
        semiCookedString = words[ counter++ ];                            // 2
        replaceObsoleteHeader( sensorID );
        if ( diagnostics )
        {
            appendDiagnosticsLine( "SensorID",   sensorID );
            appendDiagnosticsLine( "Timestamp",  timeStampBuffer );
            appendDiagnosticsLine( "SemiCooked", semiCookedString );
        }
        if ( isRegisteredDevice( sensorID ) && ( semiCookedString == C_SEMI_COOKED_SYMBOL_AS_STRING ) && isSpeedOnlySensor( sensorID ) )
        {
            startCounter = counter;
            dataPage     = words[ counter++ ].toUInt();                   // 3
            if ( words[ counter ] == C_UNSUPPORTED_DATA_PAGE )
            {
                result = UNKNOWN_DEVICE;
            }
            else
            {
                deltaBikeSpeedEventTime   = words[ counter++ ].toUInt();  // 4
                deltaWheelRevolutionCount = words[ counter++ ].toUInt();  // 5
                if ( diagnostics )
                {
                    appendDiagnosticsLine( "Data Page", dataPage );
                    appendDiagnosticsLine( "Delta Bike Speed Event Time", deltaBikeSpeedEventTime );
                    appendDiagnosticsLine( "Delta Cumulative Wheel Count", deltaWheelRevolutionCount );
                }

                int dataPageMod128 = dataPage & 0x0F;
                switch ( dataPageMod128 )
                {
                    case  0: // - - Page 0: No Additional Data - - - - - - - - - - - - - - -
                             result = SPEED_SENSOR;
                             break;

                    case  1: // - - Page 1: Operating Time - - - - - - - - - - - - - - - - -
                             if ( nbWords > 6 )
                             {
                                 result          = SPEED_SENSOR;
                                 additionalData1 = words[ counter++ ].toUInt();   // 6 -deltaOperatingTime
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Delta Cumulative Operating Time", additionalData1 );
                                 }
                             }
                             break;

                    case  2: // - - Page 2: Manufacturer Information - - - - - - - - - - - -
                             if ( nbWords > 7 )
                             {
                                 result          = SPEED_SENSOR;
                                 additionalData1 = words[ counter++ ].toUInt();   // 7 - manufacturerID
                                 additionalData2 = words[ counter++ ].toUInt();   // 8 - serialNumber
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Manufacturer ID", additionalData1 );
                                     appendDiagnosticsLine( "Serial Number", additionalData2 );
                                 }
                             }
                             break;

                    case  3: // - - Page 3: Product Information  - - - - - - - - - - - - - -
                             if ( nbWords > 8 )
                             {
                                 result          = SPEED_SENSOR;
                                 additionalData1 = words[ counter++ ].toUInt();   //  9 - hwVersion
                                 additionalData2 = words[ counter++ ].toUInt();   // 10 - swVersion
                                 additionalData3 = words[ counter++ ].toUInt();   // 11 - modelNumber
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Model Number", additionalData1 );
                                     appendDiagnosticsLine( "Software Version", additionalData2 );
                                     appendDiagnosticsLine( "Hardware Version", additionalData3 );
                                 }
                             }
                             break;

                    default: counter    = startCounter;
                             result     = SPEED_SENSOR;
                             commonPage = true;
                             break;
                }
            }
        }

        if ( result == SPEED_SENSOR )
        {
            if ( nbWords > counter )
            {
                curVersion = words.back();
                if ( diagnostics )
                {
                    appendDiagnosticsLine( "Version", curVersion );
                }
            }
            createOutputHeader( sensorID, timeStampBuffer );
            if ( commonPage )
            {
                commonPage = processCommonPagesSemiCooked( words, startCounter, outputPageNo );
                if ( !commonPage )
                {
                    result = OTHER_DEVICE;
                }
            }
            else
            {
                unsigned int nbMagnets          = ( unsigned int) round( getNbMagnets( sensorID ) );
                unsigned int zeroTime           = getZeroTimeCount( sensorID );
                double       wheelCircumference = getWheelCircumference( sensorID );
                double       speed              = getSpeed( sensorID );
                createSPB7ResultString
                (
                    speed,
                    dataPage,
                    deltaBikeSpeedEventTime,
                    deltaWheelRevolutionCount,
                    additionalData1,
                    additionalData2,
                    additionalData3,
                    wheelCircumference,
                    nbMagnets,
                    zeroTime
                );
                setZeroTimeCount( sensorID, zeroTime );
                setSpeed( sensorID, speed );
            }
            appendOutputFooter( curVersion );
        }
    }

    if ( result == UNKNOWN_DEVICE )
    {
        result = processUnsupportedDataPage( words );
    }

    if ( result == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            setOutBuffer( inputBuffer );
        }
    }

    return result;
}
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//
// SPB7: Speed only Sensor
//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
amDeviceType antSpeedOnlyProcessing::processBikeSpeedSensor
(
    const amString &deviceIDNo,
    const amString &timeStampBuffer,
    BYTE            payLoad[]
)
{
    char         auxBuffer[ C_MEDIUM_BUFFER_SIZE ] = { 0 };
    unsigned int dataPage                          = 0;
    unsigned int bikeSpeedEventTime                = 0;
    unsigned int deltaBikeSpeedEventTime           = 0;
    unsigned int wheelRevolutionCount              = 0;
    unsigned int deltaWheelRevolutionCount         = 0;
    unsigned int additionalData1                   = 0;
    unsigned int additionalData2                   = 0;
    unsigned int additionalData3                   = 0;
    unsigned int rollOver                          = 0;
    bool         rollOverHappened                  = false;
    bool         commonPage                        = false;
    bool         outputPageNo                      = true;
    amDeviceType result                            = OTHER_DEVICE;
    amString     sensorID                          = amString( C_SPEED_DEVICE_HEAD ) + deviceIDNo;

    if ( isRegisteredDevice( sensorID ) )
    {
        if ( ( eventTimeTable.count    ( sensorID ) == 0 ) ||
             ( eventCountTable.count   ( sensorID ) == 0 ) ||
             ( operatingTimeTable.count( sensorID ) == 0 ) )
        {
            eventTimeTable.insert    ( std::pair<amString, unsigned int>( sensorID, 0 ) );
            eventCountTable.insert   ( std::pair<amString, unsigned int>( sensorID, 0 ) );
            operatingTimeTable.insert( std::pair<amString, unsigned int>( sensorID, 0 ) );
            setSpeed( sensorID, 0 );
        }

        dataPage = byte2UInt( payLoad[ 0 ] );
        if ( diagnostics )
        {
            appendDiagnosticsLine( "Data Page", payLoad[ 0 ], dataPage );
        }

        bikeSpeedEventTime      = byte2UInt( payLoad[ 5 ], payLoad[ 4 ] );
        rollOver                = 65536;  // 256^2
        deltaBikeSpeedEventTime = getDeltaInt( rollOverHappened, sensorID, rollOver, eventTimeTable, bikeSpeedEventTime );
        if ( diagnostics )
        {
            appendDiagnosticsLine( "Bike Speed Event Time", payLoad[ 5 ], payLoad[ 4 ], bikeSpeedEventTime );
            *auxBuffer = 0;
            if ( rollOverHappened )
            {
                sprintf( auxBuffer, " (Rollover [%d] occurred)", rollOver );
            }
            appendDiagnosticsLine( "Delta Bike Speed Event Time", deltaBikeSpeedEventTime, auxBuffer );
        }

        wheelRevolutionCount      = byte2UInt( payLoad[ 7 ], payLoad[ 6 ] );
        rollOver                  = 65536;  // 256^2
        deltaWheelRevolutionCount = getDeltaInt( rollOverHappened, sensorID, rollOver, eventCountTable, wheelRevolutionCount );
        if ( diagnostics )
        {
            appendDiagnosticsLine( "Cumulative Wheel Revolution Count", payLoad[ 7 ], payLoad[ 6 ], wheelRevolutionCount );
            *auxBuffer = 0;
            if ( rollOverHappened )
            {
                sprintf( auxBuffer, " (Rollover [%d] occurred)", rollOver );
            }
            appendDiagnosticsLine( "Delta Cumulative Wheel Revolution Count", deltaWheelRevolutionCount, auxBuffer );
        }

        switch ( dataPage & 0x0F )
        {
            case  0: // - - Page 0: No Additional Data - - - - - - - - - - - - - - -
                     result = SPEED_SENSOR;
                     break;

            case  1: // - - Page 1: Operating Time - - - - - - - - - - - - - - - - -
                     result          = SPEED_SENSOR;
                     additionalData2 = byte2UInt( payLoad[ 3 ], payLoad[ 2 ], payLoad[ 1 ] ); // Operating Time
                     rollOver        = 16777216;  // 256^3
                     additionalData1 = getDeltaInt( rollOverHappened, sensorID, rollOver, operatingTimeTable, additionalData2 );
                                   // deltaOperatingTime
                     if ( diagnostics )
                     {
                         double cumOperatingTimeH = ( double ) additionalData2 / 3600.0;
                         sprintf( auxBuffer, " (%2.2lfh)", cumOperatingTimeH );
                         appendDiagnosticsLine( "Cumulative Operating Time", payLoad[ 3 ], payLoad[ 2 ], payLoad[ 1 ], additionalData2, auxBuffer );
                         *auxBuffer = 0;
                         if ( rollOverHappened )
                         {
                             sprintf( auxBuffer, " (Rollover [%d] occurred)", rollOver );
                         }
                         appendDiagnosticsLine( "Delta Cumulative Operating Time", additionalData1, auxBuffer );
                     }
                     break;

            case  2: // - - Page 2: Manufacturer Information - - - - - - - - - - - -
                     result          = SPEED_SENSOR;
                     additionalData1 = byte2UInt( payLoad[ 1 ] );                // Manufacturer ID
                     additionalData2 = byte2UInt( payLoad[ 3 ], payLoad[ 2 ] );  // Serial Number
                     if ( diagnostics )
                     {
                         appendDiagnosticsLine( "Manufacturer ID", payLoad[ 1 ], additionalData1 );
                         appendDiagnosticsLine( "Serial Number", payLoad[ 3 ], payLoad[ 2 ], additionalData2 );
                     }
                     break;

            case  3: // - - Page 3: Product Information  - - - - - - - - - - - - - -
                     result          = SPEED_SENSOR;
                     additionalData1 = byte2UInt( payLoad[ 1 ] );   // H/W Version
                     additionalData2 = byte2UInt( payLoad[ 2 ] );   // S/W Version
                     additionalData3 = byte2UInt( payLoad[ 3 ] );   // Model Number
                     if ( diagnostics )
                     {
                         appendDiagnosticsLine( "Hardware Version", payLoad[ 1 ], additionalData1 );
                         appendDiagnosticsLine( "Software Version", payLoad[ 2 ], additionalData2 );
                         appendDiagnosticsLine( "Model Number", payLoad[ 3 ], additionalData3 );
                     }
                     break;

            default: commonPage = true;
                     result = SPEED_SENSOR;
                     break;
        }
    }

    if ( result == SPEED_SENSOR )
    {
        createOutputHeader( sensorID, timeStampBuffer );
        if ( commonPage )
        {
            commonPage = processCommonPages( sensorID, payLoad, outputPageNo );
            if ( !commonPage )
            {
                result = OTHER_DEVICE;
            }
        }
        else
        {
            unsigned int nbMagnets          = ( unsigned int) round( getNbMagnets( sensorID ) );
            unsigned int zeroTime           = getZeroTimeCount( sensorID );
            double       wheelCircumference = getWheelCircumference( sensorID );
            double       speed              = getSpeed( sensorID );
            createSPB7ResultString
            (
                speed,
                dataPage,
                deltaBikeSpeedEventTime,
                deltaWheelRevolutionCount,
                additionalData1,
                additionalData2,
                additionalData3,
                wheelCircumference,
                nbMagnets,
                zeroTime
            );
            setZeroTimeCount( sensorID, zeroTime );
            setSpeed( sensorID, speed );
        }
        appendOutputFooter( getVersion() );
    }

    if ( result == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            int deviceIDNoAsInt = deviceIDNo.toInt();
            createUnknownDeviceTypeString( C_SPEED_TYPE, deviceIDNoAsInt, timeStampBuffer, payLoad );
        }
    }

    return result;
}
示例#9
0
// ---------------------------------------------------------------------------------------------------
//
// processHRMSensorSemiCooked
//
// Convert the raw ant data into semi-cooked text data and put the result string into the outBuffer.
// The output string has the form
// Depending on the value of <data_page> & 127:
//
// ---------------------------------------------------------------------------------------------------
amDeviceType antHRMProcessing::processHRMSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType result = OTHER_DEVICE;
    amSplitString words;
    unsigned int  deltaHeartBeatEventTime = 0;
    unsigned int  deltaHeartBeatCount     = 0;
    unsigned int  heartRate               = 0;
    unsigned int  dataPage                = 0;
    unsigned int  counter                 = 0;
    unsigned int  startCounter            = 0;
    unsigned int  additionalData1         = 0;
    unsigned int  additionalData2         = 0;
    unsigned int  additionalData3         = 0;
    unsigned int  totalHeartBeatCount     = 0;
    unsigned int  nbWords                 = words.split( inputBuffer );
    double        totalHeartBeatEventTime = 0;
    double        additionalDoubleData1   = 0;
    amString      timeStampBuffer;
    amString      curVersion              = getVersion();
    amString      sensorID;
    amString      timeStampString;
    amString      semiCookedString;
    bool          commonPage              = false;
    bool          outputPageNo            = true;

    if ( nbWords > 6 )
    {
        sensorID         = words[ counter++ ];                        // 0
        timeStampBuffer  = words[ counter++ ];                        // 1
        semiCookedString = words[ counter++ ];                        // 2
        if ( diagnostics )
        {
            appendDiagnosticsLine( "SensorID",   sensorID );
            appendDiagnosticsLine( "Timestamp",  timeStampBuffer );
            appendDiagnosticsLine( "SemiCooked", semiCookedString );
        }
        if ( isRegisteredDevice( sensorID ) && ( semiCookedString == C_SEMI_COOKED_SYMBOL_AS_STRING ) && isHeartRateSensor( sensorID ) )
        {
            startCounter            = counter;
            heartRate               = words[ counter++ ].toUInt();    // 3
            deltaHeartBeatEventTime = words[ counter++ ].toUInt();    // 4
            deltaHeartBeatCount     = words[ counter++ ].toUInt();    // 5
            dataPage                = words[ counter++ ].toUInt();    // 6
            if ( words[ counter ] == C_UNSUPPORTED_DATA_PAGE )
            {
                result = UNKNOWN_DEVICE;
            }
            else
            {
                totalHeartBeatEventTime     = totalTimeTable[ sensorID ] + ( ( double ) deltaHeartBeatEventTime ) / 1024.0;
                totalTimeTable[ sensorID ]  = totalHeartBeatEventTime;
                totalHeartBeatCount         = totalCountTable[ sensorID ] + deltaHeartBeatCount;
                totalCountTable[ sensorID ] = totalHeartBeatCount;
                if ( diagnostics )
                {
                    appendDiagnosticsLine( "Data Page", dataPage );
                    appendDiagnosticsLine( "Heart Rate", heartRate );
                    appendDiagnosticsLine( "Delta Heart Beat Event Time", deltaHeartBeatEventTime );
                    appendDiagnosticsLine( "Delta Heart Beat Count", deltaHeartBeatCount );
                }

                int dataPageMod128 = dataPage & 0x0F;
                switch ( dataPageMod128 )
                {
                    case  0: // - - Page 0: No Additional Data - - - - - - - - - - - - - - -
                             result = HEART_RATE_METER;
                             break;

                    case  1: // - - Page 1: Operating Time - - - - - - - - - - - - - - - - -
                             if ( nbWords > 7 )
                             {
                                 result          = HEART_RATE_METER;
                                 additionalData1 = words[ counter++ ].toUInt();   // deltaOperatingTime
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Delta Cumulative Operating Time", additionalData1 );
                                 }
                             }
                             break;

                    case  2: // - - Page 2: Manufacturer Information - - - - - - - - - - - -
                             if ( nbWords > 8 )
                             {
                                 result          = HEART_RATE_METER;
                                 additionalData1 = words[ counter++ ].toUInt();   // manufacturerID
                                 additionalData2 = words[ counter++ ].toUInt();   // serialNumber
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Manufacturer ID", additionalData1 );
                                     appendDiagnosticsLine( "Serial Number", additionalData2 );
                                 }
                             }
                             break;

                    case  3: // - - Page 3: Product Information  - - - - - - - - - - - - - -
                             if ( nbWords > 9 )
                             {
                                 result          = HEART_RATE_METER;
                                 additionalData1 = words[ counter++ ].toUInt();   // hwVersion
                                 additionalData2 = words[ counter++ ].toUInt();   // swVersion
                                 additionalData3 = words[ counter++ ].toUInt();   // modelNumber
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Model Number", additionalData1 );
                                     appendDiagnosticsLine( "Software Version", additionalData2 );
                                     appendDiagnosticsLine( "Hardware Version", additionalData3 );
                                 }
                             }
                             break;

                    case  4: // - - Page 4: Previous Heartbeat Time - - - - - - - - - - - - -
                             if ( nbWords > 8 )
                             {
                                 result                         = HEART_RATE_METER;
                                 additionalData1                = words[ counter++ ].toUInt(); // deltaPrevHeartBeatEventTime;
                                 additionalData2                = words[ counter++ ].toUInt(); // manufacturerSpecificData;
                                 additionalDoubleData1          = heartBeatTimeTable[ sensorID ] + ( ( double ) additionalData1 ) / 1024.0;
                                 heartBeatTimeTable[ sensorID ] = additionalDoubleData1;
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Manufacturer Specific Info", additionalData1 );
                                     appendDiagnosticsLine( "Delta Previous Heart Beat Event Time", additionalData2 );
                                 }
                             }
                             break;

                   default: counter    = startCounter;
                            commonPage = true;
                            result     = HEART_RATE_METER;
                            break;
                }
            }
        }
    }

    if ( result == HEART_RATE_METER )
    {
        if ( nbWords > counter )
        {
            curVersion = words.back();
            if ( diagnostics )
            {
                appendDiagnosticsLine( "Version", curVersion );
            }
        }
        createOutputHeader( sensorID, timeStampBuffer );
        if ( commonPage )
        {
            commonPage = processCommonPagesSemiCooked( words, startCounter, outputPageNo );
            if ( !commonPage )
            {
                result = OTHER_DEVICE;
            }
        }
        else
        {
            createHRMResultString
            (
                dataPage,
                heartRate,
                deltaHeartBeatEventTime,
                deltaHeartBeatCount,
                totalHeartBeatEventTime,
                totalHeartBeatCount,
                additionalData1,
                additionalData2,
                additionalData3,
                additionalDoubleData1
            );
        }
        appendOutputFooter( curVersion );
    }
    else if ( result == UNKNOWN_DEVICE )
    {
        result = processUnsupportedDataPage( words );
    }

    if ( result == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            setOutBuffer( inputBuffer );
        }
    }

    return result;
}
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//
// ENVRIONMENT
//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------------//
amDeviceType antEnvironmentProcessing::processEnvironmentSensor
(
    const amString &deviceIDNo,
    const amString &timeStampBuffer,
    BYTE            payLoad[]
)
{
    char         auxBuffer[ C_MEDIUM_BUFFER_SIZE ] = { 0 };
    unsigned int dataPage                          = 0;
    unsigned int auxInt0                           = 0;
    unsigned int auxInt1                           = 0;
    unsigned int auxInt2                           = 0;
    unsigned int additionalData1                   = 0;
    unsigned int additionalData2                   = 0;
    unsigned int additionalData3                   = 0;
    unsigned int additionalData4                   = 0;
    amDeviceType result                            = OTHER_DEVICE;
    amString     sensorID                          = amString( C_ENV_DEVICE_HEAD ) + deviceIDNo;
    bool         commonPage                        = false;
    bool         outputPageNo                      = true;

    if ( isRegisteredDevice( sensorID ) )
    {
        dataPage = byte2UInt( payLoad[ 0 ] );
        if ( diagnostics )
        {
            appendDiagnosticsLine( "Data Page", payLoad[ 0 ], dataPage );
        }

        switch ( dataPage & 0x0F )
        {
            case  0: // - - Page 0: No Additional Data - - - - - - - - - - - - - - -
                     //     Bytes 1, 2, and 3: 0xFF.
                     result          = ENVIRONMENT_SENSOR;
                     auxInt0         = byte2UInt( payLoad[ 3 ] );                                              // Transmission Info
                     additionalData1 = ( auxInt0 << 4 ) & 3;                                             // Local Time
                     additionalData2 = ( auxInt0 << 2 ) & 3;                                             // UTC Time
                     additionalData3 = auxInt0 & 3;                                                      // Transmission Rate
                     additionalData4 = byte2UInt( payLoad[ 7 ], payLoad[ 6 ], payLoad[ 5 ], payLoad[ 4 ] );    // Supported Pages
                     if ( diagnostics )
                     {
                         appendDiagnosticsLine( "Transmission Info", payLoad[ 3 ], auxInt0 );
                         appendDiagnosticsLine( "Local Time",        additionalData1 );
                         appendDiagnosticsLine( "UTC Time",          additionalData2 );
                         appendDiagnosticsLine( "Transmission Rate", additionalData3 );
                         appendDiagnosticsLine( "Supported Pages", payLoad[ 7 ], payLoad[ 6 ], payLoad[ 5 ], payLoad[ 4 ], additionalData4 );
                     }
                     break;
            case  1: // - - Page 1: Temperature - - - - - - - - - - - - - - - - -
                     //     Byte 3 and Bits 4-7 of Byte 4: Low  Temp * 10 (Byte 3 LSB)
                     //     Bits 0-3 of Byte 4 and Byte 5: High Temp * 10 (Byte 5 MSB)
                     //     Bytes 6 & 7                  : Current Temp * 100 (byte 6 LSB, byte 7 MSB)
                     result          = ENVIRONMENT_SENSOR;
                     additionalData4 = byte2UInt( payLoad[ 2 ] );                                              // Event Count
                     auxInt0         = byte2UInt( payLoad[ 4 ] );
                     auxInt1         = auxInt0 >> 4;
                     auxInt2         = auxInt0 & 0x0F;
                     additionalData2 = ( auxInt1 * 256 ) + byte2UInt( payLoad[ 3 ] );                          // Low Temperature 24h
                     additionalData3 = ( byte2UInt( payLoad[ 5 ] ) << 4 ) + auxInt2;                           // High Temperature 24h
                     additionalData1 = byte2UInt( payLoad[ 7 ], payLoad[ 6 ] );                               // Current Temperature
                     if ( diagnostics )
                     {
                         appendDiagnosticsLine( "Current Temperature * 100", payLoad[ 7 ], payLoad[ 6 ], additionalData1 );
                         strcpy( auxBuffer, " (Second Byte: Upper 4 Bits)" );
                         appendDiagnosticsLine( "Low Temperature 24h * 10", payLoad[ 3 ], payLoad[ 4 ], additionalData2, auxBuffer );
                         strcpy( auxBuffer, " (First Byte: Lower 4 Bits)" );
                         appendDiagnosticsLine( "High Temperature 24h * 10", payLoad[ 4 ], payLoad[ 5 ], additionalData3, auxBuffer );
                         appendDiagnosticsLine( "Event Count", payLoad[ 2 ], additionalData4 );
                     }
                     break;

            default: commonPage = true;
                     result     = ENVIRONMENT_SENSOR;
                     break;
        }
    }

    if ( result == ENVIRONMENT_SENSOR )
    {
        createOutputHeader( sensorID, timeStampBuffer );
        if ( commonPage )
        {
            commonPage = processCommonPages( sensorID, payLoad, outputPageNo );
            if ( !commonPage )
            {
                result = OTHER_DEVICE;
            }
        }
        else
        {
            createENVResultString( dataPage, additionalData1, additionalData2, additionalData3, additionalData4 );
        }
        appendOutputFooter( getVersion() );
    }

    if ( result == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            int deviceIDNoAsInt = deviceIDNo.toInt();
            createUnknownDeviceTypeString( C_ENV_TYPE, deviceIDNoAsInt, timeStampBuffer, payLoad );
        }
    }

    return result;
}
// ---------------------------------------------------------------------------------------------------
//
// processEnvironmentSensorSemiCooked
//
// Convert the raw ant data into semi-cooked text data and put the result string into the outBuffer.
// The output string has the form
// Depending on the value of <data_page> & 127:
//
// ---------------------------------------------------------------------------------------------------
amDeviceType antEnvironmentProcessing::processEnvironmentSensorSemiCooked
(
    const amString &inputBuffer
)
{
    amDeviceType result = OTHER_DEVICE;
    unsigned int  dataPage        = 0;
    unsigned int  counter         = 0;
    unsigned int  startCounter    = 0;
    unsigned int  additionalData1 = 0;
    unsigned int  additionalData2 = 0;
    unsigned int  additionalData3 = 0;
    unsigned int  additionalData4 = 0;
    amString      curVersion      = getVersion();
    amString      timeStampBuffer;
    amString      sensorID;
    amString      timeStampString;
    amString      semiCookedString;
    amString      dataPageString;
    bool          commonPage      = false;
    bool          outputPageNo    = true;
    amSplitString words;
    unsigned int  nbWords         = words.split( inputBuffer );

    // Semi-cooked string has the syntax
    //    "<device_id>\t<time_stamp>\t<semi_cooked_symbol>\t<data_page>\t...."

    if ( nbWords > 3 )
    {
        sensorID         = words[ counter++ ];                                                   // 0 - sensor ID
        timeStampBuffer  = words[ counter++ ];                                                   // 1 - time stamp
        semiCookedString = words[ counter++ ];                                                   // 2 - semi-cooked indicator
        if ( diagnostics )
        {
            appendDiagnosticsLine( "SensorID",   sensorID );
            appendDiagnosticsLine( "Timestamp",  timeStampBuffer );
            appendDiagnosticsLine( "SemiCooked", semiCookedString );
        }
        if ( isRegisteredDevice( sensorID ) && ( semiCookedString == C_SEMI_COOKED_SYMBOL_AS_STRING ) && isEnvironmentSensor( sensorID ) )
        {
            dataPage = words[ counter++ ].toUInt();                                              // 3 - data page
            if ( words[ counter ] == C_UNSUPPORTED_DATA_PAGE )
            {
                result = UNKNOWN_DEVICE;
            }
            else
            {
                startCounter = counter;

                switch ( dataPage & 0x0F )
                {
                    case  0: // - - Page 0: No Additional Data - - - - - - - - - - - - - - -
                             //
                             if ( nbWords > 7 )
                             {
                                 result          = ENVIRONMENT_SENSOR;
                                 additionalData1 = words[ counter++ ].toUInt();                      // 4 - Local Time
                                 additionalData2 = words[ counter++ ].toUInt();                      // 5 - UTC Time
                                 additionalData3 = words[ counter++ ].toUInt();                      // 6 - Transmission Rate
                                 additionalData4 = words[ counter++ ].toUInt();                      // 7 - Supported Pages
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Local Time",        additionalData1 );
                                     appendDiagnosticsLine( "UTC Time",          additionalData2 );
                                     appendDiagnosticsLine( "Transmission Rate", additionalData2 );
                                     appendDiagnosticsLine( "Supported Pages",   additionalData4 );
                                 }
                             }
                             break;
                    case  1: // - - Page 1: Temperature  - - - - - - - - - - - - - - - - - - - - - - - - -
                             //
                             if ( nbWords > 7 )
                             {
                                 result          = ENVIRONMENT_SENSOR;
                                 additionalData1 = words[ counter++ ].toUInt();                      // 4 - Current Temperature
                                 additionalData2 = words[ counter++ ].toUInt();                      // 5 - Low Temperature 24h
                                 additionalData3 = words[ counter++ ].toUInt();                      // 6 - High Temperature 24h
                                 additionalData4 = words[ counter++ ].toUInt();                      // 7 - Event Count
                                 if ( diagnostics )
                                 {
                                     appendDiagnosticsLine( "Current Temperature * 100", additionalData1 );
                                     appendDiagnosticsLine( "Low Temperature * 10",      additionalData2, " (last 24h)" );
                                     appendDiagnosticsLine( "High Temperature * 10",     additionalData3, " (last 24h)" );
                                     appendDiagnosticsLine( "Event Count",               additionalData4 );
                                 }
                             }
                             break;
                    default: commonPage = true;
                             result     = ENVIRONMENT_SENSOR;
                             break;
                }
            }
        }
    }

    if ( result == ENVIRONMENT_SENSOR )
    {
        if ( nbWords > counter )
        {
            curVersion = words.back();
            if ( diagnostics )
            {
                appendDiagnosticsLine( "Version", curVersion );
            }
        }

        createOutputHeader( sensorID, timeStampBuffer );
        if ( commonPage )
        {
            commonPage = processCommonPagesSemiCooked( words, startCounter, outputPageNo );
            if ( !commonPage )
            {
                result = OTHER_DEVICE;
            }
        }
        else
        {
            createENVResultString( dataPage, additionalData1, additionalData2, additionalData3, additionalData4 );
        }
        appendOutputFooter( curVersion );
    }
    else if ( result == UNKNOWN_DEVICE )
    {
        result = processUnsupportedDataPage( words );
    }

    if ( result == OTHER_DEVICE )
    {
        resetOutBuffer();
        if ( outputUnknown )
        {
            setOutBuffer( inputBuffer );
        }
    }

    return result;
}