Package ais :: Module nmea
[hide private]
[frames] | no frames]

Module nmea

source code

Handle creation and extraction of NMEA strings. Maybe need a separate VDM class like ais-py?


Requires:

Author: Kurt Schwehr

Version: 5698

Copyright: 2006

Since: 2006-Sep-26 FIX: replace with the file creation date

Status: under development

Organization: CCOM - FIX: if not CCOM change the name and link

License: GPL v2

Note: This package does not respence the maximum number of characters per line that is required in the NMEA specification.

Date: 2007-03-03

Functions [hide private]
str
checksumStr(data, verbose=False)
Take a NMEA 0183 string and compute the checksum.
source code
bool
isChecksumValid(nmeaStr, allowTailData=True, verbose=False)
Return True if the string checks out with the checksum
source code
 
buildNmea(aisBits, prefix='!', serviceType='AI', msgType='VDM', channelSeq=None, channel='A')
Create one long oversized nmea string for the bits
source code
str
cabEncode(TransA=False, TransB=False, Restart=False, Reset=False, prefix='AI')
CAB - Control AIS Base Station.
source code
dict
cabDecode(msg, validate=True)
Note that ZZ is probably not valid in this next example
source code
 
verQuery(prefix='xx', appendEOL=True)
Ask for the version string from a base station
source code
 
acaDecode(msg, validate=True)
Decode AIS Regional Channel Assignment Message.
source code
 
cbmDecode(msg, validate=True)
Decode Configure Base Station Message Broadcast Reporting Rates message.
source code
 
dlmDecode(msg, validate=True)
Decode Data Link Management slot allocation for Base Station nmea message
source code
str
bbmEncode(totSent, sentNum, seqId, aisChan, msgId, data, numFillBits, prefix='xx', appendEOL=True, validate=True)
Encode a binary broadcast message.
source code
dict
bbmDecode(msg, validate=True)
Decode a binary broadcast message NMEA string
source code
Variables [hide private]
  EOL = '\r\n'
