Categories: Symbian C++ | S60 | Code Examples | Connectivity | Bluetooth | GPS
This page was last modified 17:16, 1 January 2008.
Bluetooth GPS Receiver - NMEA Parsing
From Forum Nokia Wiki
Contents |
Introduction
Getting GPS data is quite often needed by many location-based application with hand-held devices. In our case we can retrive GPS details such as Latitude, Logitude, Altitude, Speed etc... with S60 devices. GPS receiver generally reads GPS data with the means of NMEA Sentences. One cannot retrieve straight away GPS details from these NMEA Sentences. NMEA sentences need to be parsed to get such GPS details. The following code snippets illustrate how to parse these NMEA sentences with Symbian C++ connecting to Bluetooth GPS Receiver.
Prerequisite
- Bluetooth GPS Receiver
- Here we are using btpointtopoint given in the SDK package to use Bluetooth functionalities.
- S60 2nd Edition device.
NMEAParser.h
#ifndef __CNMEAParser_H__ #define __CNMEAParser_H__ #include <E32Base.h> class CNMEAParser : public CBase { public: // Set the NMEA Data void SetData( TDesC8 & aNmeaMessage ); // Skip the next Token from NMEA sentence void SkipNextTokenL( ); // Read the Next Token from NMEA sentence void ReadNextTokenL( TDes8 & aBuffer ); // Read Next Token from NMEA sentecne as Latitude TReal ReadNextTokenAsLatitudeL( ); // Read Next Token from NMEA sentecne as Longitude TReal ReadNextTokenAsLongitudeL( ); // This will return Next Token from NMEA sentence as TInt TInt ReadNextTokenAsIntL( ); // This will return Next Token from NMEA sentence as TReal TReal ReadNextTokenAsRealL( ); // Clear the NMEA Data void ClearData( ); private: TDesC8 * iMessage; TInt iParsePosition; }; #endif
NMEAParser.cpp
#include <E32Math.h> #include "NMEAParser.h" // Set the NMEA Data void CNMEAParser::SetData( TDesC8 & aNmeaMessage ) { iMessage = &aNmeaMessage; iParsePosition = 0; } // Read the Next Token from NMEA sentence void CNMEAParser::ReadNextTokenL( TDes8 & aBuffer ) { if ( iMessage == NULL ) User::Leave( KErrNotReady ); if ( iParsePosition >= iMessage->Length( ) ) return; while ( iParsePosition < iMessage->Length( ) ) { TUint8 nextChar = ( *iMessage )[ iParsePosition++ ]; if ( nextChar == ',' ) break; aBuffer.Append( nextChar ); } } // Skip the next Token from NMEA sentence void CNMEAParser::SkipNextTokenL( ) { if ( iMessage == NULL ) User::Leave( KErrNotReady ); if ( iParsePosition >= iMessage->Length( ) ) return; while ( iParsePosition < iMessage->Length( ) ) { TUint8 nextChar = ( *iMessage )[ iParsePosition++ ]; if ( nextChar == ',' ) break; } } // Read Next Token from NMEA sentecne as Latitude TReal CNMEAParser::ReadNextTokenAsLatitudeL( ) { TReal angle; TBuf8< 15 > angleString; ReadNextTokenL( angleString ); TBuf8< 5 > northSouth; ReadNextTokenL( northSouth ); TLex8 latLexer( angleString ); TInt error = latLexer.Val( angle, '.' ); if ( error != KErrNone ) return 0.0; TInt32 degrees; Math::Int( degrees, angle / 100.0 ); TInt32 minutes; Math::Int( minutes, angle - degrees * 100 ); TReal decimal; Math::Frac( decimal, angle ); TReal latitude = degrees + ( minutes + decimal ) / 60.0; if ( northSouth[ 0 ] == 'S' ) latitude = -latitude; return( latitude ); } // Read Next Token from NMEA sentecne as Longitude TReal CNMEAParser::ReadNextTokenAsLongitudeL( ) { TReal angle; TBuf8< 15 > angleString; ReadNextTokenL( angleString ); TBuf8< 5 > northSouth; ReadNextTokenL( northSouth ); TLex8 latLexer( angleString ); TInt error = latLexer.Val( angle, '.' ); if ( error != KErrNone ) return 0.0; TInt32 degrees; Math::Int( degrees, angle / 100.0 ); TInt32 minutes; Math::Int( minutes, angle - degrees * 100 ); TReal decimal; Math::Frac( decimal, angle ); TReal longitude = degrees + ( minutes + decimal ) / 60.0; if ( northSouth[ 0 ] == 'W' ) longitude = -longitude; return( longitude ); } // This will return Next Token from NMEA sentence as TInt TInt CNMEAParser::ReadNextTokenAsIntL( ) { TInt result = 0; TBuf8< 10 > intString; ReadNextTokenL( intString ); TLex8 lexer( intString ); TInt ret = lexer.Val( result ); if( ret == KErrNone) return( result ); else return 0.0; } // This will return Next Token from NMEA sentence as TReal TReal CNMEAParser::ReadNextTokenAsRealL( ) { TReal result = 0; TBuf8< 10 > realString; ReadNextTokenL( realString ); TLex8 lexer( realString ); TInt ret = lexer.Val( result ); if( ret == KErrNone) return( result ); else return 0.0; } // Clear the NMEA Data void CNMEAParser::ClearData( ) { iMessage = NULL; iParsePosition = 0; }
messageclient.h
- You can find messageclient.h in the btpointtopoint example given in the SDK package.
- Include NMEAParser.h in the messageclient.h
#include "NMEAParser.h" //For NMEA sentence Parsing
- Declare the following list of functions:
//Following functions are declared for NMEA sentence parsing purpose public: void WriteToFile(TBuf8<100> aData); void NMEAUpdate( const TDes8 & aNMEABuffer ); void HandleMessageL( TDesC8 & aCommand ); void HandleGPGGAMsgL( TDesC8 & aCommand ); void HandleGPGLLMsgL( TDesC8 & aCommand ); void HandleGPVTGMsgL( TDesC8 & aCommand ); void HandleGPRMCMsgL( TDesC8 & aCommand );
- Declare the following list of variables and objet.
TBuf8 <1024> iDummyBuffer TBuf8 <1024> iTempBuffer; TBuf8 <256> iFileData; TBuf8 <512> iMessageBuffer; TReal speedInKMH; CNMEAParser iNmeaParser;
messageclient.cpp
- Change EConnceted case like:
case EConnected: iTempBuffer.Zero(); iTempBuffer.Copy(iDummyBuffer); if( iTempBuffer.Length() > 200 ) NMEAUpdate(iTempBuffer); // Just dump data iDummyBuffer.Zero(); // Catch disconnection event // By waiting to read socket WaitOnConnectionL(); break;
- Implement functions to process NMEA Sentences:
//Following functions are implemeted for NMEA sentence parsing purpose void CMessageClient::NMEAUpdate( const TDes8 & aNMEABuffer ) { TBool inMessage = ( iMessageBuffer.Length( ) > 0 ) ? ETrue : EFalse; for ( TInt Index = 0; Index < aNMEABuffer.Length( ); Index++ ) { TUint8 next = aNMEABuffer[ Index ]; if ( inMessage == EFalse && ( next == '$' ) ) inMessage = ETrue; if ( inMessage ) iMessageBuffer.Append( aNMEABuffer[ Index ] ); if ( inMessage && ( next == 13 ) ) { inMessage = EFalse; HandleMessageL( iMessageBuffer ); iMessageBuffer.SetLength( 0 ); } } }
void CMessageClient::HandleMessageL( TDesC8 & aCommand ) { TBuf8< 32 > temp; _LIT( KGlobalPositioning, "$GPGGA" ); temp.Copy( KGlobalPositioning ); TInt foundGPGGA = aCommand.Find( temp ); if ( foundGPGGA == 0 ) HandleGPGGAMsgL( aCommand ); _LIT( KGeographicPosition, "$GPGLL" ); temp.Copy( KGeographicPosition ); TInt foundGPGLL = aCommand.Find( temp ); if ( foundGPGLL == 0 ) HandleGPGLLMsgL( aCommand ); _LIT( KCourseData, "$GPVTG" ); temp.Copy( KCourseData ); TInt foundGPVTG = aCommand.Find( temp ); if ( foundGPVTG == 0 ) HandleGPVTGMsgL( aCommand ); }
void CMessageClient::HandleGPGGAMsgL( TDesC8 & aCommand ) { iNmeaParser.SetData( aCommand ); iNmeaParser.SkipNextTokenL( ); // skip message id TReal utcTime = iNmeaParser.ReadNextTokenAsRealL( ); TReal Latitude = iNmeaParser.ReadNextTokenAsLatitudeL( ); TReal Longitude = iNmeaParser.ReadNextTokenAsLongitudeL( ); TInt fixValid = iNmeaParser.ReadNextTokenAsIntL( ); TInt satellites = iNmeaParser.ReadNextTokenAsIntL( ); TReal hdop = iNmeaParser.ReadNextTokenAsRealL( ); TReal altitude = iNmeaParser.ReadNextTokenAsRealL( ); //Added for storing values in File TBuf8<100> iData; iData.Format(_L8("Lat=%f\nLon=%f\nAlt=%f\n"),Latitude,Longitude,altitude); WriteToFile(iData); //Code ends iNmeaParser.ClearData( ); }
void CMessageClient::HandleGPGLLMsgL( TDesC8 & aCommand ) { iNmeaParser.SetData( aCommand ); iNmeaParser.SkipNextTokenL( ); // skip message id TReal Latitude = iNmeaParser.ReadNextTokenAsLatitudeL( ); TReal Longitude = iNmeaParser.ReadNextTokenAsLongitudeL( ); //Added for storing values in File TBuf8<100> iData; iData.Format(_L8("Lat=%f Lon=%f\n"),Latitude,Longitude); WriteToFile(iData); //Code ends iNmeaParser.ClearData( ); }
void CMessageClient::HandleGPVTGMsgL( TDesC8 & aCommand ) { iNmeaParser.SetData( aCommand ); iNmeaParser.SkipNextTokenL( ); // skip message id TReal heading = iNmeaParser.ReadNextTokenAsRealL( ); iNmeaParser.SkipNextTokenL( ); // skip heading unit iNmeaParser.SkipNextTokenL( ); // skip magnetic heading iNmeaParser.SkipNextTokenL( ); // skip magnetic heading unit TReal speedInKnots = iNmeaParser.ReadNextTokenAsRealL( ); //Convertion from speed in Knots into speed in KiloMeters/Hour speedInKMH = speedInKnots * 1.85 ; //Conversion ends iNmeaParser.SkipNextTokenL( ); // skip speed unit iNmeaParser.SkipNextTokenL( ); // skip speed in km/h iNmeaParser.SkipNextTokenL( ); // skip speed unit iNmeaParser.ClearData( ); //Added for storing values in File TBuf8<100> iData; iData.Format(_L8("VTG Speed=%f\n"),speedInKMH); WriteToFile(iData); //Code ends }
Related Links
GPS - NMEA sentence information
| Related Discussions | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Possible: Using BT GPS and BT Carkit at the same time ? | keysersoze0909 | Bluetooth Technology | 2 | 2006-03-06 10:17 |
| 7650 bluetooth problem | movetek | Symbian Networking & Messaging | 2 | 2003-07-10 15:02 |
| N95 GPS with Python | krtrivdi | Python | 1 | 2007-07-30 19:59 |
| MLFW (GPS) not working on Nokia 6630 (Symbian 8.0a) | kvr0 | Symbian Networking & Messaging | 3 | 2006-03-08 10:13 |
| Bluetooth GPS | Royguo | Bluetooth Technology | 0 | 2005-03-14 19:13 |
