The below code defines a function for taking an entire GPS NMEA Sentence and verifying its intergrity. Below the function definition are three GPS NMEA Sentences, 2 of which are good and 1 of which is bad. The three are then run through the function and statuses are output to the screen. See it work or See the lesser commented/styled version. Or check out the full OOP version.
<?php
/**
* Verify integrity of a GPS NMEA Sentence by extracting the data and the internal checksum, calculating the checksum of the data, and comparing it to the internal checksum
*
* @param STRING $GPS_NMEA_Sentence --The GPS NMEA sentence we are checking
* @return BOOL --True if integrity is good, false if not
* @author Jim Auldridge
* @link http://www.codepedia.com/1/The+GPRMC+Sentence
* @link http://www.codepedia.com/1/Calculating+and+Validating+NMEA+Checksums
* @link http://www.tigoe.net/pcomp/code/category/code/processing/127
* @link http://wiki.forum.nokia.com/index.php/NMEA_(GPS)_Location_Viewer
*/
function GPS_NMEA_Sentence_Integrity($GPS_NMEA_Sentence)
{
//Assume failure...
$return_value = false;
//Sanity check on input
if(is_string($GPS_NMEA_Sentence))
{
//Extract Data and Internal Checksum
preg_match('/^\$([^*]+)\*/', $GPS_NMEA_Sentence, $GPS_NMEA_Data );
preg_match('/\*([^,]+)(,|$)/', $GPS_NMEA_Sentence, $GPS_NMEA_Internal_Checksum );
//Ensure extractions got what we needed
if
(
is_array($GPS_NMEA_Data) &&
!empty($GPS_NMEA_Data[1]) &&
is_array($GPS_NMEA_Internal_Checksum) &&
!empty($GPS_NMEA_Internal_Checksum[1])
)
{
//Simplify extracted data
$GPS_NMEA_Data = $GPS_NMEA_Data[1];
$GPS_NMEA_Internal_Checksum = $GPS_NMEA_Internal_Checksum[1];
//Start calculating checksum, begin at 0
$Calculated_Checksum = 0;
//Loop for length of data string
for($i=0;$i<strlen($GPS_NMEA_Data);$i++)
{
//Adding to checksum the XOR of the current value of checksum and the
//ASCII code of the current char of the data string for this iteration
$Calculated_Checksum = ($Calculated_Checksum ^ ord($GPS_NMEA_Data{$i}));
}
//Convert our calculated checksum to hex
$Calculated_Checksum = dechex($Calculated_Checksum);
//Compare it to the internal checksum and set return accordingly
$return_value = !!($GPS_NMEA_Internal_Checksum===$Calculated_Checksum);
}
}
//Return the BOOL value
return $return_value;
}
//Two Good Sentences
$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';
//Checking them all:
echo '<p>Checking Sentence 1: <strong>'.(GPS_NMEA_Sentence_Integrity($GPS_Serial_Output_1) ? 'Good' : 'Bad').'</strong></p>';
echo '<p>Checking Sentence 2: <strong>'.(GPS_NMEA_Sentence_Integrity($GPS_Serial_Output_2) ? 'Good' : 'Bad').'</strong></p>';
echo '<p>Checking Sentence 3: <strong>'.(GPS_NMEA_Sentence_Integrity($GPS_Serial_Output_3) ? 'Good' : 'Bad').'</strong></p>';
?>