An OOP version of a GPS NMEA Sentence. See the output of the example codes from under the below class definition.
<?php
/**
* A class for generating and validating objects which represent GPS NMEA Sentences
*
* @author Jim Auldridge
* @link http://www.codepedia.com/1/The+GPRMC+Sentence
* @link http://www.codepedia.com/1/Calculating+and+Validating+NMEA+Checksums
*/
class GPS_NMEA_Sentence
{
protected $Sentence;
protected $Data;
protected $Internal_Checksum;
protected $Calculated_Checksum;
protected $Valid_Command_Words = array( 'GPRMC' );
protected $CommandWord = 'GPRMC';
protected $SatelliteDerivedTime = '';
protected $SatelliteFixStatus = '';
protected $LatitudeDecimalDegrees = '';
protected $LatitudeHemisphere = '';
protected $LongitudeDecimalDegrees = '';
protected $LongitudeHemisphere = '';
protected $Speed = '';
protected $Bearing = '';
protected $UTCDate = '';
protected $Valid = false;
protected $in_error = false;
protected $error_str = '';
/**
*
* @access public
* @param OPTIONAL STRING $GPS_NMEA_Sentence
* @return void
*/
public function __construct( $GPS_NMEA_Sentence = null )
{
if( ! is_null( $GPS_NMEA_Sentence ) )
{
$this->setSentence( $GPS_NMEA_Sentence );
}
}
/**
*
* @access public
* @param STRING $GPS_NMEA_Sentence
* @return GPS_NMEA_Sentence
*/
public function setSentence( $GPS_NMEA_Sentence )
{
if( is_string( $GPS_NMEA_Sentence ) && ! empty( $GPS_NMEA_Sentence ) )
{
$this->Sentence = $GPS_NMEA_Sentence;
}
else
{
$this->setError( __METHOD__ . 'received non-string or empty value.' );
}
$this->resetStatuses();
$this->parseSentence();
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setCommandWord( $value )
{
$this->CommandWord = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setSatelliteDerivedTime( $value )
{
$this->SatelliteDerivedTime = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setSatelliteFixStatus( $value )
{
$this->SatelliteFixStatus = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setLatitudeDecimalDegrees( $value )
{
$this->LatitudeDecimalDegrees = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setLatitudeHemisphere( $value )
{
$this->LatitudeHemisphere = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setLongitudeDecimalDegrees( $value )
{
$this->LongitudeDecimalDegrees = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setLongitudeHemisphere( $value )
{
$this->LongitudeHemisphere = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setSpeed( $value )
{
$this->Speed = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setBearing( $value )
{
$this->Bearing = $value;
return $this;
}
/**
*
* @access public
* @param STRING $value
* @return GPS_NMEA_Sentence
*/
public function setUTCDate( $value )
{
$this->UTCDate = $value;
return $this;
}
/**
*
* @access public
* @return STRING
*/
public function getSentence()
{
return ( ! $this->inError() && $this->isValid() ) ? $this->Sentence : '';
}
/**
*
* @access public
* @return STRING
*/
public function __toString()
{
return $this->getSentence();
}
/**
*
* @access public
* @return STRING
*/
public function getCommandWord()
{
return $this->CommandWord;
}
/**
*
* @access public
* @return STRING
*/
public function getSatelliteDerivedTime()
{
return $this->SatelliteDerivedTime;
}
/**
*
* @access public
* @return STRING
*/
public function getSatelliteFixStatus()
{
return $this->SatelliteFixStatus;
}
/**
*
* @access public
* @return STRING
*/
public function getLatitudeDecimalDegrees()
{
return $this->LatitudeDecimalDegrees;
}
/**
*
* @access public
* @return STRING
*/
public function getLatitudeHemisphere()
{
return $this->LatitudeHemisphere;
}
/**
*
* @access public
* @return STRING
*/
public function getLongitudeDecimalDegrees()
{
return $this->LongitudeDecimalDegrees;
}
/**
*
* @access public
* @return STRING
*/
public function getLongitudeHemisphere()
{
return $this->LongitudeHemisphere;
}
/**
*
* @access public
* @return STRING
*/
public function getSpeed()
{
return $this->Speed;
}
/**
*
* @access public
* @return STRING
*/
public function getBearing()
{
return $this->Bearing;
}
/**
*
* @access public
* @return STRING
*/
public function getUTCDate()
{
return $this->UTCDate;
}
/**
*
* @access public
* @return OBJECT $this
*/
public function parseSentence()
{
if( ! $this->inError() )
{
$this->extractDataFromSentence();
$this->calculateChecksum();
$this->extractWordsFromData();
$this->extractInternalChecksum();
$this->Valid = !! ( $this->compareChecksums() && $this->validCommandWord() );
}
return $this;
}
/**
*
* @access public
* @return OBJECT $this
*/
public function writeSentence()
{
if( ! $this->inError() )
{
$this->Data = sprintf(
'%s,%s,%s,%s,%s,%s,%s,%s,%s,%s',
$this->CommandWord,
$this->SatelliteDerivedTime,
$this->SatelliteFixStatus,
$this->LatitudeDecimalDegrees,
$this->LatitudeHemisphere,
$this->LongitudeDecimalDegrees,
$this->LongitudeHemisphere,
$this->Speed,
$this->Bearing,
$this->UTCDate
);
$this->calculateChecksum();
$this->Internal_Checksum = $this->Calculated_Checksum;
$this->Valid = !! ( $this->compareChecksums() && $this->validCommandWord() );
$this->Sentence = sprintf(
'$%s*%s',
$this->Data,
$this->Internal_Checksum
);
}
return $this;
}
/**
*
* @access public
* @return BOOLEAN
*/
public function isValid()
{
return $this->Valid;
}
/**
*
* @access public
* @return BOOLEAN
*/
public function inError()
{
return $this->in_error;
}
/**
*
* @access public
* @return MIXED
*/
public function getErrorStr()
{
return $this->in_error ? $this->error_str : null;
}
/**
*
* @access protected
* @return void
*/
protected function setError($error_str)
{
$this->in_error = true;
$this->error_str = $error_str;
}
/**
*
* @access public
* @return OBJECT $this
*/
public function resetStatuses()
{
$this->Valid = false;
$this->in_error = false;
$this->error_str = '';
}
/**
*
* @access protected
* @return void
*/
protected function extractDataFromSentence()
{
if( ! $this->inError() )
{
preg_match( '/^\$([^*]+)\*/', $this->Sentence,$GPS_NMEA_Data );
if( is_array( $GPS_NMEA_Data ) && ! empty( $GPS_NMEA_Data[1] ) )
{
$this->Data = $GPS_NMEA_Data[1];
}
else
{
$this->setError( __METHOD__ . ' could not extract data from $Sentence property.');
}
}
}
/**
*
* @access protected
* @return void
*/
protected function extractWordsFromData()
{
static $wordnames = array(
'CommandWord',
'SatelliteDerivedTime',
'SatelliteFixStatus',
'LatitudeDecimalDegrees',
'LatitudeHemisphere',
'LongitudeDecimalDegrees',
'LongitudeHemisphere',
'Speed',
'Bearing',
'UTCDate'
);
if( ! $this->inError() )
{
$words = explode( ',', $this->Data );
for( $i = 0; $i < count( $wordnames ); $i++ )
{
$this->$wordnames[$i] = empty( $words[$i] ) ? '' : $words[$i];
}
}
}
/**
*
* @access protected
* @return void
*/
protected function extractInternalChecksum()
{
if( ! $this->inError() )
{
preg_match( '/\*([^,]+)(?:,|$)/', $this->Sentence, $GPS_NMEA_Internal_Checksum );
if( is_array( $GPS_NMEA_Internal_Checksum ) && ! empty( $GPS_NMEA_Internal_Checksum[1] ) )
{
$this->Internal_Checksum = $GPS_NMEA_Internal_Checksum[1];
}
else
{
$this->setError( __METHOD__ . ' could not extract internal checksum from $Sentence property.');
}
}
}
/**
*
* @access protected
* @return void
*/
protected function calculateChecksum()
{
if( ! $this->inError() )
{
$Calculated_Checksum = 0;
for( $i = 0; $i < strlen( $this->Data ); $i++ )
{
$Calculated_Checksum = ( $Calculated_Checksum ^ ord( $this->Data[$i] ) );
}
$this->Calculated_Checksum = dechex( $Calculated_Checksum );
}
}
/**
*
* @access protected
* @return void
*/
protected function compareChecksums()
{
$return_value = false;
if( ! $this->inError() )
{
if( $this->Internal_Checksum === $this->Calculated_Checksum )
{
$return_value = true;
}
else
{
$this->setError( __METHOD__.' found checksum mismatch.' );
}
}
return $return_value;
}
/**
*
* @access protected
* @return void
*/
protected function validCommandWord()
{
$return_value = false;
if( ! $this->inError() )
{
if( isset( $this->CommandWord ) && in_array( $this->CommandWord, $this->Valid_Command_Words ) )
{
$return_value = true;
}
else
{
$this->setError( __METHOD__ . ' detected empty or incorrect CommandWord in $Sentence property.');
}
}
return $return_value;
}
}
/* ***** EXAMPLES ********* */
//Two valid GPS NMEA Sentence Strings
$GPS_Serial_Output_1 = '$GPRMC,030748.000,A,4553.0146,N,07352.1516,W,0.25,0.00,171107,,,A*76,AUTO';
$GPS_Serial_Output_2 = '$GPRMC,155123.000,A,4043.8432,N,07359.7653,W,0.15,83.25,200407,,*28';
//And a third that is bad
$GPS_Serial_Output_3 = '$GPRMC,155213.000,A,4053.8432,N,07359.7653,W,0.15,83.25,200407,,*49';
//
$oGPS_NMEA_Sentence = new GPS_NMEA_Sentence;
$oGPS_NMEA_Sentence->setSentence($GPS_Serial_Output_1);
echo '<h1>', $oGPS_NMEA_Sentence, '</h1>';
echo "\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";
$oGPS_NMEA_Sentence->setSentence($GPS_Serial_Output_2);
echo '<h1>', $oGPS_NMEA_Sentence, '</h1>';
echo "\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";
$oGPS_NMEA_Sentence->setSentence($GPS_Serial_Output_3);
echo '<h1>', $oGPS_NMEA_Sentence, '</h1>';
echo "\n\n<pre>\n";var_dump($oGPS_NMEA_Sentence);echo "\n</pre>\n\n";
//Make a new empty GPS NMEA Sentence Object
$brandNew = new GPS_NMEA_Sentence();
//Set some properties on it and write the sentence property
$brandNew->setLatitudeHemisphere('E')->setLongitudeHemisphere('S')->writeSentence();
//dump out the object to see what it looks like
echo "\n\n<pre>\n";var_dump($brandNew);echo "\n</pre>\n\n";
//echo the sentence property
echo $brandNew->getSentence().'<br />';
//Make a new sentence with the otput string of the original to see if it validates
$testingBrandNew = new GPS_NMEA_Sentence($brandNew->getSentence());
//Dump it and see what we got
echo "\n\n<pre>\n";var_dump($testingBrandNew);echo "\n</pre>\n\n";