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

Source Code for Module ais.whalenotice

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 4791 $'.split()[1] 
  4  __date__ = '$Date: 2007-02-08 $'.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  ''' 
 34   
 35  import sys 
 36  from decimal import Decimal 
 37  from BitVector import BitVector 
 38   
 39  import binary, aisstring 
 40   
 41  # FIX: check to see if these will be needed 
 42  TrueBV  = BitVector(bitstring="1") 
 43  "Why always rebuild the True bit?  This should speed things up a bunch" 
 44  FalseBV = BitVector(bitstring="0") 
 45  "Why always rebuild the False bit?  This should speed things up a bunch" 
 46   
 47   
 48  fieldList = [ 
 49          'dac', 
 50          'fid', 
 51          'efid', 
 52          'timetag_month', 
 53          'timetag_day', 
 54          'timetag_hour', 
 55          'timetag_min', 
 56          'timetag_sec', 
 57          'stationid', 
 58          'station_longitude', 
 59          'station_latitude', 
 60          'whale_longitude', 
 61          'whale_latitude', 
 62          'timetoexpire', 
 63          'radius', 
 64          'heading', 
 65          'numWhales', 
 66  ] 
 67   
68 -def encode(params, validate=False):
69 '''Create a whalenotice binary message payload to pack into an AIS Msg whalenotice. 70 71 Fields in params: 72 - dac(uint): Designated Area Code (field automatically set to "366") 73 - fid(uint): Functional Identifier (field automatically set to "1") 74 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 75 - timetag_month(uint): Time whale was last recorded month 1..12 76 - timetag_day(uint): Time whale was last recorded day of the month 1..31 77 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23 78 - timetag_min(uint): Time whale was last recorded minutes 79 - timetag_sec(uint): Time whale was last recorded seconds 80 - stationid(aisstr6): Character identifier of the station. Usually a number. 81 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location 82 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location 83 - whale_longitude(decimal): Where was the whale East West location 84 - whale_latitude(decimal): Where was the whale North South location 85 - timetoexpire(uint): Seconds until this notice expires 86 - radius(uint): Distance of the required exclusion/slow zone 87 - heading(uint): Direction the whale is traveling 88 - numWhales(uint): Number of whales detected 89 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 90 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 91 @rtype: BitVector 92 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 93 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 94 ''' 95 96 bvList = [] 97 bvList.append(binary.setBitVectorSize(BitVector(intVal=366),16)) 98 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),4)) 99 bvList.append(binary.setBitVectorSize(BitVector(intVal=2),12)) 100 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_month']),4)) 101 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_day']),5)) 102 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_hour']),5)) 103 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_min']),6)) 104 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_sec']),6)) 105 if 'stationid' in params: 106 bvList.append(aisstring.encode(params['stationid'],42)) 107 else: 108 bvList.append(aisstring.encode('@@@@@@@',42)) 109 if 'station_longitude' in params: 110 bvList.append(binary.bvFromSignedInt(int(Decimal(params['station_longitude'])*Decimal('600000')),28)) 111 else: 112 bvList.append(binary.bvFromSignedInt(108600000,28)) 113 if 'station_latitude' in params: 114 bvList.append(binary.bvFromSignedInt(int(Decimal(params['station_latitude'])*Decimal('600000')),27)) 115 else: 116 bvList.append(binary.bvFromSignedInt(54600000,27)) 117 if 'whale_longitude' in params: 118 bvList.append(binary.bvFromSignedInt(int(Decimal(params['whale_longitude'])*Decimal('600000')),28)) 119 else: 120 bvList.append(binary.bvFromSignedInt(108600000,28)) 121 if 'whale_latitude' in params: 122 bvList.append(binary.bvFromSignedInt(int(Decimal(params['whale_latitude'])*Decimal('600000')),27)) 123 else: 124 bvList.append(binary.bvFromSignedInt(54600000,27)) 125 if 'timetoexpire' in params: 126 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetoexpire']),16)) 127 else: 128 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),16)) 129 if 'radius' in params: 130 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['radius']),16)) 131 else: 132 bvList.append(binary.setBitVectorSize(BitVector(intVal=65534),16)) 133 if 'heading' in params: 134 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['heading']),9)) 135 else: 136 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 137 if 'numWhales' in params: 138 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['numWhales']),8)) 139 else: 140 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8)) 141 142 return binary.joinBV(bvList)
143
144 -def decode(bv, validate=False):
145 '''Unpack a whalenotice message 146 147 Fields in params: 148 - dac(uint): Designated Area Code (field automatically set to "366") 149 - fid(uint): Functional Identifier (field automatically set to "1") 150 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 151 - timetag_month(uint): Time whale was last recorded month 1..12 152 - timetag_day(uint): Time whale was last recorded day of the month 1..31 153 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23 154 - timetag_min(uint): Time whale was last recorded minutes 155 - timetag_sec(uint): Time whale was last recorded seconds 156 - stationid(aisstr6): Character identifier of the station. Usually a number. 157 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location 158 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location 159 - whale_longitude(decimal): Where was the whale East West location 160 - whale_latitude(decimal): Where was the whale North South location 161 - timetoexpire(uint): Seconds until this notice expires 162 - radius(uint): Distance of the required exclusion/slow zone 163 - heading(uint): Direction the whale is traveling 164 - numWhales(uint): Number of whales detected 165 @type bv: BitVector 166 @param bv: Bits defining a message 167 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 168 @rtype: dict 169 @return: params 170 ''' 171 172 #Would be nice to check the bit count here.. 173 #if validate: 174 # assert (len(bv)==FIX: SOME NUMBER) 175 r = {} 176 r['dac']=366 177 r['fid']=1 178 r['efid']=2 179 r['timetag_month']=int(bv[32:36]) 180 r['timetag_day']=int(bv[36:41]) 181 r['timetag_hour']=int(bv[41:46]) 182 r['timetag_min']=int(bv[46:52]) 183 r['timetag_sec']=int(bv[52:58]) 184 r['stationid']=aisstring.decode(bv[58:100]) 185 r['station_longitude']=Decimal(binary.signedIntFromBV(bv[100:128]))/Decimal('600000') 186 r['station_latitude']=Decimal(binary.signedIntFromBV(bv[128:155]))/Decimal('600000') 187 r['whale_longitude']=Decimal(binary.signedIntFromBV(bv[155:183]))/Decimal('600000') 188 r['whale_latitude']=Decimal(binary.signedIntFromBV(bv[183:210]))/Decimal('600000') 189 r['timetoexpire']=int(bv[210:226]) 190 r['radius']=int(bv[226:242]) 191 r['heading']=int(bv[242:251]) 192 r['numWhales']=int(bv[251:259]) 193 return r
194
195 -def decodedac(bv, validate=False):
196 return 366
197
198 -def decodefid(bv, validate=False):
199 return 1
200
201 -def decodeefid(bv, validate=False):
202 return 2
203
204 -def decodetimetag_month(bv, validate=False):
205 return int(bv[32:36])
206
207 -def decodetimetag_day(bv, validate=False):
208 return int(bv[36:41])
209
210 -def decodetimetag_hour(bv, validate=False):
211 return int(bv[41:46])
212
213 -def decodetimetag_min(bv, validate=False):
214 return int(bv[46:52])
215
216 -def decodetimetag_sec(bv, validate=False):
217 return int(bv[52:58])
218
219 -def decodestationid(bv, validate=False):
220 return aisstring.decode(bv[58:100])
221
222 -def decodestation_longitude(bv, validate=False):
223 return Decimal(binary.signedIntFromBV(bv[100:128]))/Decimal('600000')
224
225 -def decodestation_latitude(bv, validate=False):
226 return Decimal(binary.signedIntFromBV(bv[128:155]))/Decimal('600000')
227
228 -def decodewhale_longitude(bv, validate=False):
229 return Decimal(binary.signedIntFromBV(bv[155:183]))/Decimal('600000')
230
231 -def decodewhale_latitude(bv, validate=False):
232 return Decimal(binary.signedIntFromBV(bv[183:210]))/Decimal('600000')
233
234 -def decodetimetoexpire(bv, validate=False):
235 return int(bv[210:226])
236
237 -def decoderadius(bv, validate=False):
238 return int(bv[226:242])
239
240 -def decodeheading(bv, validate=False):
241 return int(bv[242:251])
242
243 -def decodenumWhales(bv, validate=False):
244 return int(bv[251:259])
245 246
247 -def printHtml(params, out=sys.stdout):
248 out.write("<h3>whalenotice<h3>\n") 249 out.write("<table border=\"1\">\n") 250 out.write("<tr bgcolor=\"orange\">\n") 251 out.write("<th align=\"left\">Field Name</th>\n") 252 out.write("<th align=\"left\">Type</th>\n") 253 out.write("<th align=\"left\">Value</th>\n") 254 out.write("<th align=\"left\">Value in Lookup Table</th>\n") 255 out.write("<th align=\"left\">Units</th>\n") 256 out.write("\n") 257 out.write("<tr>\n") 258 out.write("<td>dac</td>\n") 259 out.write("<td>uint</td>\n") 260 if 'dac' in params: 261 out.write(" <td>"+str(params['dac'])+"</td>\n") 262 out.write(" <td>"+str(params['dac'])+"</td>\n") 263 out.write("</tr>\n") 264 out.write("\n") 265 out.write("<tr>\n") 266 out.write("<td>fid</td>\n") 267 out.write("<td>uint</td>\n") 268 if 'fid' in params: 269 out.write(" <td>"+str(params['fid'])+"</td>\n") 270 out.write(" <td>"+str(params['fid'])+"</td>\n") 271 out.write("</tr>\n") 272 out.write("\n") 273 out.write("<tr>\n") 274 out.write("<td>efid</td>\n") 275 out.write("<td>uint</td>\n") 276 if 'efid' in params: 277 out.write(" <td>"+str(params['efid'])+"</td>\n") 278 out.write(" <td>"+str(params['efid'])+"</td>\n") 279 out.write("</tr>\n") 280 out.write("\n") 281 out.write("<tr>\n") 282 out.write("<td>timetag_month</td>\n") 283 out.write("<td>uint</td>\n") 284 if 'timetag_month' in params: 285 out.write(" <td>"+str(params['timetag_month'])+"</td>\n") 286 out.write(" <td>"+str(params['timetag_month'])+"</td>\n") 287 out.write("</tr>\n") 288 out.write("\n") 289 out.write("<tr>\n") 290 out.write("<td>timetag_day</td>\n") 291 out.write("<td>uint</td>\n") 292 if 'timetag_day' in params: 293 out.write(" <td>"+str(params['timetag_day'])+"</td>\n") 294 out.write(" <td>"+str(params['timetag_day'])+"</td>\n") 295 out.write("</tr>\n") 296 out.write("\n") 297 out.write("<tr>\n") 298 out.write("<td>timetag_hour</td>\n") 299 out.write("<td>uint</td>\n") 300 if 'timetag_hour' in params: 301 out.write(" <td>"+str(params['timetag_hour'])+"</td>\n") 302 out.write(" <td>"+str(params['timetag_hour'])+"</td>\n") 303 out.write("</tr>\n") 304 out.write("\n") 305 out.write("<tr>\n") 306 out.write("<td>timetag_min</td>\n") 307 out.write("<td>uint</td>\n") 308 if 'timetag_min' in params: 309 out.write(" <td>"+str(params['timetag_min'])+"</td>\n") 310 out.write(" <td>"+str(params['timetag_min'])+"</td>\n") 311 out.write("</tr>\n") 312 out.write("\n") 313 out.write("<tr>\n") 314 out.write("<td>timetag_sec</td>\n") 315 out.write("<td>uint</td>\n") 316 if 'timetag_sec' in params: 317 out.write(" <td>"+str(params['timetag_sec'])+"</td>\n") 318 out.write(" <td>"+str(params['timetag_sec'])+"</td>\n") 319 out.write("</tr>\n") 320 out.write("\n") 321 out.write("<tr>\n") 322 out.write("<td>stationid</td>\n") 323 out.write("<td>aisstr6</td>\n") 324 if 'stationid' in params: 325 out.write(" <td>"+str(params['stationid'])+"</td>\n") 326 out.write(" <td>"+str(params['stationid'])+"</td>\n") 327 out.write("</tr>\n") 328 out.write("\n") 329 out.write("<tr>\n") 330 out.write("<td>station_longitude</td>\n") 331 out.write("<td>decimal</td>\n") 332 if 'station_longitude' in params: 333 out.write(" <td>"+str(params['station_longitude'])+"</td>\n") 334 out.write(" <td>"+str(params['station_longitude'])+"</td>\n") 335 out.write("<td>degrees</td>\n") 336 out.write("</tr>\n") 337 out.write("\n") 338 out.write("<tr>\n") 339 out.write("<td>station_latitude</td>\n") 340 out.write("<td>decimal</td>\n") 341 if 'station_latitude' in params: 342 out.write(" <td>"+str(params['station_latitude'])+"</td>\n") 343 out.write(" <td>"+str(params['station_latitude'])+"</td>\n") 344 out.write("<td>degrees</td>\n") 345 out.write("</tr>\n") 346 out.write("\n") 347 out.write("<tr>\n") 348 out.write("<td>whale_longitude</td>\n") 349 out.write("<td>decimal</td>\n") 350 if 'whale_longitude' in params: 351 out.write(" <td>"+str(params['whale_longitude'])+"</td>\n") 352 out.write(" <td>"+str(params['whale_longitude'])+"</td>\n") 353 out.write("<td>degrees</td>\n") 354 out.write("</tr>\n") 355 out.write("\n") 356 out.write("<tr>\n") 357 out.write("<td>whale_latitude</td>\n") 358 out.write("<td>decimal</td>\n") 359 if 'whale_latitude' in params: 360 out.write(" <td>"+str(params['whale_latitude'])+"</td>\n") 361 out.write(" <td>"+str(params['whale_latitude'])+"</td>\n") 362 out.write("<td>degrees</td>\n") 363 out.write("</tr>\n") 364 out.write("\n") 365 out.write("<tr>\n") 366 out.write("<td>timetoexpire</td>\n") 367 out.write("<td>uint</td>\n") 368 if 'timetoexpire' in params: 369 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n") 370 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n") 371 out.write("<td>seconds</td>\n") 372 out.write("</tr>\n") 373 out.write("\n") 374 out.write("<tr>\n") 375 out.write("<td>radius</td>\n") 376 out.write("<td>uint</td>\n") 377 if 'radius' in params: 378 out.write(" <td>"+str(params['radius'])+"</td>\n") 379 out.write(" <td>"+str(params['radius'])+"</td>\n") 380 out.write("<td>m</td>\n") 381 out.write("</tr>\n") 382 out.write("\n") 383 out.write("<tr>\n") 384 out.write("<td>heading</td>\n") 385 out.write("<td>uint</td>\n") 386 if 'heading' in params: 387 out.write(" <td>"+str(params['heading'])+"</td>\n") 388 out.write(" <td>"+str(params['heading'])+"</td>\n") 389 out.write("<td>degrees true north</td>\n") 390 out.write("</tr>\n") 391 out.write("\n") 392 out.write("<tr>\n") 393 out.write("<td>numWhales</td>\n") 394 out.write("<td>uint</td>\n") 395 if 'numWhales' in params: 396 out.write(" <td>"+str(params['numWhales'])+"</td>\n") 397 out.write(" <td>"+str(params['numWhales'])+"</td>\n") 398 out.write("</tr>\n") 399 out.write("</table>\n")
400 401
402 -def printKml(params, out=sys.stdout):
403 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer''' 404 out.write("\ <Placemark>\n") 405 out.write("\t <name>"+str(params['stationsid'])+"</name>\n") 406 out.write("\t\t<description>\n") 407 import StringIO 408 buf = StringIO.StringIO() 409 printHtml(params,buf) 410 import cgi 411 out.write(cgi.escape(buf.getvalue())) 412 out.write("\t\t</description>\n") 413 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n") 414 out.write("\t\t<Point>\n") 415 out.write("\t\t\t<coordinates>") 416 out.write(str(params['station_longitude'])) 417 out.write(',') 418 out.write(str(params['station_latitude'])) 419 out.write(",0</coordinates>\n") 420 out.write("\t\t</Point>\n") 421 out.write("\t</Placemark>\n")
422
423 -def printFields(params, out=sys.stdout, format='std', fieldList=None):
424 '''Print a numWhales message to stdout. 425 426 Fields in params: 427 - dac(uint): Designated Area Code (field automatically set to "366") 428 - fid(uint): Functional Identifier (field automatically set to "1") 429 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2") 430 - timetag_month(uint): Time whale was last recorded month 1..12 431 - timetag_day(uint): Time whale was last recorded day of the month 1..31 432 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23 433 - timetag_min(uint): Time whale was last recorded minutes 434 - timetag_sec(uint): Time whale was last recorded seconds 435 - stationid(aisstr6): Character identifier of the station. Usually a number. 436 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location 437 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location 438 - whale_longitude(decimal): Where was the whale East West location 439 - whale_latitude(decimal): Where was the whale North South location 440 - timetoexpire(uint): Seconds until this notice expires 441 - radius(uint): Distance of the required exclusion/slow zone 442 - heading(uint): Direction the whale is traveling 443 - numWhales(uint): Number of whales detected 444 @param params: Dictionary of field names/values. 445 @param out: File like object to write to 446 @rtype: stdout 447 @return: text to out 448 ''' 449 450 if 'std'==format: 451 out.write("numWhales:\n") 452 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n") 453 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n") 454 if 'efid' in params: out.write(" efid: "+str(params['efid'])+"\n") 455 if 'timetag_month' in params: out.write(" timetag_month: "+str(params['timetag_month'])+"\n") 456 if 'timetag_day' in params: out.write(" timetag_day: "+str(params['timetag_day'])+"\n") 457 if 'timetag_hour' in params: out.write(" timetag_hour: "+str(params['timetag_hour'])+"\n") 458 if 'timetag_min' in params: out.write(" timetag_min: "+str(params['timetag_min'])+"\n") 459 if 'timetag_sec' in params: out.write(" timetag_sec: "+str(params['timetag_sec'])+"\n") 460 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n") 461 if 'station_longitude' in params: out.write(" station_longitude: "+str(params['station_longitude'])+"\n") 462 if 'station_latitude' in params: out.write(" station_latitude: "+str(params['station_latitude'])+"\n") 463 if 'whale_longitude' in params: out.write(" whale_longitude: "+str(params['whale_longitude'])+"\n") 464 if 'whale_latitude' in params: out.write(" whale_latitude: "+str(params['whale_latitude'])+"\n") 465 if 'timetoexpire' in params: out.write(" timetoexpire: "+str(params['timetoexpire'])+"\n") 466 if 'radius' in params: out.write(" radius: "+str(params['radius'])+"\n") 467 if 'heading' in params: out.write(" heading: "+str(params['heading'])+"\n") 468 if 'numWhales' in params: out.write(" numWhales: "+str(params['numWhales'])+"\n") 469 elif 'csv'==format: 470 if None == options.fieldList: 471 options.fieldList = fieldList 472 needComma = False; 473 for field in fieldList: 474 if needComma: out.write(',') 475 needComma = True 476 if field in params: 477 out.write(str(params[field])) 478 # else: leave it empty 479 out.write("\n") 480 elif 'html'==format: 481 printHtml(params,out) 482 elif 'sql'==format: 483 sqlInsertStr(params,out) 484 elif 'kml'==format: 485 printKml(params,out) 486 elif 'kml-full'==format: 487 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") 488 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n") 489 out.write("<Document>\n") 490 out.write(" <name>whalenotice</name>\n") 491 printKml(params,out) 492 out.write("</Document>\n") 493 out.write("</kml>\n") 494 else: 495 print "ERROR: unknown format:",format 496 assert False 497 498 return # Nothing to return
499 500 ###################################################################### 501 # SQL SUPPORT 502 ###################################################################### 503
504 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None, addCoastGuardFields=True):
505 ''' 506 Return the SQL CREATE command for this message type 507 @param outfile: file like object to print to. 508 @param fields: which fields to put in the create. Defaults to all. 509 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 510 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 511 @type addCoastGuardFields: bool 512 @return: sql create string 513 @rtype: str 514 515 @see: sqlCreate 516 ''' 517 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields)))
518
519 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True):
520 ''' 521 Return the sqlhelp object to create the table. 522 523 @param fields: which fields to put in the create. Defaults to all. 524 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 525 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 526 @type addCoastGuardFields: bool 527 @return: An object that can be used to generate a return 528 @rtype: sqlhelp.create 529 ''' 530 if None == fields: fields = fieldList 531 import sqlhelp 532 c = sqlhelp.create('whalenotice') 533 if 'dac' in fields: c.addInt ('dac') 534 if 'fid' in fields: c.addInt ('fid') 535 if 'efid' in fields: c.addInt ('efid') 536 if 'timetag_month' in fields: c.addInt ('timetag_month') 537 if 'timetag_day' in fields: c.addInt ('timetag_day') 538 if 'timetag_hour' in fields: c.addInt ('timetag_hour') 539 if 'timetag_min' in fields: c.addInt ('timetag_min') 540 if 'timetag_sec' in fields: c.addInt ('timetag_sec') 541 if 'stationid' in fields: c.addVarChar('stationid',7) 542 if 'station_longitude' in fields: c.addDecimal('station_longitude',8,5) 543 if 'station_latitude' in fields: c.addDecimal('station_latitude',8,5) 544 if 'whale_longitude' in fields: c.addDecimal('whale_longitude',8,5) 545 if 'whale_latitude' in fields: c.addDecimal('whale_latitude',8,5) 546 if 'timetoexpire' in fields: c.addInt ('timetoexpire') 547 if 'radius' in fields: c.addInt ('radius') 548 if 'heading' in fields: c.addInt ('heading') 549 if 'numWhales' in fields: c.addInt ('numWhales') 550 551 if addCoastGuardFields: 552 # c.addInt('cg_rssi') # Relative signal strength indicator 553 # c.addInt('cg_d') # dBm receive strength 554 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 555 # c.addInt('cg_S') # Slot received in 556 # c.addVarChar('cg_x',10) # Idonno 557 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 558 c.addInt('cg_timestamp') # UTC seconds since the epoch 559 # FIX: maybe an actually time field? 560 561 return c
562
563 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None):
564 ''' 565 Return the SQL CREATE command for this message type 566 @param params: dictionary of values keyed by field name 567 @param outfile: file like object to print to. 568 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 569 @return: sql create string 570 @rtype: str 571 572 @see: sqlCreate 573 ''' 574 outfile.write(str(sqlInsert(params,extraParams)))
575 576
577 -def sqlInsert(params,extraParams=None):
578 ''' 579 Give the SQL insert statement 580 @param params: dict keyed by field name of values 581 @param extraParams: any extra fields that you have created beyond the normal ais message fields 582 @rtype: sqlhelp.insert 583 @return: insert class instance 584 @todo: allow optional type checking of params? 585 @warning: this will take invalid keys happily and do what??? 586 ''' 587 import sqlhelp 588 i = sqlhelp.insert('whalenotice') 589 for key in params: 590 #i.add(key,params[key]) 591 if type(params[key])==Decimal: i.add(key,float(params[key])) 592 else: i.add(key,params[key]) 593 if None != extraParams: 594 for key in extraParams: 595 i.add(key,extraParams[key]) 596 597 return i
598 599 600 ###################################################################### 601 # UNIT TESTING 602 ###################################################################### 603 import unittest
604 -def testParams():
605 '''Return a params file base on the testvalue tags. 606 @rtype: dict 607 @return: params based on testvalue tags 608 ''' 609 params = {} 610 params['dac'] = 366 611 params['fid'] = 1 612 params['efid'] = 2 613 params['timetag_month'] = 2 614 params['timetag_day'] = 28 615 params['timetag_hour'] = 23 616 params['timetag_min'] = 45 617 params['timetag_sec'] = 58 618 params['stationid'] = 'A234567' 619 params['station_longitude'] = Decimal('-122.16328055555556') 620 params['station_latitude'] = Decimal('37.424458333333334') 621 params['whale_longitude'] = Decimal('-122.16328055555556') 622 params['whale_latitude'] = Decimal('37.424458333333334') 623 params['timetoexpire'] = 1 624 params['radius'] = 5000 625 params['heading'] = 35 626 params['numWhales'] = 2 627 628 return params
629
630 -class Testwhalenotice(unittest.TestCase):
631 '''Use testvalue tag text from each type to build test case the whalenotice message'''
632 - def testEncodeDecode(self):
633 634 params = testParams() 635 bits = encode(params) 636 r = decode(bits) 637 638 # Check that each parameter came through ok. 639 self.failUnlessEqual(r['dac'],params['dac']) 640 self.failUnlessEqual(r['fid'],params['fid']) 641 self.failUnlessEqual(r['efid'],params['efid']) 642 self.failUnlessEqual(r['timetag_month'],params['timetag_month']) 643 self.failUnlessEqual(r['timetag_day'],params['timetag_day']) 644 self.failUnlessEqual(r['timetag_hour'],params['timetag_hour']) 645 self.failUnlessEqual(r['timetag_min'],params['timetag_min']) 646 self.failUnlessEqual(r['timetag_sec'],params['timetag_sec']) 647 self.failUnlessEqual(r['stationid'],params['stationid']) 648 self.failUnlessAlmostEqual(r['station_longitude'],params['station_longitude'],5) 649 self.failUnlessAlmostEqual(r['station_latitude'],params['station_latitude'],5) 650 self.failUnlessAlmostEqual(r['whale_longitude'],params['whale_longitude'],5) 651 self.failUnlessAlmostEqual(r['whale_latitude'],params['whale_latitude'],5) 652 self.failUnlessEqual(r['timetoexpire'],params['timetoexpire']) 653 self.failUnlessEqual(r['radius'],params['radius']) 654 self.failUnlessEqual(r['heading'],params['heading']) 655 self.failUnlessEqual(r['numWhales'],params['numWhales'])
656
657 -def addMsgOptions(parser):
658 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 659 help='decode a "whalenotice" AIS message') 660 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 661 help='encode a "whalenotice" AIS message') 662 parser.add_option('--timetag_month-field', dest='timetag_monthField',metavar='uint',type='int' 663 ,help='Field parameter value [default: %default]') 664 parser.add_option('--timetag_day-field', dest='timetag_dayField',metavar='uint',type='int' 665 ,help='Field parameter value [default: %default]') 666 parser.add_option('--timetag_hour-field', dest='timetag_hourField',metavar='uint',type='int' 667 ,help='Field parameter value [default: %default]') 668 parser.add_option('--timetag_min-field', dest='timetag_minField',metavar='uint',type='int' 669 ,help='Field parameter value [default: %default]') 670 parser.add_option('--timetag_sec-field', dest='timetag_secField',metavar='uint',type='int' 671 ,help='Field parameter value [default: %default]') 672 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string' 673 ,help='Field parameter value [default: %default]') 674 parser.add_option('--station_longitude-field', dest='station_longitudeField',default=Decimal('181'),metavar='decimal',type='string' 675 ,help='Field parameter value [default: %default]') 676 parser.add_option('--station_latitude-field', dest='station_latitudeField',default=Decimal('91'),metavar='decimal',type='string' 677 ,help='Field parameter value [default: %default]') 678 parser.add_option('--whale_longitude-field', dest='whale_longitudeField',default=Decimal('181'),metavar='decimal',type='string' 679 ,help='Field parameter value [default: %default]') 680 parser.add_option('--whale_latitude-field', dest='whale_latitudeField',default=Decimal('91'),metavar='decimal',type='string' 681 ,help='Field parameter value [default: %default]') 682 parser.add_option('--timetoexpire-field', dest='timetoexpireField',default=0,metavar='uint',type='int' 683 ,help='Field parameter value [default: %default]') 684 parser.add_option('--radius-field', dest='radiusField',default=65534,metavar='uint',type='int' 685 ,help='Field parameter value [default: %default]') 686 parser.add_option('--heading-field', dest='headingField',default=511,metavar='uint',type='int' 687 ,help='Field parameter value [default: %default]') 688 parser.add_option('--numWhales-field', dest='numWhalesField',default=0,metavar='uint',type='int' 689 ,help='Field parameter value [default: %default]')
690 691 ############################################################ 692 if __name__=='__main__': 693 694 from optparse import OptionParser 695 parser = OptionParser(usage="%prog [options]", 696 version="%prog "+__version__) 697 698 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 699 help='run the documentation tests') 700 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 701 help='run the unit tests') 702 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 703 help='Make the test output verbose') 704 705 # FIX: remove nmea from binary messages. No way to build the whole packet? 706 # FIX: or build the surrounding msg 8 for a broadcast? 707 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 708 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 709 ,default='nmeapayload' 710 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]') 711 712 713 outputChoices = ('std','html','csv','sql' , 'kml','kml-full') 714 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 715 ,default='std' 716 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 717 718 parser.add_option('-o','--output',dest='outputFileName',default=None, 719 help='Name of the python file to write [default: stdout]') 720 721 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 722 choices=fieldList, 723 help='Which fields to include in the output. Currently only for csv output [default: all]') 724 725 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 726 help='Print the field name for csv') 727 728 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 729 help='Print out an sql create command for the table.') 730 731 addMsgOptions(parser) 732 733 (options,args) = parser.parse_args() 734 success=True 735 736 if options.doctest: 737 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 738 sys.argv= [sys.argv[0]] 739 if options.verbose: sys.argv.append('-v') 740 import doctest 741 numfail,numtests=doctest.testmod() 742 if numfail==0: print 'ok' 743 else: 744 print 'FAILED' 745 success=False 746 747 if not success: sys.exit('Something Failed') 748 del success # Hide success from epydoc 749 750 if options.unittest: 751 sys.argv = [sys.argv[0]] 752 if options.verbose: sys.argv.append('-v') 753 unittest.main() 754 755 outfile = sys.stdout 756 if None!=options.outputFileName: 757 outfile = file(options.outputFileName,'w') 758 759 760 if options.doEncode: 761 # First make sure all non required options are specified 762 if None==options.timetag_monthField: parser.error("missing value for timetag_monthField") 763 if None==options.timetag_dayField: parser.error("missing value for timetag_dayField") 764 if None==options.timetag_hourField: parser.error("missing value for timetag_hourField") 765 if None==options.timetag_minField: parser.error("missing value for timetag_minField") 766 if None==options.timetag_secField: parser.error("missing value for timetag_secField") 767 if None==options.stationidField: parser.error("missing value for stationidField") 768 if None==options.station_longitudeField: parser.error("missing value for station_longitudeField") 769 if None==options.station_latitudeField: parser.error("missing value for station_latitudeField") 770 if None==options.whale_longitudeField: parser.error("missing value for whale_longitudeField") 771 if None==options.whale_latitudeField: parser.error("missing value for whale_latitudeField") 772 if None==options.timetoexpireField: parser.error("missing value for timetoexpireField") 773 if None==options.radiusField: parser.error("missing value for radiusField") 774 if None==options.headingField: parser.error("missing value for headingField") 775 if None==options.numWhalesField: parser.error("missing value for numWhalesField") 776 msgDict={ 777 'dac': '366', 778 'fid': '1', 779 'efid': '2', 780 'timetag_month': options.timetag_monthField, 781 'timetag_day': options.timetag_dayField, 782 'timetag_hour': options.timetag_hourField, 783 'timetag_min': options.timetag_minField, 784 'timetag_sec': options.timetag_secField, 785 'stationid': options.stationidField, 786 'station_longitude': options.station_longitudeField, 787 'station_latitude': options.station_latitudeField, 788 'whale_longitude': options.whale_longitudeField, 789 'whale_latitude': options.whale_latitudeField, 790 'timetoexpire': options.timetoexpireField, 791 'radius': options.radiusField, 792 'heading': options.headingField, 793 'numWhales': options.numWhalesField, 794 } 795 796 bits = encode(msgDict) 797 if 'binary'==options.ioType: print str(bits) 798 elif 'nmeapayload'==options.ioType: 799 # FIX: figure out if this might be necessary at compile time 800 print "bitLen",len(bits) 801 bitLen=len(bits) 802 if bitLen%6!=0: 803 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 804 print "result:",binary.bitvectoais6(bits)[0] 805 806 807 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 808 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 809 else: sys.exit('ERROR: unknown ioType. Help!') 810 811 812 if options.sqlCreate: 813 sqlCreateStr(outfile,options.fieldList) 814 815 if options.printCsvfieldList: 816 # Make a csv separated list of fields that will be displayed for csv 817 if None == options.fieldList: options.fieldList = fieldList 818 import StringIO 819 buf = StringIO.StringIO() 820 for field in options.fieldList: 821 buf.write(field+',') 822 result = buf.getvalue() 823 if result[-1] == ',': print result[:-1] 824 else: print result 825 826 if options.doDecode: 827 for msg in args: 828 bv = None 829 if 'binary' == options.ioType: bv = BitVector(bitstring=msg) 830 elif 'nmeapayload'== options.ioType: bv = binary.ais6tobitvec(msg) 831 elif 'nmea' == options.ioType: bv = binary.ais6tobitvec(msg.split(',')[5]) 832 else: sys.exit('ERROR: unknown ioType. Help!') 833 834 printFields(decode(bv),out=outfile,format=options.outputType,fieldList=options.fieldList) 835