ActiveState Code

Recipe 576789: NMEA sentence checksum


Calculates the checksum of an NMEA sentence (GPS data).

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python

import re

""" Calculate  the checksum for NMEA sentence 
    from a GPS device. An NMEA sentence comprises
    a number of comma separated fields followed by
    a checksum (in hex) after a "*". An example
    of NMEA sentence with a correct checksum (of
    0x76) is:
    
      GPGSV,3,3,10,26,37,134,00,29,25,136,00*76"
"""

def checksum(sentence):

    """ Remove any newlines """
    if re.search("\n$", sentence):
        sentence = sentence[:-1]

    nmeadata,cksum = re.split('\*', sentence)

    calc_cksum = 0
    for s in nmeadata:
        calc_cksum ^= ord(s)

    """ Return the nmeadata, the checksum from
        sentence, and the calculated checksum
    """
    return nmeadata,'0x'+cksum,hex(calc_cksum)

if __name__=='__main__':

    """ NMEA sentence with checksum error (3rd field 
       should be 10 not 20)
    """
    line = "GPGSV,3,3,20,26,37,134,00,29,25,136,00*76\n"

    """ Get NMEA data and checksums """

    data,cksum,calc_cksum = checksum(line)

    """ Verify checksum (will report checksum error) """ 
    if cksum != calc_cksum:
        print "Error in checksum for: %s" % (data)
        print "Checksums are %s and %s" % (cksum,calc_cksum)

Discussion

The checksum function is passed an NMEA sentence and returns the NMEA data, the checksum that was appended to the sentence when it was generated and the locally calculated checksum. A NMEA sentence may be read directly from a GPS device and therefore could contain a newline at the end. If so, this is removed. The example above verifies an NMEA sentence by comparing the two checksums returned by the checksum function. The example sentence has been corrupted, resulting in error message.

Comments

  1. 1. At 3:34 a.m. on 2 jun 2009, Benjamin said:

    first of all, you must love regular expressions ... for a simple split and strip ;)

    second, it's maybe better to keep the checksum a number not a string

    import operator
    def checksum(sentence):
        sentence = sentence.strip('\n')
        nmeadata,cksum = sentence.split('*', 1)
        calc_cksum = reduce(operator.xor, (ord(s) for s in nmeadata), 0)
    
        return nmeadata,int(cksum,16),calc_cksum
    
  2. 2. At 7:24 a.m. on 16 jun 2009, greg p said:

    I thought this might be useful to people so I made it into an online utility to calculate NMEA sentence checksums.

Sign in to comment