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

Source Code for Module ais.ais_msg_1

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 4791 $'.split()[1] 
  4  __date__ = '$Date: 2006-12-20 $'.split()[1] 
  5  __author__ = 'xmlbinmsg' 
  6   
  7  __doc__=''' 
  8   
  9  Autogenerated python functions to serialize/deserialize binary messages. 
 10   
 11  Generated by: ./aisxmlbinmsg2py.py 
 12   
 13  Need to then wrap these functions with the outer AIS packet and then 
 14  convert the whole binary blob to a NMEA string.  Those functions are 
 15  not currently provided in this file. 
 16   
 17  serialize: python to ais binary 
 18  deserialize: ais binary to python 
 19   
 20  The generated code uses translators.py, binary.py, and aisstring.py 
 21  which should be packaged with the resulting files. 
 22   
 23   
 24  @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3 
 25  @requires: U{BitVector<http://cheeseshop.python.org/pypi/BitVector>} 
 26   
 27  @author: '''+__author__+''' 
 28  @version: ''' + __version__ +''' 
 29  @var __date__: Date of last svn commit 
 30  @undocumented: __version__ __author__ __doc__ myparser 
 31  @status: under development 
 32  @license: Generated code has no license 
 33  ''' 
 34   
 35  import sys 
 36  from decimal import Decimal 
 37  from BitVector import BitVector 
 38   
 39  import binary, aisstring 
 40   
 41  # FIX: check to see if these will be needed 
 42  TrueBV  = BitVector(bitstring="1") 
 43  "Why always rebuild the True bit?  This should speed things up a bunch" 
 44  FalseBV = BitVector(bitstring="0") 
 45  "Why always rebuild the False bit?  This should speed things up a bunch" 
 46   
 47   
