Package ais :: Package sls :: Module waterflow
[hide private]
[frames] | no frames]

Source Code for Module ais.sls.waterflow

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 4791 $'.split()[1] 
  4  __date__ = '$Date: 2007-03-30 $'.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          'time_month', 
 51          'time_day', 
 52          'time_hour', 
 53          'time_min', 
 54          'stationid', 
 55          'pos_longitude', 
 56          'pos_latitude', 
 57          'flow', 
 58          'reserved', 
 59  ) 
 60   
 61  fieldListPostgres = ( 
 62          'time_month', 
 63          'time_day', 
 64          'time_hour', 
 65          'time_min', 
 66          'stationid', 
 67          'pos_longitude', 
 68          'pos_latitude', 
 69          'flow', 
 70          'reserved', 
 71  ) 
 72   
 73  toPgFields = { 
 74  } 
 75  ''' 
 76  Go to the Postgis field names from the straight field name 
 77  ''' 
 78   
 79  fromPgFields = { 
 80  } 
 81  ''' 
 82  Go from the Postgis field names to the straight field name 
 83  ''' 
 84   
 85  pgTypes = { 
 86  } 
 87  ''' 
 88  Lookup table for each postgis field name to get its type. 
 89  ''' 
 90   
91 -def encode(params, validate=False):
92 '''Create a sls_wind binary message payload to pack into an AIS Msg sls_wind. 93 94 Fields in params: 95 - time_month(uint): Time tag of measurement month 1..12 96 - time_day(uint): Time tag of measurement day of the month 1..31 97 - time_hour(uint): Time tag of measurement UTC hours 0..23 98 - time_min(uint): Time tag of measurement minutes 99 - stationid(aisstr6): Character identifier of the station 100 - pos_longitude(decimal): Location of measurement East West location 101 - pos_latitude(decimal): Location of measurement North South location 102 - flow(uint): Water flow 103 - reserved(uint): Reserved bits for future use (field automatically set to "0") 104 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 105 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 106 @rtype: BitVector 107 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 108 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 109 ''' 110 111 bvList = [] 112 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_month']),4)) 113 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_day']),5)) 114 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_hour']),5)) 115 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_min']),6)) 116 if 'stationid' in params: 117 bvList.append(aisstring.encode(params['stationid'],42)) 118 else: 119 bvList.append(aisstring.encode('@@@@@@@',42)) 120 if 'pos_longitude' in params: 121 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_longitude'])*Decimal('60000')),25)) 122 else: 123 bvList.append(binary.bvFromSignedInt(10860000,25)) 124 if 'pos_latitude' in params: 125 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_latitude'])*Decimal('60000')),24)) 126 else: 127 bvList.append(binary.bvFromSignedInt(5460000,24)) 128 if 'flow' in params: 129 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['flow']),10)) 130 else: 131 bvList.append(binary.setBitVectorSize(BitVector(intVal=16383),10)) 132 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),19)) 133 134 return binary.joinBV(bvList)
135
136 -def decode(bv, validate=False):
137 '''Unpack a sls_wind message 138 139 Fields in params: 140 - time_month(uint): Time tag of measurement month 1..12 141 - time_day(uint): Time tag of measurement day of the month 1..31 142 - time_hour(uint): Time tag of measurement UTC hours 0..23 143 - time_min(uint): Time tag of measurement minutes 144 - stationid(aisstr6): Character identifier of the station 145 - pos_longitude(decimal): Location of measurement East West location 146 - pos_latitude(decimal): Location of measurement North South location 147 - flow(uint): Water flow 148 - reserved(uint): Reserved bits for future use (field automatically set to "0") 149 @type bv: BitVector 150 @param bv: Bits defining a message 151 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 152 @rtype: dict 153 @return: params 154 ''' 155 156 #Would be nice to check the bit count here.. 157 #if validate: 158 # assert (len(bv)==FIX: SOME NUMBER) 159 r = {} 160 r['time_month']=int(bv[0:4]) 161 r['time_day']=int(bv[4:9]) 162 r['time_hour']=int(bv[9:14]) 163 r['time_min']=int(bv[14:20]) 164 r['stationid']=aisstring.decode(bv[20:62]) 165 r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000') 166 r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000') 167 r['flow']=int(bv[111:121]) 168 r['reserved']=0 169 return r
170
171 -def decodetime_month(bv, validate=False):
172 return int(bv[0:4])
173
174 -def decodetime_day(bv, validate=False):
175 return int(bv[4:9])
176
177 -def decodetime_hour(bv, validate=False):
178 return int(bv[9:14])
179
180 -def decodetime_min(bv, validate=False):
181 return int(bv[14:20])
182
183 -def decodestationid(bv, validate=False):
184 return aisstring.decode(bv[20:62])
185
186 -def decodepos_longitude(bv, validate=False):
187 return Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
188
189 -def decodepos_latitude(bv, validate=False):
190 return Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
191
192 -def decodeflow(bv, validate=False):
193 return int(bv[111:121])
194
195 -def decodereserved(bv, validate=False):
196 return 0
197 198
199 -def printHtml(params, out=sys.stdout):
200 out.write("<h3>sls_wind<h3>\n") 201 out.write("<table border=\"1\">\n") 202 out.write("<tr bgcolor=\"orange\">\n") 203 out.write("<th align=\"left\">Field Name</th>\n") 204 out.write("<th align=\"left\">Type</th>\n") 205 out.write("<th align=\"left\">Value</th>\n") 206 out.write("<th align=\"left\">Value in Lookup Table</th>\n") 207 out.write("<th align=\"left\">Units</th>\n") 208 out.write("\n") 209 out.write("<tr>\n") 210 out.write("<td>time_month</td>\n") 211 out.write("<td>uint</td>\n") 212 if 'time_month' in params: 213 out.write(" <td>"+str(params['time_month'])+"</td>\n") 214 out.write(" <td>"+str(params['time_month'])+"</td>\n") 215 out.write("</tr>\n") 216 out.write("\n") 217 out.write("<tr>\n") 218 out.write("<td>time_day</td>\n") 219 out.write("<td>uint</td>\n") 220 if 'time_day' in params: 221 out.write(" <td>"+str(params['time_day'])+"</td>\n") 222 out.write(" <td>"+str(params['time_day'])+"</td>\n") 223 out.write("</tr>\n") 224 out.write("\n") 225 out.write("<tr>\n") 226 out.write("<td>time_hour</td>\n") 227 out.write("<td>uint</td>\n") 228 if 'time_hour' in params: 229 out.write(" <td>"+str(params['time_hour'])+"</td>\n") 230 out.write(" <td>"+str(params['time_hour'])+"</td>\n") 231 out.write("</tr>\n") 232 out.write("\n") 233 out.write("<tr>\n") 234 out.write("<td>time_min</td>\n") 235 out.write("<td>uint</td>\n") 236 if 'time_min' in params: 237 out.write(" <td>"+str(params['time_min'])+"</td>\n") 238 out.write(" <td>"+str(params['time_min'])+"</td>\n") 239 out.write("</tr>\n") 240 out.write("\n") 241 out.write("<tr>\n") 242 out.write("<td>stationid</td>\n") 243 out.write("<td>aisstr6</td>\n") 244 if 'stationid' in params: 245 out.write(" <td>"+str(params['stationid'])+"</td>\n") 246 out.write(" <td>"+str(params['stationid'])+"</td>\n") 247 out.write("</tr>\n") 248 out.write("\n") 249 out.write("<tr>\n") 250 out.write("<td>pos_longitude</td>\n") 251 out.write("<td>decimal</td>\n") 252 if 'pos_longitude' in params: 253 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n") 254 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n") 255 out.write("<td>degrees</td>\n") 256 out.write("</tr>\n") 257 out.write("\n") 258 out.write("<tr>\n") 259 out.write("<td>pos_latitude</td>\n") 260 out.write("<td>decimal</td>\n") 261 if 'pos_latitude' in params: 262 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n") 263 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n") 264 out.write("<td>degrees</td>\n") 265 out.write("</tr>\n") 266 out.write("\n") 267 out.write("<tr>\n") 268 out.write("<td>flow</td>\n") 269 out.write("<td>uint</td>\n") 270 if 'flow' in params: 271 out.write(" <td>"+str(params['flow'])+"</td>\n") 272 out.write(" <td>"+str(params['flow'])+"</td>\n") 273 out.write("<td>m^3/s</td>\n") 274 out.write("</tr>\n") 275 out.write("\n") 276 out.write("<tr>\n") 277 out.write("<td>reserved</td>\n") 278 out.write("<td>uint</td>\n") 279 if 'reserved' in params: 280 out.write(" <td>"+str(params['reserved'])+"</td>\n") 281 out.write(" <td>"+str(params['reserved'])+"</td>\n") 282 out.write("</tr>\n") 283 out.write("</table>\n")
284 285
286 -def printKml(params, out=sys.stdout):
287 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer''' 288 out.write("\ <Placemark>\n") 289 out.write("\t <name>"+str(params['stationid'])+"</name>\n") 290 out.write("\t\t<description>\n") 291 import StringIO 292 buf = StringIO.StringIO() 293 printHtml(params,buf) 294 import cgi 295 out.write(cgi.escape(buf.getvalue())) 296 out.write("\t\t</description>\n") 297 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n") 298 out.write("\t\t<Point>\n") 299 out.write("\t\t\t<coordinates>") 300 out.write(str(params['pos_longitude'])) 301 out.write(',') 302 out.write(str(params['pos_latitude'])) 303 out.write(",0</coordinates>\n") 304 out.write("\t\t</Point>\n") 305 out.write("\t</Placemark>\n")
306
307 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
308 '''Print a sls_wind message to stdout. 309 310 Fields in params: 311 - time_month(uint): Time tag of measurement month 1..12 312 - time_day(uint): Time tag of measurement day of the month 1..31 313 - time_hour(uint): Time tag of measurement UTC hours 0..23 314 - time_min(uint): Time tag of measurement minutes 315 - stationid(aisstr6): Character identifier of the station 316 - pos_longitude(decimal): Location of measurement East West location 317 - pos_latitude(decimal): Location of measurement North South location 318 - flow(uint): Water flow 319 - reserved(uint): Reserved bits for future use (field automatically set to "0") 320 @param params: Dictionary of field names/values. 321 @param out: File like object to write to 322 @rtype: stdout 323 @return: text to out 324 ''' 325 326 if 'std'==format: 327 out.write("sls_wind:\n") 328 if 'time_month' in params: out.write(" time_month: "+str(params['time_month'])+"\n") 329 if 'time_day' in params: out.write(" time_day: "+str(params['time_day'])+"\n") 330 if 'time_hour' in params: out.write(" time_hour: "+str(params['time_hour'])+"\n") 331 if 'time_min' in params: out.write(" time_min: "+str(params['time_min'])+"\n") 332 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n") 333 if 'pos_longitude' in params: out.write(" pos_longitude: "+str(params['pos_longitude'])+"\n") 334 if 'pos_latitude' in params: out.write(" pos_latitude: "+str(params['pos_latitude'])+"\n") 335 if 'flow' in params: out.write(" flow: "+str(params['flow'])+"\n") 336 if 'reserved' in params: out.write(" reserved: "+str(params['reserved'])+"\n") 337 elif 'csv'==format: 338 if None == options.fieldList: 339 options.fieldList = fieldList 340 needComma = False; 341 for field in fieldList: 342 if needComma: out.write(',') 343 needComma = True 344 if field in params: 345 out.write(str(params[field])) 346 # else: leave it empty 347 out.write("\n") 348 elif 'html'==format: 349 printHtml(params,out) 350 elif 'sql'==format: 351 sqlInsertStr(params,out,dbType=dbType) 352 elif 'kml'==format: 353 printKml(params,out) 354 elif 'kml-full'==format: 355 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") 356 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n") 357 out.write("<Document>\n") 358 out.write(" <name>sls_wind</name>\n") 359 printKml(params,out) 360 out.write("</Document>\n") 361 out.write("</kml>\n") 362 else: 363 print "ERROR: unknown format:",format 364 assert False 365 366 return # Nothing to return
367 368 ###################################################################### 369 # SQL SUPPORT 370 ###################################################################### 371
372 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 373 ,addCoastGuardFields=True 374 ,dbType='postgres' 375 ):
376 ''' 377 Return the SQL CREATE command for this message type 378 @param outfile: file like object to print to. 379 @param fields: which fields to put in the create. Defaults to all. 380 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 381 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 382 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 383 @type addCoastGuardFields: bool 384 @return: sql create string 385 @rtype: str 386 387 @see: sqlCreate 388 ''' 389 # FIX: should this sqlCreate be the same as in LaTeX (createFuncName) rather than hard coded? 390 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
391
392 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
393 ''' 394 Return the sqlhelp object to create the table. 395 396 @param fields: which fields to put in the create. Defaults to all. 397 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 398 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 399 @type addCoastGuardFields: bool 400 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 401 @return: An object that can be used to generate a return 402 @rtype: sqlhelp.create 403 ''' 404 if None == fields: fields = fieldList 405 import sqlhelp 406 c = sqlhelp.create('sls_wind',dbType=dbType) 407 c.addPrimaryKey() 408 if 'time_month' in fields: c.addInt ('time_month') 409 if 'time_day' in fields: c.addInt ('time_day') 410 if 'time_hour' in fields: c.addInt ('time_hour') 411 if 'time_min' in fields: c.addInt ('time_min') 412 if 'stationid' in fields: c.addVarChar('stationid',7) 413 if 'pos_longitude' in fields: c.addDecimal('pos_longitude',7,4) 414 if 'pos_latitude' in fields: c.addDecimal('pos_latitude',7,4) 415 if 'flow' in fields: c.addInt ('flow') 416 if 'reserved' in fields: c.addInt ('reserved') 417 418 if addCoastGuardFields: 419 # c.addInt('cg_rssi') # Relative signal strength indicator 420 # c.addInt('cg_d') # dBm receive strength 421 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 422 # c.addInt('cg_S') # Slot received in 423 # c.addVarChar('cg_x',10) # Idonno 424 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 425 c.addInt('cg_sec') # UTC seconds since the epoch 426 427 c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream 428 429 return c
430
431 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
432 ''' 433 Return the SQL INSERT command for this message type 434 @param params: dictionary of values keyed by field name 435 @param outfile: file like object to print to. 436 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 437 @return: sql create string 438 @rtype: str 439 440 @see: sqlCreate 441 ''' 442 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
443 444
445 -def sqlInsert(params,extraParams=None,dbType='postgres'):
446 ''' 447 Give the SQL INSERT statement 448 @param params: dict keyed by field name of values 449 @param extraParams: any extra fields that you have created beyond the normal ais message fields 450 @rtype: sqlhelp.insert 451 @return: insert class instance 452 @todo: allow optional type checking of params? 453 @warning: this will take invalid keys happily and do what??? 454 ''' 455 import sqlhelp 456 i = sqlhelp.insert('sls_wind',dbType=dbType) 457 458 if dbType=='postgres': 459 finished = [] 460 for key in params: 461 if key in finished: 462 continue 463 464 if key not in toPgFields and key not in fromPgFields: 465 if type(params[key])==Decimal: i.add(key,float(params[key])) 466 else: i.add(key,params[key]) 467 else: 468 if key in fromPgFields: 469 val = params[key] 470 # Had better be a WKT type like POINT(-88.1 30.321) 471 i.addPostGIS(key,val) 472 finished.append(key) 473 else: 474 # Need to construct the type. 475 pgName = toPgFields[key] 476 #valStr='GeomFromText(\''+pgTypes[pgName]+'(' 477 valStr=pgTypes[pgName]+'(' 478 vals = [] 479 for nonPgKey in fromPgFields[pgName]: 480 vals.append(str(params[nonPgKey])) 481 finished.append(nonPgKey) 482 valStr+=' '.join(vals)+')' 483 i.addPostGIS(pgName,valStr) 484 else: 485 for key in params: 486 if type(params[key])==Decimal: i.add(key,float(params[key])) 487 else: i.add(key,params[key]) 488 489 if None != extraParams: 490 for key in extraParams: 491 i.add(key,extraParams[key]) 492 493 return i
494 ###################################################################### 495 # LATEX SUPPORT 496 ###################################################################### 497
498 -def latexDefinitionTable(outfile=sys.stdout 499 ):
500 ''' 501 Return the LaTeX definition table for this message type 502 @param outfile: file like object to print to. 503 @param fields: which fields to put in the create. Defaults to all. 504 @return: LaTeX table string 505 @rtype: str 506 507 ''' 508 o = outfile 509 510 o.write(''' 511 \\begin{table}%[htb] 512 \\centering 513 \\begin{tabular}{|l|c|l|} 514 \\hline 515 Parameter & Number of bits & Description 516 \\\\ \\hline\\hline 517 time\_month & 4 & Time tag of measurement month 1..12 \\\\ \hline 518 time\_day & 5 & Time tag of measurement day of the month 1..31 \\\\ \hline 519 time\_hour & 5 & Time tag of measurement UTC hours 0..23 \\\\ \hline 520 time\_min & 6 & Time tag of measurement minutes \\\\ \hline 521 stationid & 42 & Character identifier of the station \\\\ \hline 522 pos\_longitude & 25 & Location of measurement East West location \\\\ \hline 523 pos\_latitude & 24 & Location of measurement North South location \\\\ \hline 524 flow & 10 & Water flow \\\\ \hline 525 reserved & 19 & Reserved bits for future use\\\\ \\hline \\hline 526 Total bits & 140 & Appears to take 1 slots with 28 pad bits to fill the last slot \\\\ \\hline 527 \\end{tabular} 528 \\caption{AIS message number 8: St Lawrance Seaway wind information} 529 \\label{tab:sls_wind} 530 \\end{table} 531 ''')
532 533 534 ###################################################################### 535 # UNIT TESTING 536 ###################################################################### 537 import unittest
538 -def testParams():
539 '''Return a params file base on the testvalue tags. 540 @rtype: dict 541 @return: params based on testvalue tags 542 ''' 543 params = {} 544 params['time_month'] = 2 545 params['time_day'] = 28 546 params['time_hour'] = 23 547 params['time_min'] = 45 548 params['stationid'] = 'A345678' 549 params['pos_longitude'] = Decimal('-122.16328') 550 params['pos_latitude'] = Decimal('37.42446') 551 params['flow'] = 43 552 params['reserved'] = 0 553 554 return params
555
556 -class Testsls_wind(unittest.TestCase):
557 '''Use testvalue tag text from each type to build test case the sls_wind message'''
558 - def testEncodeDecode(self):
559 560 params = testParams() 561 bits = encode(params) 562 r = decode(bits) 563 564 # Check that each parameter came through ok. 565 self.failUnlessEqual(r['time_month'],params['time_month']) 566 self.failUnlessEqual(r['time_day'],params['time_day']) 567 self.failUnlessEqual(r['time_hour'],params['time_hour']) 568 self.failUnlessEqual(r['time_min'],params['time_min']) 569 self.failUnlessEqual(r['stationid'],params['stationid']) 570 self.failUnlessAlmostEqual(r['pos_longitude'],params['pos_longitude'],4) 571 self.failUnlessAlmostEqual(r['pos_latitude'],params['pos_latitude'],4) 572 self.failUnlessEqual(r['flow'],params['flow']) 573 self.failUnlessEqual(r['reserved'],params['reserved'])
574
575 -def addMsgOptions(parser):
576 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 577 help='decode a "sls_wind" AIS message') 578 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 579 help='encode a "sls_wind" AIS message') 580 parser.add_option('--time_month-field', dest='time_monthField',metavar='uint',type='int' 581 ,help='Field parameter value [default: %default]') 582 parser.add_option('--time_day-field', dest='time_dayField',metavar='uint',type='int' 583 ,help='Field parameter value [default: %default]') 584 parser.add_option('--time_hour-field', dest='time_hourField',metavar='uint',type='int' 585 ,help='Field parameter value [default: %default]') 586 parser.add_option('--time_min-field', dest='time_minField',metavar='uint',type='int' 587 ,help='Field parameter value [default: %default]') 588 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string' 589 ,help='Field parameter value [default: %default]') 590 parser.add_option('--pos_longitude-field', dest='pos_longitudeField',default=Decimal('181'),metavar='decimal',type='string' 591 ,help='Field parameter value [default: %default]') 592 parser.add_option('--pos_latitude-field', dest='pos_latitudeField',default=Decimal('91'),metavar='decimal',type='string' 593 ,help='Field parameter value [default: %default]') 594 parser.add_option('--flow-field', dest='flowField',default=16383,metavar='uint',type='int' 595 ,help='Field parameter value [default: %default]')
596 597 ############################################################ 598 if __name__=='__main__': 599 600 from optparse import OptionParser 601 parser = OptionParser(usage="%prog [options]", 602 version="%prog "+__version__) 603 604 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 605 help='run the documentation tests') 606 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 607 help='run the unit tests') 608 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 609 help='Make the test output verbose') 610 611 # FIX: remove nmea from binary messages. No way to build the whole packet? 612 # FIX: or build the surrounding msg 8 for a broadcast? 613 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 614 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 615 ,default='nmeapayload' 616 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 617 618 619 outputChoices = ('std','html','csv','sql' , 'kml','kml-full') 620 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 621 ,default='std' 622 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 623 624 parser.add_option('-o','--output',dest='outputFileName',default=None, 625 help='Name of the python file to write [default: stdout]') 626 627 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 628 choices=fieldList, 629 help='Which fields to include in the output. Currently only for csv output [default: all]') 630 631 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 632 help='Print the field name for csv') 633 634 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 635 help='Print out an sql create command for the table.') 636 637 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true', 638 help='Print a LaTeX table of the type') 639 640 dbChoices = ('sqlite','postgres') 641 parser.add_option('-D','--db-type',dest='dbType',default='postgres' 642 ,choices=dbChoices,type='choice' 643 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 644 645 addMsgOptions(parser) 646 647 (options,args) = parser.parse_args() 648 success=True 649 650 if options.doctest: 651 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 652 sys.argv= [sys.argv[0]] 653 if options.verbose: sys.argv.append('-v') 654 import doctest 655 numfail,numtests=doctest.testmod() 656 if numfail==0: print 'ok' 657 else: 658 print 'FAILED' 659 success=False 660 661 if not success: sys.exit('Something Failed') 662 del success # Hide success from epydoc 663 664 if options.unittest: 665 sys.argv = [sys.argv[0]] 666 if options.verbose: sys.argv.append('-v') 667 unittest.main() 668 669 outfile = sys.stdout 670 if None!=options.outputFileName: 671 outfile = file(options.outputFileName,'w') 672 673 674 if options.doEncode: 675 # First make sure all non required options are specified 676 if None==options.time_monthField: parser.error("missing value for time_monthField") 677 if None==options.time_dayField: parser.error("missing value for time_dayField") 678 if None==options.time_hourField: parser.error("missing value for time_hourField") 679 if None==options.time_minField: parser.error("missing value for time_minField") 680 if None==options.stationidField: parser.error("missing value for stationidField") 681 if None==options.pos_longitudeField: parser.error("missing value for pos_longitudeField") 682 if None==options.pos_latitudeField: parser.error("missing value for pos_latitudeField") 683 if None==options.flowField: parser.error("missing value for flowField") 684 msgDict={ 685 'time_month': options.time_monthField, 686 'time_day': options.time_dayField, 687 'time_hour': options.time_hourField, 688 'time_min': options.time_minField, 689 'stationid': options.stationidField, 690 'pos_longitude': options.pos_longitudeField, 691 'pos_latitude': options.pos_latitudeField, 692 'flow': options.flowField, 693 'reserved': '0', 694 } 695 696 bits = encode(msgDict) 697 if 'binary'==options.ioType: print str(bits) 698 elif 'nmeapayload'==options.ioType: 699 # FIX: figure out if this might be necessary at compile time 700 print "bitLen",len(bits) 701 bitLen=len(bits) 702 if bitLen%6!=0: 703 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 704 print "result:",binary.bitvectoais6(bits)[0] 705 706 707 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 708 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 709 else: sys.exit('ERROR: unknown ioType. Help!') 710 711 712 if options.sqlCreate: 713 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 714 715 if options.latexDefinitionTable: 716 latexDefinitionTable(outfile) 717 718 if options.printCsvfieldList: 719 # Make a csv separated list of fields that will be displayed for csv 720 if None == options.fieldList: options.fieldList = fieldList 721 import StringIO 722 buf = StringIO.StringIO() 723 for field in options.fieldList: 724 buf.write(field+',') 725 result = buf.getvalue() 726 if result[-1] == ',': print result[:-1] 727 else: print result 728 729 if options.doDecode: 730 for msg in args: 731 bv = None 732 733 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 734 # Found nmea 735 # FIX: do checksum 736 bv = binary.ais6tobitvec(msg.split(',')[5]) 737 else: # either binary or nmeapayload... expect mostly nmeapayloads 738 # assumes that an all 0 and 1 string can not be a nmeapayload 739 binaryMsg=True 740 for c in msg: 741 if c not in ('0','1'): 742 binaryMsg=False 743 break 744 if binaryMsg: 745 bv = BitVector(bitstring=msg) 746 else: # nmeapayload 747 bv = binary.ais6tobitvec(msg) 748 749 printFields(decode(bv) 750 ,out=outfile 751 ,format=options.outputType 752 ,fieldList=options.fieldList 753 ,dbType=options.dbType 754 ) 755