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

Source Code for Module ais.ais_msg_5

   1  #!/usr/bin/env python 
   2   
   3  __version__ = '$Revision: 4791 $'.split()[1] 
   4  __date__ = '$Date: 2007-03-18 $'.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          'AISversion', 
  54          'IMOnumber', 
  55          'callsign', 
  56          'name', 
  57          'shipandcargo', 
  58          'dimA', 
  59          'dimB', 
  60          'dimC', 
  61          'dimD', 
  62          'fixtype', 
  63          'ETAminute', 
  64          'ETAhour', 
  65          'ETAday', 
  66          'ETAmonth', 
  67          'draught', 
  68          'destination', 
  69          'dte', 
  70          'Spare', 
  71  ) 
  72   
  73  fieldListPostgres = ( 
  74          'MessageID', 
  75          'RepeatIndicator', 
  76          'UserID', 
  77          'AISversion', 
  78          'IMOnumber', 
  79          'callsign', 
  80          'name', 
  81          'shipandcargo', 
  82          'dimA', 
  83          'dimB', 
  84          'dimC', 
  85          'dimD', 
  86          'fixtype', 
  87          'ETAminute', 
  88          'ETAhour', 
  89          'ETAday', 
  90          'ETAmonth', 
  91          'draught', 
  92          'destination', 
  93          'dte', 
  94          'Spare', 
  95  ) 
  96   
  97  toPgFields = { 
  98  } 
  99  ''' 
 100  Go to the Postgis field names from the straight field name 
 101  ''' 
 102   
 103  fromPgFields = { 
 104  } 
 105  ''' 
 106  Go from the Postgis field names to the straight field name 
 107  ''' 
 108   
 109  pgTypes = { 
 110  } 
 111  ''' 
 112  Lookup table for each postgis field name to get its type. 
 113  ''' 
 114   
