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

Source Code for Module ais.sls.lockorder

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