Sign in to follow this  
Followers 0
anixon

Checksum

10 posts in this topic

Calculating the checksum is the representation of two hexadecimal characters of an XOR of all characters in the sentence between – but not including – the $ and the * character.

Lets assume the following NMEA sentence:

$GPGLL,5300.97914,N,00259.98174,E,125926,A*28

In this sentence the checksum is the character representation of the hexadecimal value 28. The string that the checksum is calculated over is

GPGLL,5300.97914,N,00259.98174,E,125926,A

To calculate the checksum you parse all characters between $ and * from the NMEA sentence into a new string. In the examples below the name of this new string is stringToCalculateTheChecksumOver. Then just XOR the first character with the next character, until the end of the string.

Below you find a code example in Java script, VB.Net and C#.

In Java script:

var checksum = 0; <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">for(var i = 0; i < stringToCalculateTheChecksumOver.length; i++) { <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;"> checksum = checksum ^ stringToCalculateTheChecksumOver.charCodeAt(i); <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">}

In C#:

int checksum = 0; <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">for (inti = 0; i < stringToCalculateTheChecksumOver.length; i++){ <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">checksum ^= Convert.ToByte(sentence);}

In VB.Net:

Dim checksum as Integer = 0 <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">For Each Character As Char In stringToCalculateTheChecksumOver <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;"> checksum = checksum Xor Convert.ToByte(Character) <br style="margin: 0px; padding: 0px; line-height: 1.4em; font-size: 9px;">Next

What is left is to transform the checksum into two hexadecimal characters, and that is it. In VB.Net and C# you can use the ToString function for this, e.g. strChecksum=checksum.ToString(“X2”).

Can this calculator be coded in AutoIT and is their an example available?

Replies are always appreciated

Ant.. :))

Share this post


Link to post
Share on other sites



Hi anxion,

sure this can be done.

You might want to take a look at Binary(), BitXOR() and StrinSplit() functions.


Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi anxion,

sure this can be done.

You might want to take a look at Binary(), BitXOR() and StrinSplit() functions.

The Visual basic code converts the character to bytes how is that achieved in AutoIT?

Edited by anixon

Share this post


Link to post
Share on other sites

I'm struggling with this one. Based on the NMEA checksum calculator method can anyone confirm that this code produces the correct checksum 'x38' for the string 'a9' $value1 = "a" and $value2 = 9. I have yet to write the loop to xor all the values that would normall make up a string. What this calculates is the checksum on the assumption that their are only two chrs in the string.

$value1 = "a"

$value2 = 9

Msgbox(0,"",BitXOR(asc($value1), asc($value2)))

Msgbox(0,"",StringToBinary(BitXOR(asc($value1), asc($value2)),1))

Help is always appreciated Ant.. :)

Share this post


Link to post
Share on other sites

Hi Ant,

This worked for me (as in: gives the answer you specified)

Global $input = "GPGLL,5300.97914,N,00259.98174,E,125926,A"

Global $result = NMEA_Checksum($input)

MsgBox(0, "NMEA Checksummmer", " input: " & $input & @CR & "output: " & $result)


Func NMEA_Checksum($string)
    Local $ret = 0

    For $i = 1 To StringLen($string)
        $ret = BitXOR($ret, Asc(StringMid($string, $i, 1)) )
    Next

    Return Hex($ret, 2)
EndFunc

Not knowing WTF an 'NMEA checksum' is, I obviously can't be sure, so over to you ...

have fun,

whim

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Hi Ant,

This worked for me (as in: gives the answer you specified)

Global $input = "GPGLL,5300.97914,N,00259.98174,E,125926,A"

Global $result = NMEA_Checksum($input)

MsgBox(0, "NMEA Checksummmer", " input: " & $input & @CR & "output: " & $result)


Func NMEA_Checksum($string)
    Local $ret = 0

    For $i = 1 To StringLen($string)
        $ret = BitXOR($ret, Asc(StringMid($string, $i, 1)) )
    Next

    Return Hex($ret, 2)
EndFunc

Not knowing WTF an 'NMEA checksum' is, I obviously can't be sure, so over to you ...

have fun,

whim

Thanks whim that works on the example. I will check it further to make sure that it works on all NMEA sentence types. I would like to confirm that your help is very much appreciated.

WTF is a NMEA sentence? Well the short answer is its the standard protocol used by a GPS receiver to create a sentence from data streamed from a GPS Satellite. The checksum is calculated and added to each sentence and is used to confirm that the data contained within each sentence has not been corrupted.

Thanks again Ant.. :)

I have tested the code on the following NMEA sentences and it works perfectly

;$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47

;$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39

;$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

;$GPGLL,4916.45,N,12311.12,W,225444,A,*1D

Cheers Ant.. ;)

Edited by anixon

Share this post


Link to post
Share on other sites

hi anixon,

Try this, a standardized version with documentation that handles NMEA sentences and verifies/calculates checksums according to NMEA specifications :)

