You Are Here:

Community: Wiki

This page was last modified on 20 September 2009, at 13:38.

Bluetooth GPS Receiver - NMEA Parsing

From Forum Nokia Wiki

Reviewer Approved   

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 Wiki Articles

No related wiki articles found

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia 
RDF Facets: qdcZdescriptionQSxEa0E20WikiE20javaE20symbianE5fosE20s60E20maemoE20cE2bE2bE20WikiE20HomeE20WikiE20HelpE20OverviewE20GlossaryE20CreateE20PageE20ProposeE20anE20ArticleE20SpotlightE20TopicE20E2dE20WE52TE20WidgetsE20ProgrammingE20E4canguageE20E2dE20SymbianE20CE2bE2bE20E2dE20OpenE20CE2fCE2bE2bE20E2dE20JavaE20E2dE20FlashE20E4citeE20E2dE20PythonE20WebE20TechnologiesE20E2dE20WE52TE20WidgetsE20E2dE20WidSetsE20ToolsE20andE20SE44KE20CodeE20E45E78amplesE20KnowledgeE20BaseE20TechnologyE20AreasE20SoftwareE20PlatformsE20E44evelopmentE20ProcessE20E3fE3fWikiE20ChineseE20E3fE3fE3fWikiE20JapaneseE20PortugueseE2fBrazilianE20E52ussianE20WhatE20linksE20hereE20UploadE20fileE20SpecialE20pagesE20PrintableE20versionE44ownloadE20asE20PE44FE20GoE20ToE20E2eE2eE2eX qdcZidentifierQSxhttpE3aE2fE2fwikiE2eforumE2enokiaE2ecomE2findeE78E2ephpE2fBluetoothE5fGPSE5fE52eceiverE5fE2dE5fNME45AE5fParsingX qdcZpublisherQUxhttpE3aE2fE2fswE2enokiaE2ecomE2fidE2fc764fd1cE2d8b06E2d499aE2d9a6aE2d17c3903d5a65E2fforumE5fnokiaE5fcrawlerE5fagentX qdcZtitleQSxBluetoothE20GPSE20E52eceiverE20E2dE20NME45AE20ParsingE20E2dE20ForumE20NokiaE20WikiX qdcZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qdcZtypeQUqfntypeZCommunityContentQ qdcZtypeQUqfntypeZE52esourceQ qdcZtypeQUqfntypeZWebpageQ qdcZtypeQUqfntypeZWikiContentQ qdcZtypeQUqmarsZManagedE52esourceQ qdcZtypeQUqwebZInformationE52esourceQ qdcZtypeQUqwebZPageQ qdcZtypeQUqwebZE52esourceQ qdcZtypeQUqrdfsZE52esourceQ qrssZdescriptionQSxEa0E20WikiE20javaE20symbianE5fosE20s60E20maemoE20cE2bE2bE20WikiE20HomeE20WikiE20HelpE20OverviewE20GlossaryE20CreateE20PageE20ProposeE20anE20ArticleE20SpotlightE20TopicE20E2dE20WE52TE20WidgetsE20ProgrammingE20E4canguageE20E2dE20SymbianE20CE2bE2bE20E2dE20OpenE20CE2fCE2bE2bE20E2dE20JavaE20E2dE20FlashE20E4citeE20E2dE20PythonE20WebE20TechnologiesE20E2dE20WE52TE20WidgetsE20E2dE20WidSetsE20ToolsE20andE20SE44KE20CodeE20E45E78amplesE20KnowledgeE20BaseE20TechnologyE20AreasE20SoftwareE20PlatformsE20E44evelopmentE20ProcessE20E3fE3fWikiE20ChineseE20E3fE3fE3fWikiE20JapaneseE20PortugueseE2fBrazilianE20E52ussianE20WhatE20linksE20hereE20UploadE20fileE20SpecialE20pagesE20PrintableE20versionE44ownloadE20asE20PE44FE20GoE20ToE20E2eE2eE2eX qfnZdistributionQUxhttpE3aE2fE2fwikiE2eforumE2enokiaE2ecomE2fX qfnZtopicQUqfnTopicZbluetoothQRqdcZtypeQUqrdfsZE52esourceQRqmarsZrelevanceQNx100X qfnZtopicQUqfnTopicZconnectivityQRqdcZtypeQUqrdfsZE52esourceQRqmarsZrelevanceQNx100X qfnZtopicQUqfnTopicZgpsQRqdcZtypeQUqrdfsZE52esourceQRqmarsZrelevanceQNx100X qfnZtopicQUqfnTopicZlocationQRqmarsZrelevanceQNx100X qfnZtopicQUqfnTopicZseriesE5f60QRqdcZtypeQUqrdfsZE52esourceQRqmarsZrelevanceQNx100X qfnZtypeQUqfntypeZCommunityContentQ qfnZtypeQUqfntypeZE52esourceQ qfnZtypeQUqfntypeZWebpageQ qfnZtypeQUqfntypeZWikiContentQ qfnZupdatedQDx2008E2d10E2d03X qfnZuserE5ftagQSxbluetoothX qfnZuserE5ftagQSxconnectivityX qfnZuserE5ftagQSxgpsX qfnZuserE5ftagQSxlocationE2dbasedE2dservicesX qfnZuserE5ftagQSxs60X qmarsZdescriptionQSxEa0E20WikiE20javaE20symbianE5fosE20s60E20maemoE20cE2bE2bE20WikiE20HomeE20WikiE20HelpE20OverviewE20GlossaryE20CreateE20PageE20ProposeE20anE20ArticleE20SpotlightE20TopicE20E2dE20WE52TE20WidgetsE20ProgrammingE20E4canguageE20E2dE20SymbianE20CE2bE2bE20E2dE20OpenE20CE2fCE2bE2bE20E2dE20JavaE20E2dE20FlashE20E4citeE20E2dE20PythonE20WebE20TechnologiesE20E2dE20WE52TE20WidgetsE20E2dE20WidSetsE20ToolsE20andE20SE44KE20CodeE20E45E78amplesE20KnowledgeE20BaseE20TechnologyE20AreasE20SoftwareE20PlatformsE20E44evelopmentE20ProcessE20E3fE3fWikiE20ChineseE20E3fE3fE3fWikiE20JapaneseE20PortugueseE2fBrazilianE20E52ussianE20WhatE20linksE20hereE20UploadE20fileE20SpecialE20pagesE20PrintableE20versionE44ownloadE20asE20PE44FE20GoE20ToE20E2eE2eE2eX qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX qrdfZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qrdfZtypeQUqfntypeZCommunityContentQ qrdfZtypeQUqfntypeZE52esourceQ qrdfZtypeQUqfntypeZWebpageQ qrdfZtypeQUqfntypeZWikiContentQ qrdfZtypeQUqmarsZManagedE52esourceQ qrdfZtypeQUqwebZInformationE52esourceQ qrdfZtypeQUqwebZPageQ qrdfZtypeQUqwebZE52esourceQ qrdfZtypeQUqrdfsZE52esourceQ