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: 2007-12-04 $'.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 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 672 ,addCoastGuardFields=True 673 ,dbType='postgres' 674 ):
675 ''' 676 Return the SQL CREATE command for this message type 677 @param outfile: file like object to print to. 678 @param fields: which fields to put in the create. Defaults to all. 679 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 680 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 681 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 682 @type addCoastGuardFields: bool 683 @return: sql create string 684 @rtype: str 685 686 @see: sqlCreate 687 ''' 688 # FIX: should this sqlCreate be the same as in LaTeX (createFuncName) rather than hard coded? 689 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
690
691 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
692 ''' 693 Return the sqlhelp object to create the table. 694 695 @param fields: which fields to put in the create. Defaults to all. 696 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 697 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 698 @type addCoastGuardFields: bool 699 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 700 @return: An object that can be used to generate a return 701 @rtype: sqlhelp.create 702 ''' 703 if None == fields: fields = fieldList 704 import sqlhelp 705 c = sqlhelp.create('bsreport',dbType=dbType) 706 c.addPrimaryKey() 707 if 'MessageID' in fields: c.addInt ('MessageID') 708 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator') 709 if 'UserID' in fields: c.addInt ('UserID') 710 if 'Time_year' in fields: c.addInt ('Time_year') 711 if 'Time_month' in fields: c.addInt ('Time_month') 712 if 'Time_day' in fields: c.addInt ('Time_day') 713 if 'Time_hour' in fields: c.addInt ('Time_hour') 714 if 'Time_min' in fields: c.addInt ('Time_min') 715 if 'Time_sec' in fields: c.addInt ('Time_sec') 716 if 'PositionAccuracy' in fields: c.addInt ('PositionAccuracy') 717 if dbType != 'postgres': 718 if 'Position_longitude' in fields: c.addDecimal('Position_longitude',8,5) 719 if dbType != 'postgres': 720 if 'Position_latitude' in fields: c.addDecimal('Position_latitude',8,5) 721 if 'fixtype' in fields: c.addInt ('fixtype') 722 if 'Spare' in fields: c.addInt ('Spare') 723 if 'RAIM' in fields: c.addBool('RAIM') 724 if 'state_syncstate' in fields: c.addInt ('state_syncstate') 725 if 'state_slottimeout' in fields: c.addInt ('state_slottimeout') 726 if 'state_slotoffset' in fields: c.addInt ('state_slotoffset') 727 728 if addCoastGuardFields: 729 # c.addInt('cg_rssi') # Relative signal strength indicator 730 # c.addInt('cg_d') # dBm receive strength 731 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 732 # c.addInt('cg_S') # Slot received in 733 # c.addVarChar('cg_x',10) # Idonno 734 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 735 c.addInt('cg_sec') # UTC seconds since the epoch 736 737 c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream 738 739 if dbType == 'postgres': 740 #--- EPSG 4326 : WGS 84 741 #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 '); 742 c.addPostGIS('Position','POINT',2,SRID=4326); 743 744 return c
745
746 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
747 ''' 748 Return the SQL INSERT command for this message type 749 @param params: dictionary of values keyed by field name 750 @param outfile: file like object to print to. 751 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 752 @return: sql create string 753 @rtype: str 754 755 @see: sqlCreate 756 ''' 757 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
758 759
760 -def sqlInsert(params,extraParams=None,dbType='postgres'):
761 ''' 762 Give the SQL INSERT statement 763 @param params: dict keyed by field name of values 764 @param extraParams: any extra fields that you have created beyond the normal ais message fields 765 @rtype: sqlhelp.insert 766 @return: insert class instance 767 @todo: allow optional type checking of params? 768 @warning: this will take invalid keys happily and do what??? 769 ''' 770 import sqlhelp 771 i = sqlhelp.insert('bsreport',dbType=dbType) 772 773 if dbType=='postgres': 774 finished = [] 775 for key in params: 776 if key in finished: 777 continue 778 779 if key not in toPgFields and key not in fromPgFields: 780 if type(params[key])==Decimal: i.add(key,float(params[key])) 781 else: i.add(key,params[key]) 782 else: 783 if key in fromPgFields: 784 val = params[key] 785 # Had better be a WKT type like POINT(-88.1 30.321) 786 i.addPostGIS(key,val) 787 finished.append(key) 788 else: 789 # Need to construct the type. 790 pgName = toPgFields[key] 791 #valStr='GeomFromText(\''+pgTypes[pgName]+'(' 792 valStr=pgTypes[pgName]+'(' 793 vals = [] 794 for nonPgKey in fromPgFields[pgName]: 795 vals.append(str(params[nonPgKey])) 796 finished.append(nonPgKey) 797 valStr+=' '.join(vals)+')' 798 i.addPostGIS(pgName,valStr) 799 else: 800 for key in params: 801 if type(params[key])==Decimal: i.add(key,float(params[key])) 802 else: i.add(key,params[key]) 803 804 if None != extraParams: 805 for key in extraParams: 806 i.add(key,extraParams[key]) 807 808 return i
809 810 ###################################################################### 811 # LATEX SUPPORT 812 ###################################################################### 813
814 -def latexDefinitionTable(outfile=sys.stdout 815 ):
816 ''' 817 Return the LaTeX definition table for this message type 818 @param outfile: file like object to print to. 819 @type outfile: file obj 820 @return: LaTeX table string via the outfile 821 @rtype: str 822 823 ''' 824 o = outfile 825 826 o.write(''' 827 \\begin{table}%[htb] 828 \\centering 829 \\begin{tabular}{|l|c|l|} 830 \\hline 831 Parameter & Number of bits & Description 832 \\\\ \\hline\\hline 833 MessageID & 6 & AIS message number. Must be 4 \\\\ \hline 834 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline 835 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline 836 Time\_year & 14 & Current time stamp year 1-9999 \\\\ \hline 837 Time\_month & 4 & Current time stamp month 1..12 \\\\ \hline 838 Time\_day & 5 & Current time stamp day of the month 1..31 \\\\ \hline 839 Time\_hour & 5 & Current time stamp UTC hours 0..23 \\\\ \hline 840 Time\_min & 6 & Current time stamp minutes \\\\ \hline 841 Time\_sec & 6 & Current time stamp seconds \\\\ \hline 842 PositionAccuracy & 1 & Accuracy of positioning fixes \\\\ \hline 843 Position\_longitude & 28 & Location of base station East West location \\\\ \hline 844 Position\_latitude & 27 & Location of base station North South location \\\\ \hline 845 fixtype & 4 & Method used for positioning \\\\ \hline 846 Spare & 10 & Not used. Should be set to zero. \\\\ \hline 847 RAIM & 1 & Receiver autonomous integrity monitoring flag \\\\ \hline 848 state\_syncstate & 2 & Communications State - SOTDMA Sycronization state \\\\ \hline 849 state\_slottimeout & 3 & Communications State - SOTDMA Frames remaining until a new slot is selected \\\\ \hline 850 state\_slotoffset & 14 & Communications State - SOTDMA In what slot will the next transmission occur. BROKEN\\\\ \\hline \\hline 851 Total bits & 168 & Appears to take 1 slot \\\\ \\hline 852 \\end{tabular} 853 \\caption{AIS message number 4: Base station report} 854 \\label{tab:bsreport} 855 \\end{table} 856 ''')
857 858 ###################################################################### 859 # Text Definition 860 ###################################################################### 861
862 -def textDefinitionTable(outfile=sys.stdout 863 ,delim='\t' 864 ):
865 ''' 866 Return the text definition table for this message type 867 @param outfile: file like object to print to. 868 @type outfile: file obj 869 @return: text table string via the outfile 870 @rtype: str 871 872 ''' 873 o = outfile 874 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description 875 MessageID'''+delim+'''6'''+delim+'''AIS message number. Must be 4 876 RepeatIndicator'''+delim+'''2'''+delim+'''Indicated how many times a message has been repeated 877 UserID'''+delim+'''30'''+delim+'''Unique ship identification number (MMSI) 878 Time_year'''+delim+'''14'''+delim+'''Current time stamp year 1-9999 879 Time_month'''+delim+'''4'''+delim+'''Current time stamp month 1..12 880 Time_day'''+delim+'''5'''+delim+'''Current time stamp day of the month 1..31 881 Time_hour'''+delim+'''5'''+delim+'''Current time stamp UTC hours 0..23 882 Time_min'''+delim+'''6'''+delim+'''Current time stamp minutes 883 Time_sec'''+delim+'''6'''+delim+'''Current time stamp seconds 884 PositionAccuracy'''+delim+'''1'''+delim+'''Accuracy of positioning fixes 885 Position_longitude'''+delim+'''28'''+delim+'''Location of base station East West location 886 Position_latitude'''+delim+'''27'''+delim+'''Location of base station North South location 887 fixtype'''+delim+'''4'''+delim+'''Method used for positioning 888 Spare'''+delim+'''10'''+delim+'''Not used. Should be set to zero. 889 RAIM'''+delim+'''1'''+delim+'''Receiver autonomous integrity monitoring flag 890 state_syncstate'''+delim+'''2'''+delim+'''Communications State - SOTDMA Sycronization state 891 state_slottimeout'''+delim+'''3'''+delim+'''Communications State - SOTDMA Frames remaining until a new slot is selected 892 state_slotoffset'''+delim+'''14'''+delim+'''Communications State - SOTDMA In what slot will the next transmission occur. BROKEN 893 Total bits'''+delim+'''168'''+delim+'''Appears to take 1 slot''')
894 895 896 ###################################################################### 897 # UNIT TESTING 898 ###################################################################### 899 import unittest
900 -def testParams():
901 '''Return a params file base on the testvalue tags. 902 @rtype: dict 903 @return: params based on testvalue tags 904 ''' 905 params = {} 906 params['MessageID'] = 4 907 params['RepeatIndicator'] = 1 908 params['UserID'] = 1193046 909 params['Time_year'] = 2 910 params['Time_month'] = 2 911 params['Time_day'] = 28 912 params['Time_hour'] = 23 913 params['Time_min'] = 45 914 params['Time_sec'] = 54 915 params['PositionAccuracy'] = 1 916 params['Position_longitude'] = Decimal('-122.16328055555556') 917 params['Position_latitude'] = Decimal('37.424458333333334') 918 params['fixtype'] = 1 919 params['Spare'] = 0 920 params['RAIM'] = False 921 params['state_syncstate'] = 2 922 params['state_slottimeout'] = 0 923 params['state_slotoffset'] = 1221 924 925 return params
926
927 -class Testbsreport(unittest.TestCase):
928 '''Use testvalue tag text from each type to build test case the bsreport message'''
929 - def testEncodeDecode(self):
930 931 params = testParams() 932 bits = encode(params) 933 r = decode(bits) 934 935 # Check that each parameter came through ok. 936 self.failUnlessEqual(r['MessageID'],params['MessageID']) 937 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 938 self.failUnlessEqual(r['UserID'],params['UserID']) 939 self.failUnlessEqual(r['Time_year'],params['Time_year']) 940 self.failUnlessEqual(r['Time_month'],params['Time_month']) 941 self.failUnlessEqual(r['Time_day'],params['Time_day']) 942 self.failUnlessEqual(r['Time_hour'],params['Time_hour']) 943 self.failUnlessEqual(r['Time_min'],params['Time_min']) 944 self.failUnlessEqual(r['Time_sec'],params['Time_sec']) 945 self.failUnlessEqual(r['PositionAccuracy'],params['PositionAccuracy']) 946 self.failUnlessAlmostEqual(r['Position_longitude'],params['Position_longitude'],5) 947 self.failUnlessAlmostEqual(r['Position_latitude'],params['Position_latitude'],5) 948 self.failUnlessEqual(r['fixtype'],params['fixtype']) 949 self.failUnlessEqual(r['Spare'],params['Spare']) 950 self.failUnlessEqual(r['RAIM'],params['RAIM']) 951 self.failUnlessEqual(r['state_syncstate'],params['state_syncstate']) 952 self.failUnlessEqual(r['state_slottimeout'],params['state_slottimeout']) 953 self.failUnlessEqual(r['state_slotoffset'],params['state_slotoffset'])
954
955 -def addMsgOptions(parser):
956 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 957 help='decode a "bsreport" AIS message') 958 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 959 help='encode a "bsreport" AIS message') 960 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int' 961 ,help='Field parameter value [default: %default]') 962 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int' 963 ,help='Field parameter value [default: %default]') 964 parser.add_option('--Time_year-field', dest='Time_yearField',default=0,metavar='uint',type='int' 965 ,help='Field parameter value [default: %default]') 966 parser.add_option('--Time_month-field', dest='Time_monthField',default=0,metavar='uint',type='int' 967 ,help='Field parameter value [default: %default]') 968 parser.add_option('--Time_day-field', dest='Time_dayField',default=0,metavar='uint',type='int' 969 ,help='Field parameter value [default: %default]') 970 parser.add_option('--Time_hour-field', dest='Time_hourField',default=24,metavar='uint',type='int' 971 ,help='Field parameter value [default: %default]') 972 parser.add_option('--Time_min-field', dest='Time_minField',default=60,metavar='uint',type='int' 973 ,help='Field parameter value [default: %default]') 974 parser.add_option('--Time_sec-field', dest='Time_secField',default=60,metavar='uint',type='int' 975 ,help='Field parameter value [default: %default]') 976 parser.add_option('--PositionAccuracy-field', dest='PositionAccuracyField',metavar='uint',type='int' 977 ,help='Field parameter value [default: %default]') 978 parser.add_option('--Position_longitude-field', dest='Position_longitudeField',default=Decimal('181'),metavar='decimal',type='string' 979 ,help='Field parameter value [default: %default]') 980 parser.add_option('--Position_latitude-field', dest='Position_latitudeField',default=Decimal('91'),metavar='decimal',type='string' 981 ,help='Field parameter value [default: %default]') 982 parser.add_option('--fixtype-field', dest='fixtypeField',default=0,metavar='uint',type='int' 983 ,help='Field parameter value [default: %default]') 984 parser.add_option('--RAIM-field', dest='RAIMField',metavar='bool',type='int' 985 ,help='Field parameter value [default: %default]') 986 parser.add_option('--state_syncstate-field', dest='state_syncstateField',metavar='uint',type='int' 987 ,help='Field parameter value [default: %default]') 988 parser.add_option('--state_slottimeout-field', dest='state_slottimeoutField',metavar='uint',type='int' 989 ,help='Field parameter value [default: %default]') 990 parser.add_option('--state_slotoffset-field', dest='state_slotoffsetField',metavar='uint',type='int' 991 ,help='Field parameter value [default: %default]')
992 993 ############################################################ 994 if __name__=='__main__': 995 996 from optparse import OptionParser 997 parser = OptionParser(usage="%prog [options]", 998 version="%prog "+__version__) 999 1000 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 1001 help='run the documentation tests') 1002 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 1003 help='run the unit tests') 1004 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 1005 help='Make the test output verbose') 1006 1007 # FIX: remove nmea from binary messages. No way to build the whole packet? 1008 # FIX: or build the surrounding msg 8 for a broadcast? 1009 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 1010 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 1011 ,default='nmeapayload' 1012 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 1013 1014 1015 outputChoices = ('std','html','csv','sql' , 'kml','kml-full') 1016 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 1017 ,default='std' 1018 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 1019 1020 parser.add_option('-o','--output',dest='outputFileName',default=None, 1021 help='Name of the python file to write [default: stdout]') 1022 1023 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 1024 choices=fieldList, 1025 help='Which fields to include in the output. Currently only for csv output [default: all]') 1026 1027 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 1028 help='Print the field name for csv') 1029 1030 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 1031 help='Print out an sql create command for the table.') 1032 1033 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true', 1034 help='Print a LaTeX table of the type') 1035 1036 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true', 1037 help='Print delimited table of the type (for Word table importing)') 1038 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t' 1039 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)') 1040 1041 1042 dbChoices = ('sqlite','postgres') 1043 parser.add_option('-D','--db-type',dest='dbType',default='postgres' 1044 ,choices=dbChoices,type='choice' 1045 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 1046 1047 addMsgOptions(parser) 1048 1049 (options,args) = parser.parse_args() 1050 success=True 1051 1052 if options.doctest: 1053 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 1054 sys.argv= [sys.argv[0]] 1055 if options.verbose: sys.argv.append('-v') 1056 import doctest 1057 numfail,numtests=doctest.testmod() 1058 if numfail==0: print 'ok' 1059 else: 1060 print 'FAILED' 1061 success=False 1062 1063 if not success: sys.exit('Something Failed') 1064 del success # Hide success from epydoc 1065 1066 if options.unittest: 1067 sys.argv = [sys.argv[0]] 1068 if options.verbose: sys.argv.append('-v') 1069 unittest.main() 1070 1071 outfile = sys.stdout 1072 if None!=options.outputFileName: 1073 outfile = file(options.outputFileName,'w') 1074 1075 1076 if options.doEncode: 1077 # First make sure all non required options are specified 1078 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField") 1079 if None==options.UserIDField: parser.error("missing value for UserIDField") 1080 if None==options.Time_yearField: parser.error("missing value for Time_yearField") 1081 if None==options.Time_monthField: parser.error("missing value for Time_monthField") 1082 if None==options.Time_dayField: parser.error("missing value for Time_dayField") 1083 if None==options.Time_hourField: parser.error("missing value for Time_hourField") 1084 if None==options.Time_minField: parser.error("missing value for Time_minField") 1085 if None==options.Time_secField: parser.error("missing value for Time_secField") 1086 if None==options.PositionAccuracyField: parser.error("missing value for PositionAccuracyField") 1087 if None==options.Position_longitudeField: parser.error("missing value for Position_longitudeField") 1088 if None==options.Position_latitudeField: parser.error("missing value for Position_latitudeField") 1089 if None==options.fixtypeField: parser.error("missing value for fixtypeField") 1090 if None==options.RAIMField: parser.error("missing value for RAIMField") 1091 if None==options.state_syncstateField: parser.error("missing value for state_syncstateField") 1092 if None==options.state_slottimeoutField: parser.error("missing value for state_slottimeoutField") 1093 if None==options.state_slotoffsetField: parser.error("missing value for state_slotoffsetField") 1094 msgDict={ 1095 'MessageID': '4', 1096 'RepeatIndicator': options.RepeatIndicatorField, 1097 'UserID': options.UserIDField, 1098 'Time_year': options.Time_yearField, 1099 'Time_month': options.Time_monthField, 1100 'Time_day': options.Time_dayField, 1101 'Time_hour': options.Time_hourField, 1102 'Time_min': options.Time_minField, 1103 'Time_sec': options.Time_secField, 1104 'PositionAccuracy': options.PositionAccuracyField, 1105 'Position_longitude': options.Position_longitudeField, 1106 'Position_latitude': options.Position_latitudeField, 1107 'fixtype': options.fixtypeField, 1108 'Spare': '0', 1109 'RAIM': options.RAIMField, 1110 'state_syncstate': options.state_syncstateField, 1111 'state_slottimeout': options.state_slottimeoutField, 1112 'state_slotoffset': options.state_slotoffsetField, 1113 } 1114 1115 bits = encode(msgDict) 1116 if 'binary'==options.ioType: print str(bits) 1117 elif 'nmeapayload'==options.ioType: 1118 # FIX: figure out if this might be necessary at compile time 1119 print "bitLen",len(bits) 1120 bitLen=len(bits) 1121 if bitLen%6!=0: 1122 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 1123 print "result:",binary.bitvectoais6(bits)[0] 1124 1125 1126 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 1127 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 1128 else: sys.exit('ERROR: unknown ioType. Help!') 1129 1130 1131 if options.sqlCreate: 1132 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 1133 1134 if options.latexDefinitionTable: 1135 latexDefinitionTable(outfile) 1136 1137 # For conversion to word tables 1138 if options.textDefinitionTable: 1139 textDefinitionTable(outfile,options.delimTextDefinitionTable) 1140 1141 if options.printCsvfieldList: 1142 # Make a csv separated list of fields that will be displayed for csv 1143 if None == options.fieldList: options.fieldList = fieldList 1144 import StringIO 1145 buf = StringIO.StringIO() 1146 for field in options.fieldList: 1147 buf.write(field+',') 1148 result = buf.getvalue() 1149 if result[-1] == ',': print result[:-1] 1150 else: print result 1151 1152 if options.doDecode: 1153 if len(args)==0: args = sys.stdin 1154 for msg in args: 1155 bv = None 1156 1157 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 1158 # Found nmea 1159 # FIX: do checksum 1160 bv = binary.ais6tobitvec(msg.split(',')[5]) 1161 else: # either binary or nmeapayload... expect mostly nmeapayloads 1162 # assumes that an all 0 and 1 string can not be a nmeapayload 1163 binaryMsg=True 1164 for c in msg: 1165 if c not in ('0','1'): 1166 binaryMsg=False 1167 break 1168 if binaryMsg: 1169 bv = BitVector(bitstring=msg) 1170 else: # nmeapayload 1171 bv = binary.ais6tobitvec(msg) 1172 1173 printFields(decode(bv) 1174 ,out=outfile 1175 ,format=options.outputType 1176 ,fieldList=options.fieldList 1177 ,dbType=options.dbType 1178 ) 1179