DOS style end-of-line (<cr><lf>) for talking to AIS base stations
  nmeaChecksumRegExStr = '\\*[0-9A-F][0-9A-F]'
  nmeaChecksumRE = re.compile(r'\*[0-9A-F][0-9A-F]')
  txrxLUT = {0: 'tx a and b, rx on a and b', 1: 'tx a, rx a and ...
Transmit and Received modes.
  acaInfoSrcLUT = {'A': 'ITU-R M.1371 message 22: addressed mess...
  ownershipLUT = {'C': 'clear reservation', 'L': 'local', 'R': '...
Function Details [hide private]

checksumStr(data, verbose=False)

source code 

Take a NMEA 0183 string and compute the checksum.

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'
>>> checksumStr('$AIACA,0,,,,,,,,,5,2087,0,2088,0,0,0,I,1,000000*15')
'15'
This is an example I made up
>>> checksumStr('$xxCAB,1,1,1,1*5D')
'40'
Parameters:
  • data (str) - NMEA message. Leading ?/! and training checksum are optional
Returns: str
hexidecimal value

isChecksumValid(nmeaStr, allowTailData=True, verbose=False)

source code 
Return True if the string checks out with the checksum
>>> isChecksumValid("!AIVDM,1,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0*09")
True
Corrupted:
>>> isChecksumValid("!AIVDM,11,1,,B,35MsUdPOh8JwI:0HUwquiIFH21>i,0*09")
False
>>> isChecksumValid('$AIACA,0,,,,,,,,,5,2087,0,2088,0,0,0,I,1,000000*15')
True
Parameters:
  • allowTailData - Permit handing of Coast Guard format with data after the checksum
  • nmeaStr (str) - NMEA message. Leading ?/! are optional
Returns: bool
True if the checksum matches

buildNmea(aisBits, prefix='!', serviceType='AI', msgType='VDM', channelSeq=None, channel='A')

source code 
Create one long oversized nmea string for the bits
Parameters:
  • aisBits (BitVector) - message payload
  • prefix - '!' or '$' what is the difference?
  • serviceType - 'can this be anything other than AI?
  • msgType - VDM. Should not be VDO (own ship)
  • channelSeq - 1-9 or None
  • channel - AIS channel A or B

To Do: sync names of prefix and serviceType to NMEA spec.

See Also: reference the appropriate spec documents for all this stuff.

cabEncode(TransA=False, TransB=False, Restart=False, Reset=False, prefix='AI')

source code 
CAB - Control AIS Base Station. Defaults to a safe state with everything shutdown. 62320-1/CDV, 80/427/CDV, Page 77, A.1.7
>>> cabEncode()
'$AICAB,0,0,,*48'

Note that xx is probably not valid in this next example, but it is used by L3

Made up example:
>>> cabEncode(True,True,True,True,prefix='xx')
'$xxCAB,1,1,1,1*40'
Parameters:
  • TransA (bool) - Transmissions enabled on channel A
  • TransB (bool) - Transmissions enabled on channel B
  • Restart (bool) - If true, command AIS Base station to restart operations in last known configuration
  • Reset (bool) -
  • prefix (str) - string to put between the $ and CAB
Returns: str
A CAB NMEA string

cabDecode(msg, validate=True)

source code 
>>> cabDecode('$AICAB,,,,*48')
{'Reset': False, 'nmeaPrefix': 'AI', 'nmeaCmd': 'CAB', 'TransB': False, 'TransA': False, 'Restart': False}
Note that ZZ is probably not valid in this next example
>>> cabDecode('$ZZCAB,1,1,1,1*40')
{'Reset': False, 'nmeaPrefix': 'ZZ', 'nmeaCmd': 'CAB', 'TransB': True, 'TransA': True, 'Restart': True}
Parameters:
  • msg (str) - NMEA string of a CAB message
  • validate (bool) - Set to False to turn off validation for speed.
Returns: dict
lookup table of key/values

To Do (FIX): throw an exception if not valid

To Do: How do I make stable doctests with dictionary returns

acaDecode(msg, validate=True)

source code 

Decode AIS Regional Channel Assignment Message. See 61993-2 Page 87.

This is an example of an unconfigured base station, plus there is a USCG timestamp at the end.
>>> acaDecode('$AIACA,0,,,,,,,,,5,2087,0,2088,0,0,0,I,1,000000*15,1172786646.1')
{'inuse': '1', 'north': None, 'txrxMode': '0', 'power': '0', 'nmeaPrefix': 'AI', 'timeinuse': '000000', 'seqnum': '0', 'chanBbandwidth': '0', 'nmeaCmd': 'ACA', 'chanAbandwidth': '0', 'west': None, 'transitionSize': '5', 'infosrc': 'I', 'east': None, 'chanA': '2087', 'south': None, 'chanB': '2088'}

To Do: get a complete example to decode as a doctest

cbmDecode(msg, validate=True)

source code 
Decode Configure Base Station Message Broadcast Reporting Rates message.
>>> cbmDecode('$AICBM,61,76,35,2,60,999,100,999,52,999,1,60,999,100,999*55,1172787005.46')
{'msg17chanAnumslots': '1', 'nmeaPrefix': 'AI', 'msg4slot': '61', 'msg17chanAslotinterval': '999', 'nmeaCmd': 'CBM', 'msg20chanAslotinterval': '999', 'msg20chanAstartslot': '60', 'msg17chanAstartslot': '52', 'msg22chanAslotinterval': '999', 'msg22chanAstartslot': '100'}

See Also: 62320-1/CDV 80/427/CDV page 78, A.1.8

dlmDecode(msg, validate=True)

source code 
Decode Data Link Management slot allocation for Base Station nmea message
>>> dlmDecode ('$AIDLM,0,A,L,0,2,7,540,L,4,1,7,250,L,2511,1,7,0,,,,,*40,1172787005.5')
{'nmeaPrefix': 'AI', 'timeout3': '7', 'timeout2': '7', 'timeout1': '7', 'timeout4': '', 'startslot2': '4', 'startslot3': '2511', 'incr4': '*40', 'incr3': '0', 'incr2': '250', 'incr1': '540', 'aisChannel': 'A', 'seqNum': '0', 'startslot1': '0', 'startslot4': '', 'nmeaCmd': 'DLM', 'ownership4': '', 'ownership3': 'L', 'ownership2': 'L', 'ownership1': 'L', 'numslots4': '', 'numslots1': '2', 'numslots2': '1', 'numslots3': '1'}

See Also: 62320-1/CDV 80/427/CDV page 79, A.1.9

bbmEncode(totSent, sentNum, seqId, aisChan, msgId, data, numFillBits, prefix='xx', appendEOL=True, validate=True)

source code 

Encode a binary broadcast message.

I have no idea what this message says...

!AIVDM,1,1,,A,85NqMF1Kf=Vsdt`l;0bnfFjd<uQeT2p<vmIRTB=mM5mtIT;sUL2t,0*54,rs003669982,1172918061

>>> bbmEncode(1,1,0,3,8,'Fs[Ifs?:=2h:ec]dc3?HKI0f3?eFHa4[MGAMO6I2vqG0g',4)
'!xxBBM,1,1,0,3,8,Fs[Ifs?:=2h:ec]dc3?HKI0f3?eFHa4[MGAMO6I2vqG0g,4*32'
Parameters:
  • totSent (int) - Total number of sentences needed for the message (1-9)
  • sentNum (int) - Which sentence is this in the series (1-9)
  • seqId (int) - need to increment this for each message??!?!? (0-9) Linked to ABK
  • aisChan (str) - AIS channel to use to send the message
    1. No channel preference
    2. AIS Channel A
    3. AIS Channel B
    4. Broadcast on both A and B
  • msgId (int) - AIS message 8 (binary broadcast message) or 14 (safety related broadcast)
  • data - Content of the binary data. First sentence must be 58 characters or less. The rest can be up to 60 characters.
  • numFillBits (int) - Number of bits of padding in the last character of the data (0-5)
Returns: str
nmea string

To Do: put in some doc tests with know messages and what would be received as the VDM message(s)

See Also: IEC-PAS 61162-100 80/330/PAS, Page 19

bbmDecode(msg, validate=True)

source code 
Decode a binary broadcast message NMEA string
>>> bbmDecode('!xxBBM,1,1,0,3,8,Fs[Ifs?:=2h:ec]dc3?HKI0f3?eFHa4[MGAMO6I2vqG0g,4*32')
{'numFillBits': '4', 'nmeaPrefix': 'xx', 'msgId': '8', 'aisChan': '3', 'data': 'Fs[Ifs?:=2h:ec]dc3?HKI0f3?eFHa4[MGAMO6I2vqG0g', 'seqId': '0', 'nmeaCmd': 'BBM', 'sentNum': '1', 'totSent': '1'}
Parameters:
  • msg (str) - NMEA string of a CAB message
  • validate (bool) - Set to False to turn off validation for speed.
Returns: dict
lookup table of key/values
To Do:
  • make the doctest stable
  • doctests with known messages

See Also: IEC-PAS 61162-100 80/330/PAS, Page 19


Variables Details [hide private]

txrxLUT

Transmit and Received modes. See Page 88 61993-2 and XXXX???
Value:
{0: 'tx a and b, rx on a and b',
 1: 'tx a, rx a and b',
 2: 'tx b, rx a and b',
 3: 'no tx, rx a and b',
 4: 'no tx, rx a',
 5: 'no tx, no rx'}

acaInfoSrcLUT

Value:
{'A': 'ITU-R M.1371 message 22: addressed message',
 'B': 'ITU-R M.1371 message 22: broadcast message',
 'C': 'IEC 61162-1 AIS Channel Assignment setence',
 'D': 'DSC Channel 70 telecommand',
 'M': 'Operator manual input'}

ownershipLUT

Value:
{'C': 'clear reservation', 'L': 'local', 'R': 'remote'}