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

Source Code for Module ais.ais_msg_4

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