48 -def encode(params, validate=False):
49 '''Create a position binary message payload to pack into an AIS Msg position. 50 51 Fields in params: 52 - MessageID(uint): AIS message number. Must be 1 (field automatically set to "1") 53 - RepeatIndicator(uint): Indicated how many times a message has been repeated 54 - UserID(uint): Unique ship identification number (MMSI) 55 - NavigationStatus(uint): What is the vessel doing 56 - ROT(int): RateOfTurn 57 - SOG(udecimal): Speed over ground 58 - PositionAccuracy(uint): Accuracy of positioning fixes 59 - Position_longitude(decimal): Location of the vessel East West location 60 - Position_latitude(decimal): Location of the vessel North South location 61 - COG(udecimal): Course over ground 62 - TrueHeading(uint): True heading (relative to true North) 63 - TimeStamp(uint): UTC second when the report was generated 64 - RegionalReserved(uint): Reserved for definition by a regional authority. (field automatically set to "0") 65 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 66 - RAIM(bool): Receiver autonomous integrity monitoring flag 67 - syncstate(uint): Sycronization state 68 - slotoffset(uint): In what slot will the next transmission occur. BROKEN 69 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 70 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 71 @rtype: BitVector 72 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 73 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 74 ''' 75 76 bvList = [] 77 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),6)) 78 if 'RepeatIndicator' in params: 79 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2)) 80 else: 81 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 82 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30)) 83 if 'NavigationStatus' in params: 84 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['NavigationStatus']),4)) 85 else: 86 bvList.append(binary.setBitVectorSize(BitVector(intVal=15),4)) 87 if 'ROT' in params: 88 bvList.append(binary.bvFromSignedInt(params['ROT'],8)) 89 else: 90 bvList.append(binary.bvFromSignedInt(-128,8)) 91 if 'SOG' in params: 92 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['SOG'])*Decimal('10')))),10)) 93 else: 94 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(1023)),10)) 95 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['PositionAccuracy']),1)) 96 if 'Position_longitude' in params: 97 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_longitude'])*Decimal('600000')),28)) 98 else: 99 bvList.append(binary.bvFromSignedInt(108600000,28)) 100 if 'Position_latitude' in params: 101 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_latitude'])*Decimal('600000')),27)) 102 else: 103 bvList.append(binary.bvFromSignedInt(54600000,27)) 104 if 'COG' in params: 105 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['COG'])*Decimal('10')))),12)) 106 else: 107 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(3600)),12)) 108 if 'TrueHeading' in params: 109 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['TrueHeading']),9)) 110 else: 111 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 112 if 'TimeStamp' in params: 113 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['TimeStamp']),6)) 114 else: 115 bvList.append(binary.setBitVectorSize(BitVector(intVal=60),6)) 116 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4)) 117 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),1)) 118 if params["RAIM"]: bvList.append(TrueBV) 119 else: bvList.append(FalseBV) 120 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['syncstate']),2)) 121 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['slotoffset']),14)) 122 123 return binary.joinBV(bvList)
124
125 -def decode(bv, validate=False):
126 '''Unpack a position message 127 128 Fields in params: 129 - MessageID(uint): AIS message number. Must be 1 (field automatically set to "1") 130 - RepeatIndicator(uint): Indicated how many times a message has been repeated 131 - UserID(uint): Unique ship identification number (MMSI) 132 - NavigationStatus(uint): What is the vessel doing 133 - ROT(int): RateOfTurn 134 - SOG(udecimal): Speed over ground 135 - PositionAccuracy(uint): Accuracy of positioning fixes 136 - Position_longitude(decimal): Location of the vessel East West location 137 - Position_latitude(decimal): Location of the vessel North South location 138 - COG(udecimal): Course over ground 139 - TrueHeading(uint): True heading (relative to true North) 140 - TimeStamp(uint): UTC second when the report was generated 141 - RegionalReserved(uint): Reserved for definition by a regional authority. (field automatically set to "0") 142 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 143 - RAIM(bool): Receiver autonomous integrity monitoring flag 144 - syncstate(uint): Sycronization state 145 - slotoffset(uint): In what slot will the next transmission occur. BROKEN 146 @type bv: BitVector 147 @param bv: Bits defining a message 148 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 149 @rtype: dict 150 @return: params 151 ''' 152 153 #Would be nice to check the bit count here.. 154 #if validate: 155 # assert (len(bv)==FIX: SOME NUMBER) 156 r = {} 157 r['MessageID']=1 158 r['RepeatIndicator']=int(bv[6:8]) 159 r['UserID']=int(bv[8:38]) 160 r['NavigationStatus']=int(bv[38:42]) 161 r['ROT']=binary.signedIntFromBV(bv[42:50]) 162 r['SOG']=Decimal(int(bv[50:60]))/Decimal('10') 163 r['PositionAccuracy']=int(bv[60:61]) 164 r['Position_longitude']=Decimal(binary.signedIntFromBV(bv[61:89]))/Decimal('600000') 165 r['Position_latitude']=Decimal(binary.signedIntFromBV(bv[89:116]))/Decimal('600000') 166 r['COG']=Decimal(int(bv[116:128]))/Decimal('10') 167 r['TrueHeading']=int(bv[128:137]) 168 r['TimeStamp']=int(bv[137:143]) 169 r['RegionalReserved']=0 170 r['Spare']=0 171 r['RAIM']=bool(int(bv[148:149])) 172 r['syncstate']=int(bv[149:151]) 173 r['slotoffset']=int(bv[151:165]) 174 return r
175
176 -def decodeMessageID(bv, validate=False):
177 return 1
178
179 -def decodeRepeatIndicator(bv, validate=False):
180 return int(bv[6:8])
181
182 -def decodeUserID(bv, validate=False):
183 return int(bv[8:38])
184
185 -def decodeNavigationStatus(bv, validate=False):
186 return int(bv[38:42])
187
188 -def decodeROT(bv, validate=False):
189 return binary.signedIntFromBV(bv[42:50])
190
191 -def decodeSOG(bv, validate=False):
192 return Decimal(int(bv[50:60]))/Decimal('10')
193
194 -def decodePositionAccuracy(bv, validate=False):
195 return int(bv[60:61])
196
197 -def decodePosition_longitude(bv, validate=False):
198 return Decimal(binary.signedIntFromBV(bv[61:89]))/Decimal('600000')
199
200 -def decodePosition_latitude(bv, validate=False):
201 return Decimal(binary.signedIntFromBV(bv[89:116]))/Decimal('600000')
202
203 -def decodeCOG(bv, validate=False):
204 return Decimal(int(bv[116:128]))/Decimal('10')
205
206 -def decodeTrueHeading(bv, validate=False):
207 return int(bv[128:137])
208
209 -def decodeTimeStamp(bv, validate=False):
210 return int(bv[137:143])
211
212 -def decodeRegionalReserved(bv, validate=False):
213 return 0
214
215 -def decodeSpare(bv, validate=False):
216 return 0
217
218 -def decodeRAIM(bv, validate=False):
219 return bool(int(bv[148:149]))
220
221 -def decodesyncstate(bv, validate=False):
222 return int(bv[149:151])
223
224 -def decodeslotoffset(bv, validate=False):
225 return int(bv[151:165])
226
227 -def printFields(params, out=sys.stdout, format='std'):
228 '''Print a position message to stdout. 229 230 Fields in params: 231 - MessageID(uint): AIS message number. Must be 1 (field automatically set to "1") 232 - RepeatIndicator(uint): Indicated how many times a message has been repeated 233 - UserID(uint): Unique ship identification number (MMSI) 234 - NavigationStatus(uint): What is the vessel doing 235 - ROT(int): RateOfTurn 236 - SOG(udecimal): Speed over ground 237 - PositionAccuracy(uint): Accuracy of positioning fixes 238 - Position_longitude(decimal): Location of the vessel East West location 239 - Position_latitude(decimal): Location of the vessel North South location 240 - COG(udecimal): Course over ground 241 - TrueHeading(uint): True heading (relative to true North) 242 - TimeStamp(uint): UTC second when the report was generated 243 - RegionalReserved(uint): Reserved for definition by a regional authority. (field automatically set to "0") 244 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 245 - RAIM(bool): Receiver autonomous integrity monitoring flag 246 - syncstate(uint): Sycronization state 247 - slotoffset(uint): In what slot will the next transmission occur. BROKEN 248 @param params: Dictionary of field names/values. 249 @param out: File like object to write to 250 @rtype: stdout 251 @return: text to out 252 ''' 253 254 if 'std'==format: 255 out.write("position:\n") 256 out.write(" MessageID: "+str(params['MessageID'])+"\n") 257 out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n") 258 out.write(" UserID: "+str(params['UserID'])+"\n") 259 out.write(" NavigationStatus: "+str(params['NavigationStatus'])+"\n") 260 out.write(" ROT: "+str(params['ROT'])+"\n") 261 out.write(" SOG: "+str(params['SOG'])+"\n") 262 out.write(" PositionAccuracy: "+str(params['PositionAccuracy'])+"\n") 263 out.write(" Position_longitude: "+str(params['Position_longitude'])+"\n") 264 out.write(" Position_latitude: "+str(params['Position_latitude'])+"\n") 265 out.write(" COG: "+str(params['COG'])+"\n") 266 out.write(" TrueHeading: "+str(params['TrueHeading'])+"\n") 267 out.write(" TimeStamp: "+str(params['TimeStamp'])+"\n") 268 out.write(" RegionalReserved: "+str(params['RegionalReserved'])+"\n") 269 out.write(" Spare: "+str(params['Spare'])+"\n") 270 out.write(" RAIM: "+str(params['RAIM'])+"\n") 271 out.write(" syncstate: "+str(params['syncstate'])+"\n") 272 out.write(" slotoffset: "+str(params['slotoffset'])+"\n") 273 274 return # Nothing to return
275 276 277 278 ###################################################################### 279 # UNIT TESTING 280 ###################################################################### 281 import unittest
282 -def testParams():
283 '''Return a params file base on the testvalue tags. 284 @rtype: dict 285 @return: params based on testvalue tags 286 ''' 287 params = {} 288 params['MessageID'] = 1 289 params['RepeatIndicator'] = 1 290 params['UserID'] = 1193046 291 params['NavigationStatus'] = 3 292 params['ROT'] = -2 293 params['SOG'] = Decimal('101.9') 294 params['PositionAccuracy'] = 1 295 params['Position_longitude'] = Decimal('-122.16328055555556') 296 params['Position_latitude'] = Decimal('37.424458333333334') 297 params['COG'] = Decimal('34.5') 298 params['TrueHeading'] = 41 299 params['TimeStamp'] = 35 300 params['RegionalReserved'] = 0 301 params['Spare'] = 0 302 params['RAIM'] = False 303 params['syncstate'] = 2 304 params['slotoffset'] = 1221 305 306 return params
307
308 -class Testposition(unittest.TestCase):
309 '''Use testvalue tag text from each type to build test case the position message'''
310 - def testEncodeDecode(self):
311 312 params = testParams() 313 bits = encode(params) 314 r = decode(bits) 315 316 # Check that each parameter came through ok. 317 self.failUnlessEqual(r['MessageID'],params['MessageID']) 318 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 319 self.failUnlessEqual(r['UserID'],params['UserID']) 320 self.failUnlessEqual(r['NavigationStatus'],params['NavigationStatus']) 321 self.failUnlessEqual(r['ROT'],params['ROT']) 322 self.failUnlessAlmostEqual(r['SOG'],params['SOG'],1) 323 self.failUnlessEqual(r['PositionAccuracy'],params['PositionAccuracy']) 324 self.failUnlessAlmostEqual(r['Position_longitude'],params['Position_longitude'],5) 325 self.failUnlessAlmostEqual(r['Position_latitude'],params['Position_latitude'],5) 326 self.failUnlessAlmostEqual(r['COG'],params['COG'],7) 327 self.failUnlessEqual(r['TrueHeading'],params['TrueHeading']) 328 self.failUnlessEqual(r['TimeStamp'],params['TimeStamp']) 329 self.failUnlessEqual(r['RegionalReserved'],params['RegionalReserved']) 330 self.failUnlessEqual(r['Spare'],params['Spare']) 331 self.failUnlessEqual(r['RAIM'],params['RAIM']) 332 self.failUnlessEqual(r['syncstate'],params['syncstate']) 333 self.failUnlessEqual(r['slotoffset'],params['slotoffset'])
334 335 ############################################################ 336 if __name__=='__main__': 337 338 from optparse import OptionParser 339 myparser = OptionParser(usage="%prog [options]", 340 version="%prog "+__version__) 341 342 #sys.exit('EARLY EXIT - FIX: remove') 343 myparser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 344 help='run the documentation tests') 345 myparser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 346 help='run the unit tests') 347 myparser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 348 help='Make the test output verbose') 349 350 351 myparser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 352 help='decode a "position" AIS message') 353 myparser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 354 help='encode a "position" AIS message') 355 356 357 # FIX: remove nmea from binary messages. No way to build the whole packet? 358 # FIX: or build the surrounding msg 8 for a broadcast? 359 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 360 myparser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 361 ,default='nmeapayload' 362 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]') 363 364 myparser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0 365 ,help='Field parameter value [default: %default]' 366 ,metavar='uint' 367 ,type='int' 368 ) 369 myparser.add_option('--UserID-field', dest='UserIDField' 370 ,help='Field parameter value [default: %default]' 371 ,metavar='uint' 372 ,type='int' 373 ) 374 myparser.add_option('--NavigationStatus-field', dest='NavigationStatusField',default=15 375 ,help='Field parameter value [default: %default]' 376 ,metavar='uint' 377 ,type='int' 378 ) 379 myparser.add_option('--ROT-field', dest='ROTField',default=-128 380 ,help='Field parameter value [default: %default]' 381 ,metavar='int' 382 ,type='int' 383 ) 384 myparser.add_option('--SOG-field', dest='SOGField',default=Decimal('102.3') 385 ,help='Field parameter value [default: %default]' 386 ,metavar='udecimal' 387 ,type='string' 388 ) 389 myparser.add_option('--PositionAccuracy-field', dest='PositionAccuracyField' 390 ,help='Field parameter value [default: %default]' 391 ,metavar='uint' 392 ,type='int' 393 ) 394 myparser.add_option('--Position_longitude-field', dest='Position_longitudeField',default=Decimal('181') 395 ,help='Field parameter value [default: %default]' 396 ,metavar='decimal' 397 ,type='string' 398 ) 399 myparser.add_option('--Position_latitude-field', dest='Position_latitudeField',default=Decimal('91') 400 ,help='Field parameter value [default: %default]' 401 ,metavar='decimal' 402 ,type='string' 403 ) 404 myparser.add_option('--COG-field', dest='COGField',default=Decimal('360') 405 ,help='Field parameter value [default: %default]' 406 ,metavar='udecimal' 407 ,type='string' 408 ) 409 myparser.add_option('--TrueHeading-field', dest='TrueHeadingField',default=511 410 ,help='Field parameter value [default: %default]' 411 ,metavar='uint' 412 ,type='int' 413 ) 414 myparser.add_option('--TimeStamp-field', dest='TimeStampField',default=60 415 ,help='Field parameter value [default: %default]' 416 ,metavar='uint' 417 ,type='int' 418 ) 419 myparser.add_option('--RAIM-field', dest='RAIMField' 420 ,help='Field parameter value [default: %default]' 421 ,metavar='bool' 422 ,type='int' 423 ) 424 myparser.add_option('--syncstate-field', dest='syncstateField' 425 ,help='Field parameter value [default: %default]' 426 ,metavar='uint' 427 ,type='int' 428 ) 429 myparser.add_option('--slotoffset-field', dest='slotoffsetField' 430 ,help='Field parameter value [default: %default]' 431 ,metavar='uint' 432 ,type='int' 433 ) 434 435 (options,args) = myparser.parse_args() 436 success=True 437 438 if options.doctest: 439 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 440 sys.argv= [sys.argv[0]] 441 if options.verbose: sys.argv.append('-v') 442 import doctest 443 numfail,numtests=doctest.testmod() 444 if numfail==0: print 'ok' 445 else: 446 print 'FAILED' 447 success=False 448 449 if not success: 450 sys.exit('Something Failed') 451 452 del success # Hide success from epydoc 453 454 if options.unittest: 455 sys.argv = [sys.argv[0]] 456 if options.verbose: sys.argv.append('-v') 457 unittest.main() 458 459 if options.doEncode: 460 # First make sure all non required options are specified 461 if None==options.RepeatIndicatorField: myparser.error("missing value for RepeatIndicatorField") 462 if None==options.UserIDField: myparser.error("missing value for UserIDField") 463 if None==options.NavigationStatusField: myparser.error("missing value for NavigationStatusField") 464 if None==options.ROTField: myparser.error("missing value for ROTField") 465 if None==options.SOGField: myparser.error("missing value for SOGField") 466 if None==options.PositionAccuracyField: myparser.error("missing value for PositionAccuracyField") 467 if None==options.Position_longitudeField: myparser.error("missing value for Position_longitudeField") 468 if None==options.Position_latitudeField: myparser.error("missing value for Position_latitudeField") 469 if None==options.COGField: myparser.error("missing value for COGField") 470 if None==options.TrueHeadingField: myparser.error("missing value for TrueHeadingField") 471 if None==options.TimeStampField: myparser.error("missing value for TimeStampField") 472 if None==options.RAIMField: myparser.error("missing value for RAIMField") 473 if None==options.syncstateField: myparser.error("missing value for syncstateField") 474 if None==options.slotoffsetField: myparser.error("missing value for slotoffsetField") 475 msgDict={ 476 'MessageID': '1', 477 'RepeatIndicator': options.RepeatIndicatorField, 478 'UserID': options.UserIDField, 479 'NavigationStatus': options.NavigationStatusField, 480 'ROT': options.ROTField, 481 'SOG': options.SOGField, 482 'PositionAccuracy': options.PositionAccuracyField, 483 'Position_longitude': options.Position_longitudeField, 484 'Position_latitude': options.Position_latitudeField, 485 'COG': options.COGField, 486 'TrueHeading': options.TrueHeadingField, 487 'TimeStamp': options.TimeStampField, 488 'RegionalReserved': '0', 489 'Spare': '0', 490 'RAIM': options.RAIMField, 491 'syncstate': options.syncstateField, 492 'slotoffset': options.slotoffsetField, 493 } 494 bits = encode(msgDict) 495 if 'binary'==options.ioType: print str(bits) 496 elif 'nmeapayload'==options.ioType: 497 print "bitLen",len(bits) 498 bitLen=len(bits) 499 if bitLen%6!=0: 500 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 501 print "result:",binary.bitvectoais6(bits)[0] 502 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 503 else: sys.exit('ERROR: unknown ioType. Help!') 504 505 if options.doDecode: 506 for msg in args: 507 if 'binary'==options.ioType: 508 bv = BitVector(bitstring=msg) 509 printFields(decode(bv)) 510 elif 'nmeapayload'==options.ioType: 511 bv = binary.ais6tobitvec(msg) 512 printFields(decode(bv)) 513 elif 'nmea'==options.ioType: 514 bv = binary.ais6tobitvec(msg.split(',')[5]) 515 printFields(decode(bv)) 516 else: sys.exit('ERROR: unknown ioType. Help!') 517