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

Source Code for Module ais.ais_msg_4

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