NMEAUDFv1.0.zip

If you find any bugs, or would like anything added tell me! ;)

Hope this helps,

-smartee

Share this post


Link to post
Share on other sites

hi anixon,

Try this, a standardized version with documentation that handles NMEA sentences and verifies/calculates checksums according to NMEA specifications :)

NMEAUDFv1.0.zip

If you find any bugs, or would like anything added tell me! ;)

Hope this helps,

-smartee

Happy to test your code if you post it here rather than a download. Ant:)

Share this post


Link to post
Share on other sites
;) Ok, I always found a download more convenient :) Zip has examples and helpfile, here's the bare function
; #FUNCTION# ====================================================================================================================
; Name...........: _NMEAChecksum
; Description ...: Takes a NMEA sentence, and returns its validity, or calculates its checksum.
; Syntax.........: _NMEAChecksum($sData [, $iVerify = Default])
; Parameters ....: $sData   - The NMEA sentence
;                  $iVerify - [optional] Numeric value that defines the function's behaviour as follows:
;                  |0 - Calculate checksum.
;                  |1 - Verify the sentence's validity by comparing the calculated and embedded checksums.
; Return values .: Success - The sentence's checksum, or True, depending on the value of $iVerify.
;                  Failure - False, Sets @Error:
;                  |0 - No error.
;                  |1 - Invalid input.
;                  |2 - Verify mode specified for data containing no embedded checksum.
; Author ........: smartee
; Modified.......:
; Remarks .......:
; Related .......: None
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func _NMEAChecksum($sData, $iVerify = Default)
    Local $vChecksum = 0
    If $iVerify = Default Then $iVerify = 0
    Local $avData = StringRegExp($sData, "^\$([^\*]*)(?:\*(\w{2}))?(?:\r\n)?$", 1)
    If @error Then Return SetError(1, 0, False)
    If $iVerify And UBound($avData) < 2 Then Return SetError(2, 0, False)
    For $i = 1 To StringLen($avData[0])
        If $i = 1 Then
            $vChecksum = Binary(StringMid($avData[0], $i, 1))
        Else
            $vChecksum = BitXOR($vChecksum, Binary(StringMid($avData[0], $i, 1)))
        EndIf
    Next
    $vChecksum = Hex($vChecksum, 2)
    If $iVerify Then Return SetError(Number(Not ($vChecksum = $avData[1])), 0, $vChecksum = $avData[1])
    Return SetError(0, 0, $vChecksum)
EndFunc   ;==>_NMEAChecksum

Share this post


Link to post
Share on other sites

:) Ok, I always found a download more convenient :mellow: Zip has examples and helpfile, here's the bare function

; #FUNCTION# ====================================================================================================================
; Name...........: _NMEAChecksum
; Description ...: Takes a NMEA sentence, and returns its validity, or calculates its checksum.
; Syntax.........: _NMEAChecksum($sData [, $iVerify = Default])
; Parameters ....: $sData   - The NMEA sentence
;                  $iVerify - [optional] Numeric value that defines the function's behaviour as follows:
;                  |0 - Calculate checksum.
;                  |1 - Verify the sentence's validity by comparing the calculated and embedded checksums.
; Return values .: Success - The sentence's checksum, or True, depending on the value of $iVerify.
;                  Failure - False, Sets @Error:
;                  |0 - No error.
;                  |1 - Invalid input.
;                  |2 - Verify mode specified for data containing no embedded checksum.
; Author ........: smartee
; Modified.......:
; Remarks .......:
; Related .......: None
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func _NMEAChecksum($sData, $iVerify = Default)
    Local $vChecksum = 0
    If $iVerify = Default Then $iVerify = 0
    Local $avData = StringRegExp($sData, "^\$([^\*]*)(?:\*(\w{2}))?(?:\r\n)?{:content:}quot;, 1)
    If @error Then Return SetError(1, 0, False)
    If $iVerify And UBound($avData) < 2 Then Return SetError(2, 0, False)
    For $i = 1 To StringLen($avData[0])
        If $i = 1 Then
            $vChecksum = Binary(StringMid($avData[0], $i, 1))
        Else
            $vChecksum = BitXOR($vChecksum, Binary(StringMid($avData[0], $i, 1)))
        EndIf
    Next
    $vChecksum = Hex($vChecksum, 2)
    If $iVerify Then Return SetError(Number(Not ($vChecksum = $avData[1])), 0, $vChecksum = $avData[1])
    Return SetError(0, 0, $vChecksum)
EndFunc   ;==>_NMEAChecksum

Hi smartee

Very nice including the elegant method you have used for stripping the $ and *.. checksum from the NMEA sentence. I probably would have approached it stringleft stringright and tested the value probably achieving the same result but to much code. What is interesting with coding is what sometimes appears to be the almost endless possibilities of achieving the same result.

Cheers Ant.. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0