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

Source Code for Module ais.whalenotice

   1  #!/usr/bin/env python 
   2   
   3  __version__ = '$Revision: 4791 $'.split()[1] 
   4  __date__ = '$Date: 2007-06-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__ parser 
  31  @status: under development 
  32  @license: Generated code has no license 
  33  @todo: FIX: put in a description of the message here with fields and types. 
  34  ''' 
  35   
  36  import sys 
  37  from decimal import Decimal 
  38  from BitVector import BitVector 
  39   
  40  import binary, aisstring 
  41   
  42  # FIX: check to see if these will be needed 
  43  TrueBV  = BitVector(bitstring="1") 
  44  "Why always rebuild the True bit?  This should speed things up a bunch" 
  45  FalseBV = BitVector(bitstring="0") 
  46  "Why always rebuild the False bit?  This should speed things up a bunch" 
  47   
  48   
  49  fieldList = ( 
  50          'MessageID', 
  51          'RepeatIndicator', 
  52          'UserID', 
  53          'Spare', 
  54          'dac', 
  55          'fid', 
  56          'efid', 
  57          'month', 
  58          'day', 
  59          'hour', 
  60          'min', 
  61          'sec', 
  62          'stationid', 
  63          'longitude', 
  64          'latitude', 
  65          'timetoexpire', 
  66          'radius', 
  67          'heading', 
  68          'numWhales', 
  69  ) 
  70   
  71  fieldListPostgres = ( 
  72          'MessageID', 
  73          'RepeatIndicator', 
  74          'UserID', 
  75          'Spare', 
  76          'dac', 
  77          'fid', 
  78          'efid', 
  79          'month', 
  80          'day', 
  81          'hour', 
  82          'min', 
  83          'sec', 
  84          'stationid', 
  85          'whale',        # PostGIS data type 
  86          'timetoexpire', 
  87          'radius', 
  88          'heading', 
  89          'numWhales', 
  90  ) 
  91   
  92  toPgFields = { 
  93          'longitude':'whale', 
  94          'latitude':'whale', 
  95  } 
  96  ''' 
  97  Go to the Postgis field names from the straight field name 
  98  ''' 
  99   
 100  fromPgFields = { 
 101          'whale':('longitude','latitude',), 
 102  } 
 103  ''' 
 104  Go from the Postgis field names to the straight field name 
 105  ''' 
 106   
 107  pgTypes = { 
 108          'whale':'POINT', 
 109  } 
 110  ''' 
 111  Lookup table for each postgis field name to get its type. 
 112  ''' 
 113   
114 -def encode(params, validate=False):
115 '''Create a whalenotice binary message payload to pack into an AIS Msg whalenotice. 116 117 Fields in params: 118 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 119 - RepeatIndicator(uint): Indicated how many times a message has been repeated 120 - UserID(uint): Unique ship identification number (MMSI) 121 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 122 - dac(uint): Designated Area Code (field automatically set to "366") 123 - fid(uint): Functional Identifier (field automatically set to "1") 124 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 125 - month(uint): Time whale was last recorded. month 1..12 126 - day(uint): Time whale was last recorded. day of the month 1..31 127 - hour(uint): Time whale was last recorded. UTC hours 0..23 128 - min(uint): Time whale was last recorded. minutes 129 - sec(uint): Time whale was last recorded. seconds 130 - stationid(aisstr6): Character identifier of the station. Usually a number. 131 - longitude(decimal): Where was the whale located. Center of the restricted speed zone. East West location 132 - latitude(decimal): Where was the whale located. Center of the restricted speed zone. North South location 133 - timetoexpire(uint): Seconds from the time tag until this notice expires 134 - radius(uint): Distance of the required exclusion/slow zone 135 - heading(uint): Direction the whale is traveling if known 136 - numWhales(uint): Number of whales detected 137 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 138 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 139 @rtype: BitVector 140 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 141 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 142 ''' 143 144 bvList = [] 145 bvList.append(binary.setBitVectorSize(BitVector(intVal=8),6)) 146 if 'RepeatIndicator' in params: 147 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2)) 148 else: 149 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 150 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30)) 151 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 152 bvList.append(binary.setBitVectorSize(BitVector(intVal=366),10)) 153 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),6)) 154 bvList.append(binary.setBitVectorSize(BitVector(intVal=2),12)) 155 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['month']),4)) 156 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['day']),5)) 157 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['hour']),5)) 158 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['min']),6)) 159 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['sec']),6)) 160 if 'stationid' in params: 161 bvList.append(aisstring.encode(params['stationid'],42)) 162 else: 163 bvList.append(aisstring.encode('@@@@@@@',42)) 164 if 'longitude' in params: 165 bvList.append(binary.bvFromSignedInt(int(Decimal(params['longitude'])*Decimal('600000')),28)) 166 else: 167 bvList.append(binary.bvFromSignedInt(108600000,28)) 168 if 'latitude' in params: 169 bvList.append(binary.bvFromSignedInt(int(Decimal(params['latitude'])*Decimal('600000')),27)) 170 else: 171 bvList.append(binary.bvFromSignedInt(54600000,27)) 172 if 'timetoexpire' in params: 173 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetoexpire']),16)) 174 else: 175 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),16)) 176 if 'radius' in params: 177 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['radius']),16)) 178 else: 179 bvList.append(binary.setBitVectorSize(BitVector(intVal=65534),16)) 180 if 'heading' in params: 181 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['heading']),9)) 182 else: 183 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 184 if 'numWhales' in params: 185 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['numWhales']),8)) 186 else: 187 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8)) 188 189 return binary.joinBV(bvList)
190
191 -def decode(bv, validate=False):
192 '''Unpack a whalenotice message 193 194 Fields in params: 195 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 196 - RepeatIndicator(uint): Indicated how many times a message has been repeated 197 - UserID(uint): Unique ship identification number (MMSI) 198 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 199 - dac(uint): Designated Area Code (field automatically set to "366") 200 - fid(uint): Functional Identifier (field automatically set to "1") 201 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 202 - month(uint): Time whale was last recorded. month 1..12 203 - day(uint): Time whale was last recorded. day of the month 1..31 204 - hour(uint): Time whale was last recorded. UTC hours 0..23 205 - min(uint): Time whale was last recorded. minutes 206 - sec(uint): Time whale was last recorded. seconds 207 - stationid(aisstr6): Character identifier of the station. Usually a number. 208 - longitude(decimal): Where was the whale located. Center of the restricted speed zone. East West location 209 - latitude(decimal): Where was the whale located. Center of the restricted speed zone. North South location 210 - timetoexpire(uint): Seconds from the time tag until this notice expires 211 - radius(uint): Distance of the required exclusion/slow zone 212 - heading(uint): Direction the whale is traveling if known 213 - numWhales(uint): Number of whales detected 214 @type bv: BitVector 215 @param bv: Bits defining a message 216 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 217 @rtype: dict 218 @return: params 219 ''' 220 221 #Would be nice to check the bit count here.. 222 #if validate: 223 # assert (len(bv)==FIX: SOME NUMBER) 224 r = {} 225 r['MessageID']=8 226 r['RepeatIndicator']=int(bv[6:8]) 227 r['UserID']=int(bv[8:38]) 228 r['Spare']=0 229 r['dac']=366 230 r['fid']=1 231 r['efid']=2 232 r['month']=int(bv[68:72]) 233 r['day']=int(bv[72:77]) 234 r['hour']=int(bv[77:82]) 235 r['min']=int(bv[82:88]) 236 r['sec']=int(bv[88:94]) 237 r['stationid']=aisstring.decode(bv[94:136]) 238 r['longitude']=Decimal(binary.signedIntFromBV(bv[136:164]))/Decimal('600000') 239 r['latitude']=Decimal(binary.signedIntFromBV(bv[164:191]))/Decimal('600000') 240 r['timetoexpire']=int(bv[191:207]) 241 r['radius']=int(bv[207:223]) 242 r['heading']=int(bv[223:232]) 243 r['numWhales']=int(bv[232:240]) 244 return r
245
246 -def decodeMessageID(bv, validate=False):
247 return 8
248
249 -def decodeRepeatIndicator(bv, validate=False):
250 return int(bv[6:8])
251
252 -def decodeUserID(bv, validate=False):
253 return int(bv[8:38])
254
255 -def decodeSpare(bv, validate=False):
256 return 0
257
258 -def decodedac(bv, validate=False):
259 return 366
260
261 -def decodefid(bv, validate=False):
262 return 1
263
264 -def decodeefid(bv, validate=False):
265 return 2
266
267 -def decodemonth(bv, validate=False):
268 return int(bv[68:72])
269
270 -def decodeday(bv, validate=False):
271 return int(bv[72:77])
272
273 -def decodehour(bv, validate=False):
274 return int(bv[77:82])
275
276 -def decodemin(bv, validate=False):
277 return int(bv[82:88])
278
279 -def decodesec(bv, validate=False):
280 return int(bv[88:94])
281
282 -def decodestationid(bv, validate=False):
283 return aisstring.decode(bv[94:136])
284
285 -def decodelongitude(bv, validate=False):
286 return Decimal(binary.signedIntFromBV(bv[136:164]))/Decimal('600000')
287
288 -def decodelatitude(bv, validate=False):
289 return Decimal(binary.signedIntFromBV(bv[164:191]))/Decimal('600000')
290
291 -def decodetimetoexpire(bv, validate=False):
292 return int(bv[191:207])
293
294 -def decoderadius(bv, validate=False):
295 return int(bv[207:223])
296
297 -def decodeheading(bv, validate=False):
298 return int(bv[223:232])
299
300 -def decodenumWhales(bv, validate=False):
301 return int(bv[232:240])
302 303
304 -def printHtml(params, out=sys.stdout):
305 out.write("<h3>whalenotice<h3>\n") 306 out.write("<table border=\"1\">\n") 307 out.write("<tr bgcolor=\"orange\">\n") 308 out.write("<th align=\"left\">Field Name</th>\n") 309 out.write("<th align=\"left\">Type</th>\n") 310 out.write("<th align=\"left\">Value</th>\n") 311 out.write("<th align=\"left\">Value in Lookup Table</th>\n") 312 out.write("<th align=\"left\">Units</th>\n") 313 out.write("\n") 314 out.write("<tr>\n") 315 out.write("<td>MessageID</td>\n") 316 out.write("<td>uint</td>\n") 317 if 'MessageID' in params: 318 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 319 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 320 out.write("</tr>\n") 321 out.write("\n") 322 out.write("<tr>\n") 323 out.write("<td>RepeatIndicator</td>\n") 324 out.write("<td>uint</td>\n") 325 if 'RepeatIndicator' in params: 326 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n") 327 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut: 328 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>") 329 else: 330 out.write("<td><i>Missing LUT entry</i></td>") 331 out.write("</tr>\n") 332 out.write("\n") 333 out.write("<tr>\n") 334 out.write("<td>UserID</td>\n") 335 out.write("<td>uint</td>\n") 336 if 'UserID' in params: 337 out.write(" <td>"+str(params['UserID'])+"</td>\n") 338 out.write(" <td>"+str(params['UserID'])+"</td>\n") 339 out.write("</tr>\n") 340 out.write("\n") 341 out.write("<tr>\n") 342 out.write("<td>Spare</td>\n") 343 out.write("<td>uint</td>\n") 344 if 'Spare' in params: 345 out.write(" <td>"+str(params['Spare'])+"</td>\n") 346 out.write(" <td>"+str(params['Spare'])+"</td>\n") 347 out.write("</tr>\n") 348 out.write("\n") 349 out.write("<tr>\n") 350 out.write("<td>dac</td>\n") 351 out.write("<td>uint</td>\n") 352 if 'dac' in params: 353 out.write(" <td>"+str(params['dac'])+"</td>\n") 354 out.write(" <td>"+str(params['dac'])+"</td>\n") 355 out.write("</tr>\n") 356 out.write("\n") 357 out.write("<tr>\n") 358 out.write("<td>fid</td>\n") 359 out.write("<td>uint</td>\n") 360 if 'fid' in params: 361 out.write(" <td>"+str(params['fid'])+"</td>\n") 362 out.write(" <td>"+str(params['fid'])+"</td>\n") 363 out.write("</tr>\n") 364 out.write("\n") 365 out.write("<tr>\n") 366 out.write("<td>efid</td>\n") 367 out.write("<td>uint</td>\n") 368 if 'efid' in params: 369 out.write(" <td>"+str(params['efid'])+"</td>\n") 370 out.write(" <td>"+str(params['efid'])+"</td>\n") 371 out.write("</tr>\n") 372 out.write("\n") 373 out.write("<tr>\n") 374 out.write("<td>month</td>\n") 375 out.write("<td>uint</td>\n") 376 if 'month' in params: 377 out.write(" <td>"+str(params['month'])+"</td>\n") 378 out.write(" <td>"+str(params['month'])+"</td>\n") 379 out.write("</tr>\n") 380 out.write("\n") 381 out.write("<tr>\n") 382 out.write("<td>day</td>\n") 383 out.write("<td>uint</td>\n") 384 if 'day' in params: 385 out.write(" <td>"+str(params['day'])+"</td>\n") 386 out.write(" <td>"+str(params['day'])+"</td>\n") 387 out.write("</tr>\n") 388 out.write("\n") 389 out.write("<tr>\n") 390 out.write("<td>hour</td>\n") 391 out.write("<td>uint</td>\n") 392 if 'hour' in params: 393 out.write(" <td>"+str(params['hour'])+"</td>\n") 394 out.write(" <td>"+str(params['hour'])+"</td>\n") 395 out.write("</tr>\n") 396 out.write("\n") 397 out.write("<tr>\n") 398 out.write("<td>min</td>\n") 399 out.write("<td>uint</td>\n") 400 if 'min' in params: 401 out.write(" <td>"+str(params['min'])+"</td>\n") 402 out.write(" <td>"+str(params['min'])+"</td>\n") 403 out.write("</tr>\n") 404 out.write("\n") 405 out.write("<tr>\n") 406 out.write("<td>sec</td>\n") 407 out.write("<td>uint</td>\n") 408 if 'sec' in params: 409 out.write(" <td>"+str(params['sec'])+"</td>\n") 410 out.write(" <td>"+str(params['sec'])+"</td>\n") 411 out.write("</tr>\n") 412 out.write("\n") 413 out.write("<tr>\n") 414 out.write("<td>stationid</td>\n") 415 out.write("<td>aisstr6</td>\n") 416 if 'stationid' in params: 417 out.write(" <td>"+str(params['stationid'])+"</td>\n") 418 out.write(" <td>"+str(params['stationid'])+"</td>\n") 419 out.write("</tr>\n") 420 out.write("\n") 421 out.write("<tr>\n") 422 out.write("<td>longitude</td>\n") 423 out.write("<td>decimal</td>\n") 424 if 'longitude' in params: 425 out.write(" <td>"+str(params['longitude'])+"</td>\n") 426 out.write(" <td>"+str(params['longitude'])+"</td>\n") 427 out.write("<td>degrees</td>\n") 428 out.write("</tr>\n") 429 out.write("\n") 430 out.write("<tr>\n") 431 out.write("<td>latitude</td>\n") 432 out.write("<td>decimal</td>\n") 433 if 'latitude' in params: 434 out.write(" <td>"+str(params['latitude'])+"</td>\n") 435 out.write(" <td>"+str(params['latitude'])+"</td>\n") 436 out.write("<td>degrees</td>\n") 437 out.write("</tr>\n") 438 out.write("\n") 439 out.write("<tr>\n") 440 out.write("<td>timetoexpire</td>\n") 441 out.write("<td>uint</td>\n") 442 if 'timetoexpire' in params: 443 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n") 444 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n") 445 out.write("<td>seconds</td>\n") 446 out.write("</tr>\n") 447 out.write("\n") 448 out.write("<tr>\n") 449 out.write("<td>radius</td>\n") 450 out.write("<td>uint</td>\n") 451 if 'radius' in params: 452 out.write(" <td>"+str(params['radius'])+"</td>\n") 453 out.write(" <td>"+str(params['radius'])+"</td>\n") 454 out.write("<td>m</td>\n") 455 out.write("</tr>\n") 456 out.write("\n") 457 out.write("<tr>\n") 458 out.write("<td>heading</td>\n") 459 out.write("<td>uint</td>\n") 460 if 'heading' in params: 461 out.write(" <td>"+str(params['heading'])+"</td>\n") 462 out.write(" <td>"+str(params['heading'])+"</td>\n") 463 out.write("<td>degrees true north</td>\n") 464 out.write("</tr>\n") 465 out.write("\n") 466 out.write("<tr>\n") 467 out.write("<td>numWhales</td>\n") 468 out.write("<td>uint</td>\n") 469 if 'numWhales' in params: 470 out.write(" <td>"+str(params['numWhales'])+"</td>\n") 471 out.write(" <td>"+str(params['numWhales'])+"</td>\n") 472 out.write("</tr>\n") 473 out.write("</table>\n")
474 475
476 -def printKml(params, out=sys.stdout):
477 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer''' 478 out.write("\ <Placemark>\n") 479 out.write("\t <name>"+str(params['stationsid'])+"</name>\n") 480 out.write("\t\t<description>\n") 481 import StringIO 482 buf = StringIO.StringIO() 483 printHtml(params,buf) 484 import cgi 485 out.write(cgi.escape(buf.getvalue())) 486 out.write("\t\t</description>\n") 487 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n") 488 out.write("\t\t<Point>\n") 489 out.write("\t\t\t<coordinates>") 490 out.write(str(params['longitude'])) 491 out.write(',') 492 out.write(str(params['latitude'])) 493 out.write(",0</coordinates>\n") 494 out.write("\t\t</Point>\n") 495 out.write("\t</Placemark>\n")
496
497 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
498 '''Print a whalenotice message to stdout. 499 500 Fields in params: 501 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 502 - RepeatIndicator(uint): Indicated how many times a message has been repeated 503 - UserID(uint): Unique ship identification number (MMSI) 504 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 505 - dac(uint): Designated Area Code (field automatically set to "366") 506 - fid(uint): Functional Identifier (field automatically set to "1") 507 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 508 - month(uint): Time whale was last recorded. month 1..12 509 - day(uint): Time whale was last recorded. day of the month 1..31 510 - hour(uint): Time whale was last recorded. UTC hours 0..23 511 - min(uint): Time whale was last recorded. minutes 512 - sec(uint): Time whale was last recorded. seconds 513 - stationid(aisstr6): Character identifier of the station. Usually a number. 514 - longitude(decimal): Where was the whale located. Center of the restricted speed zone. East West location 515 - latitude(decimal): Where was the whale located. Center of the restricted speed zone. North South location 516 - timetoexpire(uint): Seconds from the time tag until this notice expires 517 - radius(uint): Distance of the required exclusion/slow zone 518 - heading(uint): Direction the whale is traveling if known 519 - numWhales(uint): Number of whales detected 520 @param params: Dictionary of field names/values. 521 @param out: File like object to write to 522 @rtype: stdout 523 @return: text to out 524 ''' 525 526 if 'std'==format: 527 out.write("whalenotice:\n") 528 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n") 529 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n") 530 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n") 531 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n") 532 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n") 533 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n") 534 if 'efid' in params: out.write(" efid: "+str(params['efid'])+"\n") 535 if 'month' in params: out.write(" month: "+str(params['month'])+"\n") 536 if 'day' in params: out.write(" day: "+str(params['day'])+"\n") 537 if 'hour' in params: out.write(" hour: "+str(params['hour'])+"\n") 538 if 'min' in params: out.write(" min: "+str(params['min'])+"\n") 539 if 'sec' in params: out.write(" sec: "+str(params['sec'])+"\n") 540 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n") 541 if 'longitude' in params: out.write(" longitude: "+str(params['longitude'])+"\n") 542 if 'latitude' in params: out.write(" latitude: "+str(params['latitude'])+"\n") 543 if 'timetoexpire' in params: out.write(" timetoexpire: "+str(params['timetoexpire'])+"\n") 544 if 'radius' in params: out.write(" radius: "+str(params['radius'])+"\n") 545 if 'heading' in params: out.write(" heading: "+str(params['heading'])+"\n") 546 if 'numWhales' in params: out.write(" numWhales: "+str(params['numWhales'])+"\n") 547 elif 'csv'==format: 548 if None == options.fieldList: 549 options.fieldList = fieldList 550 needComma = False; 551 for field in fieldList: 552 if needComma: out.write(',') 553 needComma = True 554 if field in params: 555 out.write(str(params[field])) 556 # else: leave it empty 557 out.write("\n") 558 elif 'html'==format: 559 printHtml(params,out) 560 elif 'sql'==format: 561 sqlInsertStr(params,out,dbType=dbType) 562 elif 'kml'==format: 563 printKml(params,out) 564 elif 'kml-full'==format: 565 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") 566 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n") 567 out.write("<Document>\n") 568 out.write(" <name>whalenotice</name>\n") 569 printKml(params,out) 570 out.write("</Document>\n") 571 out.write("</kml>\n") 572 else: 573 print "ERROR: unknown format:",format 574 assert False 575 576 return # Nothing to return
577 578 RepeatIndicatorEncodeLut = { 579 'default':'0', 580 'do not repeat any more':'3', 581 } #RepeatIndicatorEncodeLut 582 583 RepeatIndicatorDecodeLut = { 584 '0':'default', 585 '3':'do not repeat any more', 586 } # RepeatIndicatorEncodeLut 587 588 ###################################################################### 589 # SQL SUPPORT 590 ###################################################################### 591
592 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 593 ,addCoastGuardFields=True 594 ,dbType='postgres' 595 ):
596 ''' 597 Return the SQL CREATE command for this message type 598 @param outfile: file like object to print to. 599 @param fields: which fields to put in the create. Defaults to all. 600 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 601 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 602 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 603 @type addCoastGuardFields: bool 604 @return: sql create string 605 @rtype: str 606 607 @see: sqlCreate 608 ''' 609 # FIX: should this sqlCreate be the same as in LaTeX (createFuncName) rather than hard coded? 610 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
611
612 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
613 ''' 614 Return the sqlhelp object to create the table. 615 616 @param fields: which fields to put in the create. Defaults to all. 617 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 618 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 619 @type addCoastGuardFields: bool 620 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 621 @return: An object that can be used to generate a return 622 @rtype: sqlhelp.create 623 ''' 624 if None == fields: fields = fieldList 625 import sqlhelp 626 c = sqlhelp.create('whalenotice',dbType=dbType) 627 c.addPrimaryKey() 628 if 'MessageID' in fields: c.addInt ('MessageID') 629 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator') 630 if 'UserID' in fields: c.addInt ('UserID') 631 if 'Spare' in fields: c.addInt ('Spare') 632 if 'dac' in fields: c.addInt ('dac') 633 if 'fid' in fields: c.addInt ('fid') 634 if 'efid' in fields: c.addInt ('efid') 635 if 'month' in fields: c.addInt ('month') 636 if 'day' in fields: c.addInt ('day') 637 if 'hour' in fields: c.addInt ('hour') 638 if 'min' in fields: c.addInt ('min') 639 if 'sec' in fields: c.addInt ('sec') 640 if 'stationid' in fields: c.addVarChar('stationid',7) 641 if dbType != 'postgres': 642 if 'longitude' in fields: c.addDecimal('longitude',8,5) 643 if dbType != 'postgres': 644 if 'latitude' in fields: c.addDecimal('latitude',8,5) 645 if 'timetoexpire' in fields: c.addInt ('timetoexpire') 646 if 'radius' in fields: c.addInt ('radius') 647 if 'heading' in fields: c.addInt ('heading') 648 if 'numWhales' in fields: c.addInt ('numWhales') 649 650 if addCoastGuardFields: 651 # c.addInt('cg_rssi') # Relative signal strength indicator 652 # c.addInt('cg_d') # dBm receive strength 653 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 654 # c.addInt('cg_S') # Slot received in 655 # c.addVarChar('cg_x',10) # Idonno 656 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 657 c.addInt('cg_sec') # UTC seconds since the epoch 658 659 c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream 660 661 if dbType == 'postgres': 662 #--- EPSG 4326 : WGS 84 663 #INSERT INTO "spatial_ref_sys" ("srid","auth_name","auth_srid","srtext","proj4text") VALUES (4326,'EPSG',4326,'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '); 664 c.addPostGIS('whale','POINT',2,SRID=4326); 665 666 return c
667
668 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
669 ''' 670 Return the SQL INSERT command for this message type 671 @param params: dictionary of values keyed by field name 672 @param outfile: file like object to print to. 673 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 674 @return: sql create string 675 @rtype: str 676 677 @see: sqlCreate 678 ''' 679 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
680 681
682 -def sqlInsert(params,extraParams=None,dbType='postgres'):
683 ''' 684 Give the SQL INSERT statement 685 @param params: dict keyed by field name of values 686 @param extraParams: any extra fields that you have created beyond the normal ais message fields 687 @rtype: sqlhelp.insert 688 @return: insert class instance 689 @todo: allow optional type checking of params? 690 @warning: this will take invalid keys happily and do what??? 691 ''' 692 import sqlhelp 693 i = sqlhelp.insert('whalenotice',dbType=dbType) 694 695 if dbType=='postgres': 696 finished = [] 697 for key in params: 698 if key in finished: 699 continue 700 701 if key not in toPgFields and key not in fromPgFields: 702 if type(params[key])==Decimal: i.add(key,float(params[key])) 703 else: i.add(key,params[key]) 704 else: 705 if key in fromPgFields: 706 val = params[key] 707 # Had better be a WKT type like POINT(-88.1 30.321) 708 i.addPostGIS(key,val) 709 finished.append(key) 710 else: 711 # Need to construct the type. 712 pgName = toPgFields[key] 713 #valStr='GeomFromText(\''+pgTypes[pgName]+'(' 714 valStr=pgTypes[pgName]+'(' 715 vals = [] 716 for nonPgKey in fromPgFields[pgName]: 717 vals.append(str(params[nonPgKey])) 718 finished.append(nonPgKey) 719 valStr+=' '.join(vals)+')' 720 i.addPostGIS(pgName,valStr) 721 else: 722 for key in params: 723 if type(params[key])==Decimal: i.add(key,float(params[key])) 724 else: i.add(key,params[key]) 725 726 if None != extraParams: 727 for key in extraParams: 728 i.add(key,extraParams[key]) 729 730 return i
731 732 ###################################################################### 733 # LATEX SUPPORT 734 ###################################################################### 735
736 -def latexDefinitionTable(outfile=sys.stdout 737 ):
738 ''' 739 Return the LaTeX definition table for this message type 740 @param outfile: file like object to print to. 741 @type outfile: file obj 742 @return: LaTeX table string via the outfile 743 @rtype: str 744 745 ''' 746 o = outfile 747 748 o.write(''' 749 \\begin{table}%[htb] 750 \\centering 751 \\begin{tabular}{|l|c|l|} 752 \\hline 753 Parameter & Number of bits & Description 754 \\\\ \\hline\\hline 755 MessageID & 6 & AIS message number. Must be 8 \\\\ \hline 756 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline 757 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline 758 Spare & 2 & Reserved for definition by a regional authority. \\\\ \hline 759 dac & 10 & Designated Area Code \\\\ \hline 760 fid & 6 & Functional Identifier \\\\ \hline 761 efid & 12 & extended functional identifier (dac+fid+id defines which message) \\\\ \hline 762 month & 4 & Time whale was last recorded. month 1..12 \\\\ \hline 763 day & 5 & Time whale was last recorded. day of the month 1..31 \\\\ \hline 764 hour & 5 & Time whale was last recorded. UTC hours 0..23 \\\\ \hline 765 min & 6 & Time whale was last recorded. minutes \\\\ \hline 766 sec & 6 & Time whale was last recorded. seconds \\\\ \hline 767 stationid & 42 & Character identifier of the station. Usually a number. \\\\ \hline 768 longitude & 28 & Where was the whale located. Center of the restricted speed zone. East West location \\\\ \hline 769 latitude & 27 & Where was the whale located. Center of the restricted speed zone. North South location \\\\ \hline 770 timetoexpire & 16 & Seconds from the time tag until this notice expires \\\\ \hline 771 radius & 16 & Distance of the required exclusion/slow zone \\\\ \hline 772 heading & 9 & Direction the whale is traveling if known \\\\ \hline 773 numWhales & 8 & Number of whales detected\\\\ \\hline \\hline 774 Total bits & 240 & Appears to take 2 slots with 184 pad bits to fill the last slot \\\\ \\hline 775 \\end{tabular} 776 \\caption{AIS message number 8: Endangered whale notification binary message.} 777 \\label{tab:whalenotice} 778 \\end{table} 779 ''')
780 781 ###################################################################### 782 # Text Definition 783 ###################################################################### 784
785 -def textDefinitionTable(outfile=sys.stdout 786 ,delim='\t' 787 ):
788 ''' 789 Return the text definition table for this message type 790 @param outfile: file like object to print to. 791 @type outfile: file obj 792 @return: text table string via the outfile 793 @rtype: str 794 795 ''' 796 o = outfile 797 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description 798 MessageID'''+delim+'''6'''+delim+'''AIS message number. Must be 8 799 RepeatIndicator'''+delim+'''2'''+delim+'''Indicated how many times a message has been repeated 800 UserID'''+delim+'''30'''+delim+'''Unique ship identification number (MMSI) 801 Spare'''+delim+'''2'''+delim+'''Reserved for definition by a regional authority. 802 dac'''+delim+'''10'''+delim+'''Designated Area Code 803 fid'''+delim+'''6'''+delim+'''Functional Identifier 804 efid'''+delim+'''12'''+delim+'''extended functional identifier (dac+fid+id defines which message) 805 month'''+delim+'''4'''+delim+'''Time whale was last recorded. month 1..12 806 day'''+delim+'''5'''+delim+'''Time whale was last recorded. day of the month 1..31 807 hour'''+delim+'''5'''+delim+'''Time whale was last recorded. UTC hours 0..23 808 min'''+delim+'''6'''+delim+'''Time whale was last recorded. minutes 809 sec'''+delim+'''6'''+delim+'''Time whale was last recorded. seconds 810 stationid'''+delim+'''42'''+delim+'''Character identifier of the station. Usually a number. 811 longitude'''+delim+'''28'''+delim+'''Where was the whale located. Center of the restricted speed zone. East West location 812 latitude'''+delim+'''27'''+delim+'''Where was the whale located. Center of the restricted speed zone. North South location 813 timetoexpire'''+delim+'''16'''+delim+'''Seconds from the time tag until this notice expires 814 radius'''+delim+'''16'''+delim+'''Distance of the required exclusion/slow zone 815 heading'''+delim+'''9'''+delim+'''Direction the whale is traveling if known 816 numWhales'''+delim+'''8'''+delim+'''Number of whales detected 817 Total bits'''+delim+'''240'''+delim+'''Appears to take 2 slots with 184 pad bits to fill the last slot''')
818 819 820 ###################################################################### 821 # UNIT TESTING 822 ###################################################################### 823 import unittest
824 -def testParams():
825 '''Return a params file base on the testvalue tags. 826 @rtype: dict 827 @return: params based on testvalue tags 828 ''' 829 params = {} 830 params['MessageID'] = 8 831 params['RepeatIndicator'] = 1 832 params['UserID'] = 1193046 833 params['Spare'] = 0 834 params['dac'] = 366 835 params['fid'] = 1 836 params['efid'] = 2 837 params['month'] = 2 838 params['day'] = 28 839 params['hour'] = 23 840 params['min'] = 45 841 params['sec'] = 58 842 params['stationid'] = 'A234567' 843 params['longitude'] = Decimal('-122.16328055555556') 844 params['latitude'] = Decimal('37.424458333333334') 845 params['timetoexpire'] = 1 846 params['radius'] = 5000 847 params['heading'] = 35 848 params['numWhales'] = 2 849 850 return params
851
852 -class Testwhalenotice(unittest.TestCase):
853 '''Use testvalue tag text from each type to build test case the whalenotice message'''
854 - def testEncodeDecode(self):
855 856 params = testParams() 857 bits = encode(params) 858 r = decode(bits) 859 860 # Check that each parameter came through ok. 861 self.failUnlessEqual(r['MessageID'],params['MessageID']) 862 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 863 self.failUnlessEqual(r['UserID'],params['UserID']) 864 self.failUnlessEqual(r['Spare'],params['Spare']) 865 self.failUnlessEqual(r['dac'],params['dac']) 866 self.failUnlessEqual(r['fid'],params['fid']) 867 self.failUnlessEqual(r['efid'],params['efid']) 868 self.failUnlessEqual(r['month'],params['month']) 869 self.failUnlessEqual(r['day'],params['day']) 870 self.failUnlessEqual(r['hour'],params['hour']) 871 self.failUnlessEqual(r['min'],params['min']) 872 self.failUnlessEqual(r['sec'],params['sec']) 873 self.failUnlessEqual(r['stationid'],params['stationid']) 874 self.failUnlessAlmostEqual(r['longitude'],params['longitude'],5) 875 self.failUnlessAlmostEqual(r['latitude'],params['latitude'],5) 876 self.failUnlessEqual(r['timetoexpire'],params['timetoexpire']) 877 self.failUnlessEqual(r['radius'],params['radius']) 878 self.failUnlessEqual(r['heading'],params['heading']) 879 self.failUnlessEqual(r['numWhales'],params['numWhales'])
880
881 -def addMsgOptions(parser):
882 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 883 help='decode a "whalenotice" AIS message') 884 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 885 help='encode a "whalenotice" AIS message') 886 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int' 887 ,help='Field parameter value [default: %default]') 888 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int' 889 ,help='Field parameter value [default: %default]') 890 parser.add_option('--month-field', dest='monthField',metavar='uint',type='int' 891 ,help='Field parameter value [default: %default]') 892 parser.add_option('--day-field', dest='dayField',metavar='uint',type='int' 893 ,help='Field parameter value [default: %default]') 894 parser.add_option('--hour-field', dest='hourField',metavar='uint',type='int' 895 ,help='Field parameter value [default: %default]') 896 parser.add_option('--min-field', dest='minField',metavar='uint',type='int' 897 ,help='Field parameter value [default: %default]') 898 parser.add_option('--sec-field', dest='secField',metavar='uint',type='int' 899 ,help='Field parameter value [default: %default]') 900 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string' 901 ,help='Field parameter value [default: %default]') 902 parser.add_option('--longitude-field', dest='longitudeField',default=Decimal('181'),metavar='decimal',type='string' 903 ,help='Field parameter value [default: %default]') 904 parser.add_option('--latitude-field', dest='latitudeField',default=Decimal('91'),metavar='decimal',type='string' 905 ,help='Field parameter value [default: %default]') 906 parser.add_option('--timetoexpire-field', dest='timetoexpireField',default=0,metavar='uint',type='int' 907 ,help='Field parameter value [default: %default]') 908 parser.add_option('--radius-field', dest='radiusField',default=65534,metavar='uint',type='int' 909 ,help='Field parameter value [default: %default]') 910 parser.add_option('--heading-field', dest='headingField',default=511,metavar='uint',type='int' 911 ,help='Field parameter value [default: %default]') 912 parser.add_option('--numWhales-field', dest='numWhalesField',default=0,metavar='uint',type='int' 913 ,help='Field parameter value [default: %default]')
914 915 ############################################################ 916 if __name__=='__main__': 917 918 from optparse import OptionParser 919 parser = OptionParser(usage="%prog [options]", 920 version="%prog "+__version__) 921 922 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 923 help='run the documentation tests') 924 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 925 help='run the unit tests') 926 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 927 help='Make the test output verbose') 928 929 # FIX: remove nmea from binary messages. No way to build the whole packet? 930 # FIX: or build the surrounding msg 8 for a broadcast? 931 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 932 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 933 ,default='nmeapayload' 934 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 935 936 937 outputChoices = ('std','html','csv','sql' , 'kml','kml-full') 938 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 939 ,default='std' 940 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 941 942 parser.add_option('-o','--output',dest='outputFileName',default=None, 943 help='Name of the python file to write [default: stdout]') 944 945 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 946 choices=fieldList, 947 help='Which fields to include in the output. Currently only for csv output [default: all]') 948 949 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 950 help='Print the field name for csv') 951 952 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 953 help='Print out an sql create command for the table.') 954 955 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true', 956 help='Print a LaTeX table of the type') 957 958 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true', 959 help='Print delimited table of the type (for Word table importing)') 960 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t' 961 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)') 962 963 964 dbChoices = ('sqlite','postgres') 965 parser.add_option('-D','--db-type',dest='dbType',default='postgres' 966 ,choices=dbChoices,type='choice' 967 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 968 969 addMsgOptions(parser) 970 971 (options,args) = parser.parse_args() 972 success=True 973 974 if options.doctest: 975 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 976 sys.argv= [sys.argv[0]] 977 if options.verbose: sys.argv.append('-v') 978 import doctest 979 numfail,numtests=doctest.testmod() 980 if numfail==0: print 'ok' 981 else: 982 print 'FAILED' 983 success=False 984 985 if not success: sys.exit('Something Failed') 986 del success # Hide success from epydoc 987 988 if options.unittest: 989 sys.argv = [sys.argv[0]] 990 if options.verbose: sys.argv.append('-v') 991 unittest.main() 992 993 outfile = sys.stdout 994 if None!=options.outputFileName: 995 outfile = file(options.outputFileName,'w') 996 997 998 if options.doEncode: 999 # First make sure all non required options are specified 1000 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField") 1001 if None==options.UserIDField: parser.error("missing value for UserIDField") 1002 if None==options.monthField: parser.error("missing value for monthField") 1003 if None==options.dayField: parser.error("missing value for dayField") 1004 if None==options.hourField: parser.error("missing value for hourField") 1005 if None==options.minField: parser.error("missing value for minField") 1006 if None==options.secField: parser.error("missing value for secField") 1007 if None==options.stationidField: parser.error("missing value for stationidField") 1008 if None==options.longitudeField: parser.error("missing value for longitudeField") 1009 if None==options.latitudeField: parser.error("missing value for latitudeField") 1010 if None==options.timetoexpireField: parser.error("missing value for timetoexpireField") 1011 if None==options.radiusField: parser.error("missing value for radiusField") 1012 if None==options.headingField: parser.error("missing value for headingField") 1013 if None==options.numWhalesField: parser.error("missing value for numWhalesField") 1014 msgDict={ 1015 'MessageID': '8', 1016 'RepeatIndicator': options.RepeatIndicatorField, 1017 'UserID': options.UserIDField, 1018 'Spare': '0', 1019 'dac': '366', 1020 'fid': '1', 1021 'efid': '2', 1022 'month': options.monthField, 1023 'day': options.dayField, 1024 'hour': options.hourField, 1025 'min': options.minField, 1026 'sec': options.secField, 1027 'stationid': options.stationidField, 1028 'longitude': options.longitudeField, 1029 'latitude': options.latitudeField, 1030 'timetoexpire': options.timetoexpireField, 1031 'radius': options.radiusField, 1032 'heading': options.headingField, 1033 'numWhales': options.numWhalesField, 1034 } 1035 1036 bits = encode(msgDict) 1037 if 'binary'==options.ioType: print str(bits) 1038 elif 'nmeapayload'==options.ioType: 1039 # FIX: figure out if this might be necessary at compile time 1040 print "bitLen",len(bits) 1041 bitLen=len(bits) 1042 if bitLen%6!=0: 1043 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 1044 print "result:",binary.bitvectoais6(bits)[0] 1045 1046 1047 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 1048 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 1049 else: sys.exit('ERROR: unknown ioType. Help!') 1050 1051 1052 if options.sqlCreate: 1053 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 1054 1055 if options.latexDefinitionTable: 1056 latexDefinitionTable(outfile) 1057 1058 # For conversion to word tables 1059 if options.textDefinitionTable: 1060 textDefinitionTable(outfile,options.delimTextDefinitionTable) 1061 1062 if options.printCsvfieldList: 1063 # Make a csv separated list of fields that will be displayed for csv 1064 if None == options.fieldList: options.fieldList = fieldList 1065 import StringIO 1066 buf = StringIO.StringIO() 1067 for field in options.fieldList: 1068 buf.write(field+',') 1069 result = buf.getvalue() 1070 if result[-1] == ',': print result[:-1] 1071 else: print result 1072 1073 if options.doDecode: 1074 if len(args)==0: args = sys.stdin 1075 for msg in args: 1076 bv = None 1077 1078 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 1079 # Found nmea 1080 # FIX: do checksum 1081 bv = binary.ais6tobitvec(msg.split(',')[5]) 1082 else: # either binary or nmeapayload... expect mostly nmeapayloads 1083 # assumes that an all 0 and 1 string can not be a nmeapayload 1084 binaryMsg=True 1085 for c in msg: 1086 if c not in ('0','1'): 1087 binaryMsg=False 1088 break 1089 if binaryMsg: 1090 bv = BitVector(bitstring=msg) 1091 else: # nmeapayload 1092 bv = binary.ais6tobitvec(msg) 1093 1094 printFields(decode(bv) 1095 ,out=outfile 1096 ,format=options.outputType 1097 ,fieldList=options.fieldList 1098 ,dbType=options.dbType 1099 ) 1100