115 -def encode(params, validate=False):
116 '''Create a shipdata binary message payload to pack into an AIS Msg shipdata. 117 118 Fields in params: 119 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5") 120 - RepeatIndicator(uint): Indicated how many times a message has been repeated 121 - UserID(uint): Unique ship identification number (MMSI) 122 - AISversion(uint): Compliant with what edition. 0 is the first edition. 123 - IMOnumber(uint): vessel identification number (different than mmsi) 124 - callsign(aisstr6): Ship radio call sign 125 - name(aisstr6): Vessel name 126 - shipandcargo(uint): what 127 - dimA(uint): Distance from bow to reference position 128 - dimB(uint): Distance from reference position to stern 129 - dimC(uint): Distance from port side to reference position 130 - dimD(uint): Distance from reference position to starboard side 131 - fixtype(uint): Method used for positioning 132 - ETAminute(uint): Estimated time of arrival - minutes 133 - ETAhour(uint): Estimated time of arrival - hour 134 - ETAday(uint): Estimated time of arrival - day 135 - ETAmonth(uint): Estimated time of arrival - month 136 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater 137 - destination(aisstr6): Where is the vessel going 138 - dte(uint): Data terminal ready 139 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 140 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 141 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 142 @rtype: BitVector 143 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 144 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 145 ''' 146 147 bvList = [] 148 bvList.append(binary.setBitVectorSize(BitVector(intVal=5),6)) 149 if 'RepeatIndicator' in params: 150 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2)) 151 else: 152 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 153 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30)) 154 if 'AISversion' in params: 155 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['AISversion']),2)) 156 else: 157 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 158 if 'IMOnumber' in params: 159 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['IMOnumber']),30)) 160 else: 161 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),30)) 162 if 'callsign' in params: 163 bvList.append(aisstring.encode(params['callsign'],42)) 164 else: 165 bvList.append(aisstring.encode('@@@@@@@',42)) 166 if 'name' in params: 167 bvList.append(aisstring.encode(params['name'],120)) 168 else: 169 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@@@@@@',120)) 170 if 'shipandcargo' in params: 171 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['shipandcargo']),8)) 172 else: 173 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8)) 174 if 'dimA' in params: 175 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimA']),9)) 176 else: 177 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),9)) 178 if 'dimB' in params: 179 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimB']),9)) 180 else: 181 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),9)) 182 if 'dimC' in params: 183 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimC']),6)) 184 else: 185 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6)) 186 if 'dimD' in params: 187 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimD']),6)) 188 else: 189 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6)) 190 if 'fixtype' in params: 191 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['fixtype']),4)) 192 else: 193 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4)) 194 if 'ETAminute' in params: 195 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAminute']),6)) 196 else: 197 bvList.append(binary.setBitVectorSize(BitVector(intVal=60),6)) 198 if 'ETAhour' in params: 199 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAhour']),5)) 200 else: 201 bvList.append(binary.setBitVectorSize(BitVector(intVal=24),5)) 202 if 'ETAday' in params: 203 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAday']),5)) 204 else: 205 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),5)) 206 if 'ETAmonth' in params: 207 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAmonth']),4)) 208 else: 209 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4)) 210 if 'draught' in params: 211 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['draught'])*Decimal('10')))),8)) 212 else: 213 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(0)),8)) 214 if 'destination' in params: 215 bvList.append(aisstring.encode(params['destination'],120)) 216 else: 217 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@@@@@@',120)) 218 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dte']),1)) 219 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),1)) 220 221 return binary.joinBV(bvList)
222
223 -def decode(bv, validate=False):
224 '''Unpack a shipdata message 225 226 Fields in params: 227 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5") 228 - RepeatIndicator(uint): Indicated how many times a message has been repeated 229 - UserID(uint): Unique ship identification number (MMSI) 230 - AISversion(uint): Compliant with what edition. 0 is the first edition. 231 - IMOnumber(uint): vessel identification number (different than mmsi) 232 - callsign(aisstr6): Ship radio call sign 233 - name(aisstr6): Vessel name 234 - shipandcargo(uint): what 235 - dimA(uint): Distance from bow to reference position 236 - dimB(uint): Distance from reference position to stern 237 - dimC(uint): Distance from port side to reference position 238 - dimD(uint): Distance from reference position to starboard side 239 - fixtype(uint): Method used for positioning 240 - ETAminute(uint): Estimated time of arrival - minutes 241 - ETAhour(uint): Estimated time of arrival - hour 242 - ETAday(uint): Estimated time of arrival - day 243 - ETAmonth(uint): Estimated time of arrival - month 244 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater 245 - destination(aisstr6): Where is the vessel going 246 - dte(uint): Data terminal ready 247 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 248 @type bv: BitVector 249 @param bv: Bits defining a message 250 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 251 @rtype: dict 252 @return: params 253 ''' 254 255 #Would be nice to check the bit count here.. 256 #if validate: 257 # assert (len(bv)==FIX: SOME NUMBER) 258 r = {} 259 r['MessageID']=5 260 r['RepeatIndicator']=int(bv[6:8]) 261 r['UserID']=int(bv[8:38]) 262 r['AISversion']=int(bv[38:40]) 263 r['IMOnumber']=int(bv[40:70]) 264 r['callsign']=aisstring.decode(bv[70:112]) 265 r['name']=aisstring.decode(bv[112:232]) 266 r['shipandcargo']=int(bv[232:240]) 267 r['dimA']=int(bv[240:249]) 268 r['dimB']=int(bv[249:258]) 269 r['dimC']=int(bv[258:264]) 270 r['dimD']=int(bv[264:270]) 271 r['fixtype']=int(bv[270:274]) 272 r['ETAminute']=int(bv[274:280]) 273 r['ETAhour']=int(bv[280:285]) 274 r['ETAday']=int(bv[285:290]) 275 r['ETAmonth']=int(bv[290:294]) 276 r['draught']=Decimal(int(bv[294:302]))/Decimal('10') 277 r['destination']=aisstring.decode(bv[302:422]) 278 r['dte']=int(bv[422:423]) 279 r['Spare']=0 280 return r
281
282 -def decodeMessageID(bv, validate=False):
283 return 5
284
285 -def decodeRepeatIndicator(bv, validate=False):
286 return int(bv[6:8])
287
288 -def decodeUserID(bv, validate=False):
289 return int(bv[8:38])
290
291 -def decodeAISversion(bv, validate=False):
292 return int(bv[38:40])
293
294 -def decodeIMOnumber(bv, validate=False):
295 return int(bv[40:70])
296
297 -def decodecallsign(bv, validate=False):
298 return aisstring.decode(bv[70:112])
299
300 -def decodename(bv, validate=False):
301 return aisstring.decode(bv[112:232])
302
303 -def decodeshipandcargo(bv, validate=False):
304 return int(bv[232:240])
305
306 -def decodedimA(bv, validate=False):
307 return int(bv[240:249])
308
309 -def decodedimB(bv, validate=False):
310 return int(bv[249:258])
311
312 -def decodedimC(bv, validate=False):
313 return int(bv[258:264])
314
315 -def decodedimD(bv, validate=False):
316 return int(bv[264:270])
317
318 -def decodefixtype(bv, validate=False):
319 return int(bv[270:274])
320
321 -def decodeETAminute(bv, validate=False):
322 return int(bv[274:280])
323
324 -def decodeETAhour(bv, validate=False):
325 return int(bv[280:285])
326
327 -def decodeETAday(bv, validate=False):
328 return int(bv[285:290])
329
330 -def decodeETAmonth(bv, validate=False):
331 return int(bv[290:294])
332
333 -def decodedraught(bv, validate=False):
334 return Decimal(int(bv[294:302]))/Decimal('10')
335
336 -def decodedestination(bv, validate=False):
337 return aisstring.decode(bv[302:422])
338
339 -def decodedte(bv, validate=False):
340 return int(bv[422:423])
341
342 -def decodeSpare(bv, validate=False):
343 return 0
344 345
346 -def printHtml(params, out=sys.stdout):
347 out.write("<h3>shipdata<h3>\n") 348 out.write("<table border=\"1\">\n") 349 out.write("<tr bgcolor=\"orange\">\n") 350 out.write("<th align=\"left\">Field Name</th>\n") 351 out.write("<th align=\"left\">Type</th>\n") 352 out.write("<th align=\"left\">Value</th>\n") 353 out.write("<th align=\"left\">Value in Lookup Table</th>\n") 354 out.write("<th align=\"left\">Units</th>\n") 355 out.write("\n") 356 out.write("<tr>\n") 357 out.write("<td>MessageID</td>\n") 358 out.write("<td>uint</td>\n") 359 if 'MessageID' in params: 360 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 361 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 362 out.write("</tr>\n") 363 out.write("\n") 364 out.write("<tr>\n") 365 out.write("<td>RepeatIndicator</td>\n") 366 out.write("<td>uint</td>\n") 367 if 'RepeatIndicator' in params: 368 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n") 369 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut: 370 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>") 371 else: 372 out.write("<td><i>Missing LUT entry</i></td>") 373 out.write("</tr>\n") 374 out.write("\n") 375 out.write("<tr>\n") 376 out.write("<td>UserID</td>\n") 377 out.write("<td>uint</td>\n") 378 if 'UserID' in params: 379 out.write(" <td>"+str(params['UserID'])+"</td>\n") 380 out.write(" <td>"+str(params['UserID'])+"</td>\n") 381 out.write("</tr>\n") 382 out.write("\n") 383 out.write("<tr>\n") 384 out.write("<td>AISversion</td>\n") 385 out.write("<td>uint</td>\n") 386 if 'AISversion' in params: 387 out.write(" <td>"+str(params['AISversion'])+"</td>\n") 388 out.write(" <td>"+str(params['AISversion'])+"</td>\n") 389 out.write("</tr>\n") 390 out.write("\n") 391 out.write("<tr>\n") 392 out.write("<td>IMOnumber</td>\n") 393 out.write("<td>uint</td>\n") 394 if 'IMOnumber' in params: 395 out.write(" <td>"+str(params['IMOnumber'])+"</td>\n") 396 out.write(" <td>"+str(params['IMOnumber'])+"</td>\n") 397 out.write("</tr>\n") 398 out.write("\n") 399 out.write("<tr>\n") 400 out.write("<td>callsign</td>\n") 401 out.write("<td>aisstr6</td>\n") 402 if 'callsign' in params: 403 out.write(" <td>"+str(params['callsign'])+"</td>\n") 404 out.write(" <td>"+str(params['callsign'])+"</td>\n") 405 out.write("</tr>\n") 406 out.write("\n") 407 out.write("<tr>\n") 408 out.write("<td>name</td>\n") 409 out.write("<td>aisstr6</td>\n") 410 if 'name' in params: 411 out.write(" <td>"+str(params['name'])+"</td>\n") 412 out.write(" <td>"+str(params['name'])+"</td>\n") 413 out.write("</tr>\n") 414 out.write("\n") 415 out.write("<tr>\n") 416 out.write("<td>shipandcargo</td>\n") 417 out.write("<td>uint</td>\n") 418 if 'shipandcargo' in params: 419 out.write(" <td>"+str(params['shipandcargo'])+"</td>\n") 420 if str(params['shipandcargo']) in shipandcargoDecodeLut: 421 out.write("<td>"+shipandcargoDecodeLut[str(params['shipandcargo'])]+"</td>") 422 else: 423 out.write("<td><i>Missing LUT entry</i></td>") 424 out.write("</tr>\n") 425 out.write("\n") 426 out.write("<tr>\n") 427 out.write("<td>dimA</td>\n") 428 out.write("<td>uint</td>\n") 429 if 'dimA' in params: 430 out.write(" <td>"+str(params['dimA'])+"</td>\n") 431 out.write(" <td>"+str(params['dimA'])+"</td>\n") 432 out.write("<td>m</td>\n") 433 out.write("</tr>\n") 434 out.write("\n") 435 out.write("<tr>\n") 436 out.write("<td>dimB</td>\n") 437 out.write("<td>uint</td>\n") 438 if 'dimB' in params: 439 out.write(" <td>"+str(params['dimB'])+"</td>\n") 440 out.write(" <td>"+str(params['dimB'])+"</td>\n") 441 out.write("<td>m</td>\n") 442 out.write("</tr>\n") 443 out.write("\n") 444 out.write("<tr>\n") 445 out.write("<td>dimC</td>\n") 446 out.write("<td>uint</td>\n") 447 if 'dimC' in params: 448 out.write(" <td>"+str(params['dimC'])+"</td>\n") 449 if str(params['dimC']) in dimCDecodeLut: 450 out.write("<td>"+dimCDecodeLut[str(params['dimC'])]+"</td>") 451 else: 452 out.write("<td><i>Missing LUT entry</i></td>") 453 out.write("<td>m</td>\n") 454 out.write("</tr>\n") 455 out.write("\n") 456 out.write("<tr>\n") 457 out.write("<td>dimD</td>\n") 458 out.write("<td>uint</td>\n") 459 if 'dimD' in params: 460 out.write(" <td>"+str(params['dimD'])+"</td>\n") 461 if str(params['dimD']) in dimDDecodeLut: 462 out.write("<td>"+dimDDecodeLut[str(params['dimD'])]+"</td>") 463 else: 464 out.write("<td><i>Missing LUT entry</i></td>") 465 out.write("<td>m</td>\n") 466 out.write("</tr>\n") 467 out.write("\n") 468 out.write("<tr>\n") 469 out.write("<td>fixtype</td>\n") 470 out.write("<td>uint</td>\n") 471 if 'fixtype' in params: 472 out.write(" <td>"+str(params['fixtype'])+"</td>\n") 473 if str(params['fixtype']) in fixtypeDecodeLut: 474 out.write("<td>"+fixtypeDecodeLut[str(params['fixtype'])]+"</td>") 475 else: 476 out.write("<td><i>Missing LUT entry</i></td>") 477 out.write("</tr>\n") 478 out.write("\n") 479 out.write("<tr>\n") 480 out.write("<td>ETAminute</td>\n") 481 out.write("<td>uint</td>\n") 482 if 'ETAminute' in params: 483 out.write(" <td>"+str(params['ETAminute'])+"</td>\n") 484 out.write(" <td>"+str(params['ETAminute'])+"</td>\n") 485 out.write("</tr>\n") 486 out.write("\n") 487 out.write("<tr>\n") 488 out.write("<td>ETAhour</td>\n") 489 out.write("<td>uint</td>\n") 490 if 'ETAhour' in params: 491 out.write(" <td>"+str(params['ETAhour'])+"</td>\n") 492 out.write(" <td>"+str(params['ETAhour'])+"</td>\n") 493 out.write("</tr>\n") 494 out.write("\n") 495 out.write("<tr>\n") 496 out.write("<td>ETAday</td>\n") 497 out.write("<td>uint</td>\n") 498 if 'ETAday' in params: 499 out.write(" <td>"+str(params['ETAday'])+"</td>\n") 500 out.write(" <td>"+str(params['ETAday'])+"</td>\n") 501 out.write("</tr>\n") 502 out.write("\n") 503 out.write("<tr>\n") 504 out.write("<td>ETAmonth</td>\n") 505 out.write("<td>uint</td>\n") 506 if 'ETAmonth' in params: 507 out.write(" <td>"+str(params['ETAmonth'])+"</td>\n") 508 out.write(" <td>"+str(params['ETAmonth'])+"</td>\n") 509 out.write("</tr>\n") 510 out.write("\n") 511 out.write("<tr>\n") 512 out.write("<td>draught</td>\n") 513 out.write("<td>udecimal</td>\n") 514 if 'draught' in params: 515 out.write(" <td>"+str(params['draught'])+"</td>\n") 516 out.write(" <td>"+str(params['draught'])+"</td>\n") 517 out.write("<td>m</td>\n") 518 out.write("</tr>\n") 519 out.write("\n") 520 out.write("<tr>\n") 521 out.write("<td>destination</td>\n") 522 out.write("<td>aisstr6</td>\n") 523 if 'destination' in params: 524 out.write(" <td>"+str(params['destination'])+"</td>\n") 525 out.write(" <td>"+str(params['destination'])+"</td>\n") 526 out.write("</tr>\n") 527 out.write("\n") 528 out.write("<tr>\n") 529 out.write("<td>dte</td>\n") 530 out.write("<td>uint</td>\n") 531 if 'dte' in params: 532 out.write(" <td>"+str(params['dte'])+"</td>\n") 533 if str(params['dte']) in dteDecodeLut: 534 out.write("<td>"+dteDecodeLut[str(params['dte'])]+"</td>") 535 else: 536 out.write("<td><i>Missing LUT entry</i></td>") 537 out.write("</tr>\n") 538 out.write("\n") 539 out.write("<tr>\n") 540 out.write("<td>Spare</td>\n") 541 out.write("<td>uint</td>\n") 542 if 'Spare' in params: 543 out.write(" <td>"+str(params['Spare'])+"</td>\n") 544 out.write(" <td>"+str(params['Spare'])+"</td>\n") 545 out.write("</tr>\n") 546 out.write("</table>\n")
547
548 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
549 '''Print a shipdata message to stdout. 550 551 Fields in params: 552 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5") 553 - RepeatIndicator(uint): Indicated how many times a message has been repeated 554 - UserID(uint): Unique ship identification number (MMSI) 555 - AISversion(uint): Compliant with what edition. 0 is the first edition. 556 - IMOnumber(uint): vessel identification number (different than mmsi) 557 - callsign(aisstr6): Ship radio call sign 558 - name(aisstr6): Vessel name 559 - shipandcargo(uint): what 560 - dimA(uint): Distance from bow to reference position 561 - dimB(uint): Distance from reference position to stern 562 - dimC(uint): Distance from port side to reference position 563 - dimD(uint): Distance from reference position to starboard side 564 - fixtype(uint): Method used for positioning 565 - ETAminute(uint): Estimated time of arrival - minutes 566 - ETAhour(uint): Estimated time of arrival - hour 567 - ETAday(uint): Estimated time of arrival - day 568 - ETAmonth(uint): Estimated time of arrival - month 569 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater 570 - destination(aisstr6): Where is the vessel going 571 - dte(uint): Data terminal ready 572 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 573 @param params: Dictionary of field names/values. 574 @param out: File like object to write to 575 @rtype: stdout 576 @return: text to out 577 ''' 578 579 if 'std'==format: 580 out.write("shipdata:\n") 581 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n") 582 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n") 583 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n") 584 if 'AISversion' in params: out.write(" AISversion: "+str(params['AISversion'])+"\n") 585 if 'IMOnumber' in params: out.write(" IMOnumber: "+str(params['IMOnumber'])+"\n") 586 if 'callsign' in params: out.write(" callsign: "+str(params['callsign'])+"\n") 587 if 'name' in params: out.write(" name: "+str(params['name'])+"\n") 588 if 'shipandcargo' in params: out.write(" shipandcargo: "+str(params['shipandcargo'])+"\n") 589 if 'dimA' in params: out.write(" dimA: "+str(params['dimA'])+"\n") 590 if 'dimB' in params: out.write(" dimB: "+str(params['dimB'])+"\n") 591 if 'dimC' in params: out.write(" dimC: "+str(params['dimC'])+"\n") 592 if 'dimD' in params: out.write(" dimD: "+str(params['dimD'])+"\n") 593 if 'fixtype' in params: out.write(" fixtype: "+str(params['fixtype'])+"\n") 594 if 'ETAminute' in params: out.write(" ETAminute: "+str(params['ETAminute'])+"\n") 595 if 'ETAhour' in params: out.write(" ETAhour: "+str(params['ETAhour'])+"\n") 596 if 'ETAday' in params: out.write(" ETAday: "+str(params['ETAday'])+"\n") 597 if 'ETAmonth' in params: out.write(" ETAmonth: "+str(params['ETAmonth'])+"\n") 598 if 'draught' in params: out.write(" draught: "+str(params['draught'])+"\n") 599 if 'destination' in params: out.write(" destination: "+str(params['destination'])+"\n") 600 if 'dte' in params: out.write(" dte: "+str(params['dte'])+"\n") 601 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n") 602 elif 'csv'==format: 603 if None == options.fieldList: 604 options.fieldList = fieldList 605 needComma = False; 606 for field in fieldList: 607 if needComma: out.write(',') 608 needComma = True 609 if field in params: 610 out.write(str(params[field])) 611 # else: leave it empty 612 out.write("\n") 613 elif 'html'==format: 614 printHtml(params,out) 615 elif 'sql'==format: 616 sqlInsertStr(params,out,dbType=dbType) 617 else: 618 print "ERROR: unknown format:",format 619 assert False 620 621 return # Nothing to return
622 623 RepeatIndicatorEncodeLut = { 624 'default':'0', 625 'do not repeat any more':'3', 626 } #RepeatIndicatorEncodeLut 627 628 RepeatIndicatorDecodeLut = { 629 '0':'default', 630 '3':'do not repeat any more', 631 } # RepeatIndicatorEncodeLut 632 633 shipandcargoEncodeLut = { 634 'Wing in ground (WIG), all ships of this type':'20', 635 'Wing in ground (WIG), Hazardous catagory A':'21', 636 'Wing in ground (WIG), Hazardous catagory B':'22', 637 'Wing in ground (WIG), Hazardous catagory C':'23', 638 'Wing in ground (WIG), Hazardous catagory D':'24', 639 'Wing in ground (WIG), Reserved for future use':'25', 640 'Wing in ground (WIG), Reserved for future use':'26', 641 'Wing in ground (WIG), Reserved for future use':'27', 642 'Wing in ground (WIG), Reserved for future use':'28', 643 'Wing in ground (WIG), No additional information':'29', 644 'fishing':'30', 645 'towing':'31', 646 'towing length exceeds 200m or breadth exceeds 25m':'32', 647 'dredging or underwater ops':'33', 648 'diving ops':'34', 649 'military ops':'35', 650 'sailing':'36', 651 'pleasure craft':'37', 652 'reserved':'38', 653 'reserved':'39', 654 'High speed craft (HSC), all ships of this type':'40', 655 'High speed craft (HSC), Hazardous catagory A':'41', 656 'High speed craft (HSC), Hazardous catagory B':'42', 657 'High speed craft (HSC), Hazardous catagory C':'43', 658 'High speed craft (HSC), Hazardous catagory D':'44', 659 'High speed craft (HSC), Reserved for future use':'45', 660 'High speed craft (HSC), Reserved for future use':'46', 661 'High speed craft (HSC), Reserved for future use':'47', 662 'High speed craft (HSC), Reserved for future use':'48', 663 'High speed craft (HSC), No additional information':'49', 664 'pilot vessel':'50', 665 'search and rescue vessel':'51', 666 'tug':'52', 667 'port tender':'53', 668 'anti-polution equipment':'54', 669 'law enforcement':'55', 670 'spare - local vessel':'56', 671 'spare - local vessel':'57', 672 'medical transport':'58', 673 'ship according to RR Resolution No. 18':'59', 674 'passenger, all ships of this type':'60', 675 'passenger, Hazardous catagory A':'61', 676 'passenger, Hazardous catagory B':'62', 677 'passenger, Hazardous catagory C':'63', 678 'passenger, Hazardous catagory D':'64', 679 'passenger, Reserved for future use':'65', 680 'passenger, Reserved for future use':'66', 681 'passenger, Reserved for future use':'67', 682 'passenger, Reserved for future use':'68', 683 'passenger, No additional information':'69', 684 'cargo, all ships of this type':'70', 685 'cargo, Hazardous catagory A':'71', 686 'cargo, Hazardous catagory B':'72', 687 'cargo, Hazardous catagory C':'73', 688 'cargo, Hazardous catagory D':'74', 689 'cargo, Reserved for future use':'75', 690 'cargo, Reserved for future use':'76', 691 'cargo, Reserved for future use':'77', 692 'cargo, Reserved for future use':'78', 693 'cargo, No additional information':'79', 694 'tanker, all ships of this type':'80', 695 'tanker, Hazardous catagory A':'81', 696 'tanker, Hazardous catagory B':'82', 697 'tanker, Hazardous catagory C':'83', 698 'tanker, Hazardous catagory D':'84', 699 'tanker, Reserved for future use':'85', 700 'tanker, Reserved for future use':'86', 701 'tanker, Reserved for future use':'87', 702 'tanker, Reserved for future use':'88', 703 'tanker, No additional information':'89', 704 'other type, all ships of this type':'90', 705 'other type, Hazardous catagory A':'91', 706 'other type, Hazardous catagory B':'92', 707 'other type, Hazardous catagory C':'93', 708 'other type, Hazardous catagory D':'94', 709 'other type, Reserved for future use':'95', 710 'other type, Reserved for future use':'96', 711 'other type, Reserved for future use':'97', 712 'other type, Reserved for future use':'98', 713 'other type, No additional information':'99', 714 } #shipandcargoEncodeLut 715 716 shipandcargoDecodeLut = { 717 '20':'Wing in ground (WIG), all ships of this type', 718 '21':'Wing in ground (WIG), Hazardous catagory A', 719 '22':'Wing in ground (WIG), Hazardous catagory B', 720 '23':'Wing in ground (WIG), Hazardous catagory C', 721 '24':'Wing in ground (WIG), Hazardous catagory D', 722 '25':'Wing in ground (WIG), Reserved for future use', 723 '26':'Wing in ground (WIG), Reserved for future use', 724 '27':'Wing in ground (WIG), Reserved for future use', 725 '28':'Wing in ground (WIG), Reserved for future use', 726 '29':'Wing in ground (WIG), No additional information', 727 '30':'fishing', 728 '31':'towing', 729 '32':'towing length exceeds 200m or breadth exceeds 25m', 730 '33':'dredging or underwater ops', 731 '34':'diving ops', 732 '35':'military ops', 733 '36':'sailing', 734 '37':'pleasure craft', 735 '38':'reserved', 736 '39':'reserved', 737 '40':'High speed craft (HSC), all ships of this type', 738 '41':'High speed craft (HSC), Hazardous catagory A', 739 '42':'High speed craft (HSC), Hazardous catagory B', 740 '43':'High speed craft (HSC), Hazardous catagory C', 741 '44':'High speed craft (HSC), Hazardous catagory D', 742 '45':'High speed craft (HSC), Reserved for future use', 743 '46':'High speed craft (HSC), Reserved for future use', 744 '47':'High speed craft (HSC), Reserved for future use', 745 '48':'High speed craft (HSC), Reserved for future use', 746 '49':'High speed craft (HSC), No additional information', 747 '50':'pilot vessel', 748 '51':'search and rescue vessel', 749 '52':'tug', 750 '53':'port tender', 751 '54':'anti-polution equipment', 752 '55':'law enforcement', 753 '56':'spare - local vessel', 754 '57':'spare - local vessel', 755 '58':'medical transport', 756 '59':'ship according to RR Resolution No. 18', 757 '60':'passenger, all ships of this type', 758 '61':'passenger, Hazardous catagory A', 759 '62':'passenger, Hazardous catagory B', 760 '63':'passenger, Hazardous catagory C', 761 '64':'passenger, Hazardous catagory D', 762 '65':'passenger, Reserved for future use', 763 '66':'passenger, Reserved for future use', 764 '67':'passenger, Reserved for future use', 765 '68':'passenger, Reserved for future use', 766 '69':'passenger, No additional information', 767 '70':'cargo, all ships of this type', 768 '71':'cargo, Hazardous catagory A', 769 '72':'cargo, Hazardous catagory B', 770 '73':'cargo, Hazardous catagory C', 771 '74':'cargo, Hazardous catagory D', 772 '75':'cargo, Reserved for future use', 773 '76':'cargo, Reserved for future use', 774 '77':'cargo, Reserved for future use', 775 '78':'cargo, Reserved for future use', 776 '79':'cargo, No additional information', 777 '80':'tanker, all ships of this type', 778 '81':'tanker, Hazardous catagory A', 779 '82':'tanker, Hazardous catagory B', 780 '83':'tanker, Hazardous catagory C', 781 '84':'tanker, Hazardous catagory D', 782 '85':'tanker, Reserved for future use', 783 '86':'tanker, Reserved for future use', 784 '87':'tanker, Reserved for future use', 785 '88':'tanker, Reserved for future use', 786 '89':'tanker, No additional information', 787 '90':'other type, all ships of this type', 788 '91':'other type, Hazardous catagory A', 789 '92':'other type, Hazardous catagory B', 790 '93':'other type, Hazardous catagory C', 791 '94':'other type, Hazardous catagory D', 792 '95':'other type, Reserved for future use', 793 '96':'other type, Reserved for future use', 794 '97':'other type, Reserved for future use', 795 '98':'other type, Reserved for future use', 796 '99':'other type, No additional information', 797 } # shipandcargoEncodeLut 798 799 dimCEncodeLut = { 800 '63 m or greater':'63', 801 } #dimCEncodeLut 802 803 dimCDecodeLut = { 804 '63':'63 m or greater', 805 } # dimCEncodeLut 806 807 dimDEncodeLut = { 808 '63 m or greater':'63', 809 } #dimDEncodeLut 810 811 dimDDecodeLut = { 812 '63':'63 m or greater', 813 } # dimDEncodeLut 814 815 fixtypeEncodeLut = { 816 'undefined':'0', 817 'GPS':'1', 818 'GLONASS':'2', 819 'combined GPS/GLONASS':'3', 820 'Loran-C':'4', 821 'Chayka':'5', 822 'integrated navigation system':'6', 823 'surveyed':'7', 824 } #fixtypeEncodeLut 825 826 fixtypeDecodeLut = { 827 '0':'undefined', 828 '1':'GPS', 829 '2':'GLONASS', 830 '3':'combined GPS/GLONASS', 831 '4':'Loran-C', 832 '5':'Chayka', 833 '6':'integrated navigation system', 834 '7':'surveyed', 835 } # fixtypeEncodeLut 836 837 dteEncodeLut = { 838 'available':'0', 839 'not available':'1', 840 } #dteEncodeLut 841 842 dteDecodeLut = { 843 '0':'available', 844 '1':'not available', 845 } # dteEncodeLut 846 847 ###################################################################### 848 # SQL SUPPORT 849 ###################################################################### 850
851 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 852 ,addCoastGuardFields=True 853 ,dbType='postgres' 854 ):
855 ''' 856 Return the SQL CREATE command for this message type 857 @param outfile: file like object to print to. 858 @param fields: which fields to put in the create. Defaults to all. 859 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 860 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 861 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 862 @type addCoastGuardFields: bool 863 @return: sql create string 864 @rtype: str 865 866 @see: sqlCreate 867 ''' 868 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
869
870 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
871 ''' 872 Return the sqlhelp object to create the table. 873 874 @param fields: which fields to put in the create. Defaults to all. 875 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 876 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 877 @type addCoastGuardFields: bool 878 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 879 @return: An object that can be used to generate a return 880 @rtype: sqlhelp.create 881 ''' 882 if None == fields: fields = fieldList 883 import sqlhelp 884 c = sqlhelp.create('shipdata',dbType=dbType) 885 c.addPrimaryKey() 886 if 'MessageID' in fields: c.addInt ('MessageID') 887 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator') 888 if 'UserID' in fields: c.addInt ('UserID') 889 if 'AISversion' in fields: c.addInt ('AISversion') 890 if 'IMOnumber' in fields: c.addInt ('IMOnumber') 891 if 'callsign' in fields: c.addVarChar('callsign',7) 892 if 'name' in fields: c.addVarChar('name',20) 893 if 'shipandcargo' in fields: c.addInt ('shipandcargo') 894 if 'dimA' in fields: c.addInt ('dimA') 895 if 'dimB' in fields: c.addInt ('dimB') 896 if 'dimC' in fields: c.addInt ('dimC') 897 if 'dimD' in fields: c.addInt ('dimD') 898 if 'fixtype' in fields: c.addInt ('fixtype') 899 if 'ETAminute' in fields: c.addInt ('ETAminute') 900 if 'ETAhour' in fields: c.addInt ('ETAhour') 901 if 'ETAday' in fields: c.addInt ('ETAday') 902 if 'ETAmonth' in fields: c.addInt ('ETAmonth') 903 if 'draught' in fields: c.addDecimal('draught',3,1) 904 if 'destination' in fields: c.addVarChar('destination',20) 905 if 'dte' in fields: c.addInt ('dte') 906 if 'Spare' in fields: c.addInt ('Spare') 907 908 if addCoastGuardFields: 909 # c.addInt('cg_rssi') # Relative signal strength indicator 910 # c.addInt('cg_d') # dBm receive strength 911 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 912 # c.addInt('cg_S') # Slot received in 913 # c.addVarChar('cg_x',10) # Idonno 914 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 915 c.addInt('cg_sec') # UTC seconds since the epoch 916 917 c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream 918 919 return c
920
921 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
922 ''' 923 Return the SQL INSERT command for this message type 924 @param params: dictionary of values keyed by field name 925 @param outfile: file like object to print to. 926 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 927 @return: sql create string 928 @rtype: str 929 930 @see: sqlCreate 931 ''' 932 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
933 934
935 -def sqlInsert(params,extraParams=None,dbType='postgres'):
936 ''' 937 Give the SQL INSERT statement 938 @param params: dict keyed by field name of values 939 @param extraParams: any extra fields that you have created beyond the normal ais message fields 940 @rtype: sqlhelp.insert 941 @return: insert class instance 942 @todo: allow optional type checking of params? 943 @warning: this will take invalid keys happily and do what??? 944 ''' 945 import sqlhelp 946 i = sqlhelp.insert('shipdata',dbType=dbType) 947 948 if dbType=='postgres': 949 finished = [] 950 for key in params: 951 if key in finished: 952 continue 953 954 if key not in toPgFields and key not in fromPgFields: 955 if type(params[key])==Decimal: i.add(key,float(params[key])) 956 else: i.add(key,params[key]) 957 else: 958 if key in fromPgFields: 959 val = params[key] 960 # Had better be a WKT type like POINT(-88.1 30.321) 961 i.addPostGIS(key,val) 962 finished.append(key) 963 else: 964 # Need to construct the type. 965 pgName = toPgFields[key] 966 #valStr='GeomFromText(\''+pgTypes[pgName]+'(' 967 valStr=pgTypes[pgName]+'(' 968 vals = [] 969 for nonPgKey in fromPgFields[pgName]: 970 vals.append(str(params[nonPgKey])) 971 finished.append(nonPgKey) 972 valStr+=' '.join(vals)+')' 973 i.addPostGIS(pgName,valStr) 974 else: 975 for key in params: 976 if type(params[key])==Decimal: i.add(key,float(params[key])) 977 else: i.add(key,params[key]) 978 979 if None != extraParams: 980 for key in extraParams: 981 i.add(key,extraParams[key]) 982 983 return i
984 985 986 ###################################################################### 987 # UNIT TESTING 988 ###################################################################### 989 import unittest
990 -def testParams():
991 '''Return a params file base on the testvalue tags. 992 @rtype: dict 993 @return: params based on testvalue tags 994 ''' 995 params = {} 996 params['MessageID'] = 5 997 params['RepeatIndicator'] = 1 998 params['UserID'] = 1193046 999 params['AISversion'] = 0 1000 params['IMOnumber'] = 3210 1001 params['callsign'] = 'PIRATE1' 1002 params['name'] = 'BLACK PEARL@@@@@@@@@' 1003 params['shipandcargo'] = 55 1004 params['dimA'] = 10 1005 params['dimB'] = 11 1006 params['dimC'] = 12 1007 params['dimD'] = 13 1008 params['fixtype'] = 1 1009 params['ETAminute'] = 54 1010 params['ETAhour'] = 9 1011 params['ETAday'] = 28 1012 params['ETAmonth'] = 2 1013 params['draught'] = Decimal('21.1') 1014 params['destination'] = 'NOWHERE@@@@@@@@@@@@@' 1015 params['dte'] = 0 1016 params['Spare'] = 0 1017 1018 return params
1019
1020 -class Testshipdata(unittest.TestCase):
1021 '''Use testvalue tag text from each type to build test case the shipdata message'''
1022 - def testEncodeDecode(self):
1023 1024 params = testParams() 1025 bits = encode(params) 1026 r = decode(bits) 1027 1028 # Check that each parameter came through ok. 1029 self.failUnlessEqual(r['MessageID'],params['MessageID']) 1030 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 1031 self.failUnlessEqual(r['UserID'],params['UserID']) 1032 self.failUnlessEqual(r['AISversion'],params['AISversion']) 1033 self.failUnlessEqual(r['IMOnumber'],params['IMOnumber']) 1034 self.failUnlessEqual(r['callsign'],params['callsign']) 1035 self.failUnlessEqual(r['name'],params['name']) 1036 self.failUnlessEqual(r['shipandcargo'],params['shipandcargo']) 1037 self.failUnlessEqual(r['dimA'],params['dimA']) 1038 self.failUnlessEqual(r['dimB'],params['dimB']) 1039 self.failUnlessEqual(r['dimC'],params['dimC']) 1040 self.failUnlessEqual(r['dimD'],params['dimD']) 1041 self.failUnlessEqual(r['fixtype'],params['fixtype']) 1042 self.failUnlessEqual(r['ETAminute'],params['ETAminute']) 1043 self.failUnlessEqual(r['ETAhour'],params['ETAhour']) 1044 self.failUnlessEqual(r['ETAday'],params['ETAday']) 1045 self.failUnlessEqual(r['ETAmonth'],params['ETAmonth']) 1046 self.failUnlessAlmostEqual(r['draught'],params['draught'],1) 1047 self.failUnlessEqual(r['destination'],params['destination']) 1048 self.failUnlessEqual(r['dte'],params['dte']) 1049 self.failUnlessEqual(r['Spare'],params['Spare'])
1050
1051 -def addMsgOptions(parser):
1052 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 1053 help='decode a "shipdata" AIS message') 1054 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 1055 help='encode a "shipdata" AIS message') 1056 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int' 1057 ,help='Field parameter value [default: %default]') 1058 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int' 1059 ,help='Field parameter value [default: %default]') 1060 parser.add_option('--AISversion-field', dest='AISversionField',default=0,metavar='uint',type='int' 1061 ,help='Field parameter value [default: %default]') 1062 parser.add_option('--IMOnumber-field', dest='IMOnumberField',default=0,metavar='uint',type='int' 1063 ,help='Field parameter value [default: %default]') 1064 parser.add_option('--callsign-field', dest='callsignField',default='@@@@@@@',metavar='aisstr6',type='string' 1065 ,help='Field parameter value [default: %default]') 1066 parser.add_option('--name-field', dest='nameField',default='@@@@@@@@@@@@@@@@@@@@',metavar='aisstr6',type='string' 1067 ,help='Field parameter value [default: %default]') 1068 parser.add_option('--shipandcargo-field', dest='shipandcargoField',default=0,metavar='uint',type='int' 1069 ,help='Field parameter value [default: %default]') 1070 parser.add_option('--dimA-field', dest='dimAField',default=0,metavar='uint',type='int' 1071 ,help='Field parameter value [default: %default]') 1072 parser.add_option('--dimB-field', dest='dimBField',default=0,metavar='uint',type='int' 1073 ,help='Field parameter value [default: %default]') 1074 parser.add_option('--dimC-field', dest='dimCField',default=0,metavar='uint',type='int' 1075 ,help='Field parameter value [default: %default]') 1076 parser.add_option('--dimD-field', dest='dimDField',default=0,metavar='uint',type='int' 1077 ,help='Field parameter value [default: %default]') 1078 parser.add_option('--fixtype-field', dest='fixtypeField',default=0,metavar='uint',type='int' 1079 ,help='Field parameter value [default: %default]') 1080 parser.add_option('--ETAminute-field', dest='ETAminuteField',default=60,metavar='uint',type='int' 1081 ,help='Field parameter value [default: %default]') 1082 parser.add_option('--ETAhour-field', dest='ETAhourField',default=24,metavar='uint',type='int' 1083 ,help='Field parameter value [default: %default]') 1084 parser.add_option('--ETAday-field', dest='ETAdayField',default=0,metavar='uint',type='int' 1085 ,help='Field parameter value [default: %default]') 1086 parser.add_option('--ETAmonth-field', dest='ETAmonthField',default=0,metavar='uint',type='int' 1087 ,help='Field parameter value [default: %default]') 1088 parser.add_option('--draught-field', dest='draughtField',default=Decimal('0'),metavar='udecimal',type='string' 1089 ,help='Field parameter value [default: %default]') 1090 parser.add_option('--destination-field', dest='destinationField',default='@@@@@@@@@@@@@@@@@@@@',metavar='aisstr6',type='string' 1091 ,help='Field parameter value [default: %default]') 1092 parser.add_option('--dte-field', dest='dteField',metavar='uint',type='int' 1093 ,help='Field parameter value [default: %default]')
1094 1095 ############################################################ 1096 if __name__=='__main__': 1097 1098 from optparse import OptionParser 1099 parser = OptionParser(usage="%prog [options]", 1100 version="%prog "+__version__) 1101 1102 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 1103 help='run the documentation tests') 1104 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 1105 help='run the unit tests') 1106 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 1107 help='Make the test output verbose') 1108 1109 # FIX: remove nmea from binary messages. No way to build the whole packet? 1110 # FIX: or build the surrounding msg 8 for a broadcast? 1111 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 1112 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 1113 ,default='nmeapayload' 1114 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 1115 1116 1117 outputChoices = ('std','html','csv','sql' ) 1118 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 1119 ,default='std' 1120 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 1121 1122 parser.add_option('-o','--output',dest='outputFileName',default=None, 1123 help='Name of the python file to write [default: stdout]') 1124 1125 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 1126 choices=fieldList, 1127 help='Which fields to include in the output. Currently only for csv output [default: all]') 1128 1129 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 1130 help='Print the field name for csv') 1131 1132 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 1133 help='Print out an sql create command for the table.') 1134 1135 dbChoices = ('sqlite','postgres') 1136 parser.add_option('-D','--db-type',dest='dbType',default='postgres' 1137 ,choices=dbChoices,type='choice' 1138 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 1139 1140 addMsgOptions(parser) 1141 1142 (options,args) = parser.parse_args() 1143 success=True 1144 1145 if options.doctest: 1146 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 1147 sys.argv= [sys.argv[0]] 1148 if options.verbose: sys.argv.append('-v') 1149 import doctest 1150 numfail,numtests=doctest.testmod() 1151 if numfail==0: print 'ok' 1152 else: 1153 print 'FAILED' 1154 success=False 1155 1156 if not success: sys.exit('Something Failed') 1157 del success # Hide success from epydoc 1158 1159 if options.unittest: 1160 sys.argv = [sys.argv[0]] 1161 if options.verbose: sys.argv.append('-v') 1162 unittest.main() 1163 1164 outfile = sys.stdout 1165 if None!=options.outputFileName: 1166 outfile = file(options.outputFileName,'w') 1167 1168 1169 if options.doEncode: 1170 # First make sure all non required options are specified 1171 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField") 1172 if None==options.UserIDField: parser.error("missing value for UserIDField") 1173 if None==options.AISversionField: parser.error("missing value for AISversionField") 1174 if None==options.IMOnumberField: parser.error("missing value for IMOnumberField") 1175 if None==options.callsignField: parser.error("missing value for callsignField") 1176 if None==options.nameField: parser.error("missing value for nameField") 1177 if None==options.shipandcargoField: parser.error("missing value for shipandcargoField") 1178 if None==options.dimAField: parser.error("missing value for dimAField") 1179 if None==options.dimBField: parser.error("missing value for dimBField") 1180 if None==options.dimCField: parser.error("missing value for dimCField") 1181 if None==options.dimDField: parser.error("missing value for dimDField") 1182 if None==options.fixtypeField: parser.error("missing value for fixtypeField") 1183 if None==options.ETAminuteField: parser.error("missing value for ETAminuteField") 1184 if None==options.ETAhourField: parser.error("missing value for ETAhourField") 1185 if None==options.ETAdayField: parser.error("missing value for ETAdayField") 1186 if None==options.ETAmonthField: parser.error("missing value for ETAmonthField") 1187 if None==options.draughtField: parser.error("missing value for draughtField") 1188 if None==options.destinationField: parser.error("missing value for destinationField") 1189 if None==options.dteField: parser.error("missing value for dteField") 1190 msgDict={ 1191 'MessageID': '5', 1192 'RepeatIndicator': options.RepeatIndicatorField, 1193 'UserID': options.UserIDField, 1194 'AISversion': options.AISversionField, 1195 'IMOnumber': options.IMOnumberField, 1196 'callsign': options.callsignField, 1197 'name': options.nameField, 1198 'shipandcargo': options.shipandcargoField, 1199 'dimA': options.dimAField, 1200 'dimB': options.dimBField, 1201 'dimC': options.dimCField, 1202 'dimD': options.dimDField, 1203 'fixtype': options.fixtypeField, 1204 'ETAminute': options.ETAminuteField, 1205 'ETAhour': options.ETAhourField, 1206 'ETAday': options.ETAdayField, 1207 'ETAmonth': options.ETAmonthField, 1208 'draught': options.draughtField, 1209 'destination': options.destinationField, 1210 'dte': options.dteField, 1211 'Spare': '0', 1212 } 1213 1214 bits = encode(msgDict) 1215 if 'binary'==options.ioType: print str(bits) 1216 elif 'nmeapayload'==options.ioType: 1217 # FIX: figure out if this might be necessary at compile time 1218 print "bitLen",len(bits) 1219 bitLen=len(bits) 1220 if bitLen%6!=0: 1221 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 1222 print "result:",binary.bitvectoais6(bits)[0] 1223 1224 1225 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 1226 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 1227 else: sys.exit('ERROR: unknown ioType. Help!') 1228 1229 1230 if options.sqlCreate: 1231 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 1232 1233 if options.printCsvfieldList: 1234 # Make a csv separated list of fields that will be displayed for csv 1235 if None == options.fieldList: options.fieldList = fieldList 1236 import StringIO 1237 buf = StringIO.StringIO() 1238 for field in options.fieldList: 1239 buf.write(field+',') 1240 result = buf.getvalue() 1241 if result[-1] == ',': print result[:-1] 1242 else: print result 1243 1244 if options.doDecode: 1245 for msg in args: 1246 bv = None 1247 1248 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 1249 # Found nmea 1250 # FIX: do checksum 1251 bv = binary.ais6tobitvec(msg.split(',')[5]) 1252 else: # either binary or nmeapayload... expect mostly nmeapayloads 1253 # assumes that an all 0 and 1 string can not be a nmeapayload 1254 binaryMsg=True 1255 for c in msg: 1256 if c not in ('0','1'): 1257 binaryMsg=False 1258 break 1259 if binaryMsg: 1260 bv = BitVector(bitstring=msg) 1261 else: # nmeapayload 1262 bv = binary.ais6tobitvec(msg) 1263 1264 printFields(decode(bv) 1265 ,out=outfile 1266 ,format=options.outputType 1267 ,fieldList=options.fieldList 1268 ,dbType=options.dbType 1269 ) 1270