File: checksum.py

package info (click to toggle)
python-libais 0.17%2Bgit.20190917.master.e464cf8-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,828 kB
  • sloc: cpp: 56,058; python: 11,979; makefile: 537; sh: 466
file content (69 lines) | stat: -rwxr-xr-x 1,975 bytes parent folder | download | duplicates (4)
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""Utilities for working with NMEA strings."""

import re
import sys
import time

nmeaChecksumRegExStr = r"""\,[0-9]\*[0-9A-F][0-9A-F]"""
nmeaChecksumRE = re.compile(nmeaChecksumRegExStr)


def checksumStr(data):
    """Take a NMEA 0183 string and compute the checksum.
    @param data: NMEA message.  Leading ?/! and training checksum are optional
    @type data: str
    @return: hexidecimal value
    @rtype: str

    Checksum is calculated by xor'ing everything between ? or ! and the *

    >>> checksumStr("!AIVDM,1,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0*09")
    '09'
    >>> checksumStr("AIVDM,1,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0")
    '09'
    """

    # FIX: strip off new line at the end too
    if data[0]=='!' or data[0]=='?': data = data[1:]
    if data[-1]=='*': data = data[:-1]
    if data[-3]=='*': data = data[:-3]
    # FIX: rename sum to not shadown builting function
    checksum = 0
    for c in data:
      checksum = checksum ^ ord(c)
    sum_hex = "%x" % checksum
    if len(sum_hex) == 1:
      sum_hex = '0' + sum_hex
    return sum_hex.upper()


def isChecksumValid(nmeaStr, allowTailData=True):
    """Return True if the string checks out with the checksum.

    @param allowTailData: Permit handing of Coast Guard format with data after the checksum
    @param data: NMEA message.  Leading ?/! are optional
    @type data: str
    @return: True if the checksum matches
    @rtype: bool

    >>> isChecksumValid("!AIVDM,1,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0*09")
    True

    Corrupted:

    >>> isChecksumValid("!AIVDM,11,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0*09")
    False
    """

    if allowTailData:
        match = nmeaChecksumRE.search(nmeaStr)
        if not match:
            return False
        nmeaStr = nmeaStr[:match.end()]

    if nmeaStr[-3]!='*':
        return False  # Bad string without proper checksum.
    checksum=nmeaStr[-2:]
    if checksum.upper() == checksumStr(nmeaStr).upper():
        return True
    return False