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

Source Code for Module ais.sls.weatherreport

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