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

Source Code for Module ais.foo

   1  #!/usr/bin/env python 
   2   
   3  __version__ = '$Revision: 4791 $'.split()[1] 
   4  __date__ = '$Date: 2007-04-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          'Spare', 
  54          'dac', 
  55          'fid', 
  56          'longitude', 
  57          'latitude', 
  58          'day', 
  59          'hour', 
  60          'min', 
  61          'avewind', 
  62          'windgust', 
  63          'winddir', 
  64          'windgustdir', 
  65          'airtemp', 
  66          'relhumid', 
  67          'dewpoint', 
  68          'airpressure', 
  69          'airpressuretrend', 
  70          'horizvis', 
  71          'waterlevel', 
  72          'waterleveltrend', 
  73          'surfcurspeed', 
  74          'surfcurdir', 
  75          'curspeed2', 
  76          'curdir2', 
  77          'curlevel2', 
  78          'curspeed3', 
  79          'curdir3', 
  80          'curlevel3', 
  81          'sigwaveheight', 
  82          'waveperiod', 
  83          'wavedir', 
  84          'swellheight', 
  85          'swellperiod', 
  86          'swelldir', 
  87          'seastate', 
  88          'watertemp', 
  89          'preciptype', 
  90          'salinity', 
  91          'ice', 
  92          'Spare', 
  93  ) 
  94   
  95  fieldListPostgres = ( 
  96          'MessageID', 
  97          'RepeatIndicator', 
  98          'UserID', 
  99          'Spare', 
 100          'dac', 
 101          'fid', 
 102          'Position',     # PostGIS data type 
 103          'day', 
 104          'hour', 
 105          'min', 
 106          'avewind', 
 107          'windgust', 
 108          'winddir', 
 109          'windgustdir', 
 110          'airtemp', 
 111          'relhumid', 
 112          'dewpoint', 
 113          'airpressure', 
 114          'airpressuretrend', 
 115          'horizvis', 
 116          'waterlevel', 
 117          'waterleveltrend', 
 118          'surfcurspeed', 
 119          'surfcurdir', 
 120          'curspeed2', 
 121          'curdir2', 
 122          'curlevel2', 
 123          'curspeed3', 
 124          'curdir3', 
 125          'curlevel3', 
 126          'sigwaveheight', 
 127          'waveperiod', 
 128          'wavedir', 
 129          'swellheight', 
 130          'swellperiod', 
 131          'swelldir', 
 132          'seastate', 
 133          'watertemp', 
 134          'preciptype', 
 135          'salinity', 
 136          'ice', 
 137          'Spare', 
 138  ) 
 139   
 140  toPgFields = { 
 141          'longitude':'Position', 
 142          'latitude':'Position', 
 143  } 
 144  ''' 
 145  Go to the Postgis field names from the straight field name 
 146  ''' 
 147   
 148  fromPgFields = { 
 149          'Position':('longitude','latitude',), 
 150  } 
 151  ''' 
 152  Go from the Postgis field names to the straight field name 
 153  ''' 
 154   
 155  pgTypes = { 
 156          'Position':'POINT', 
 157  } 
 158  ''' 
 159  Lookup table for each postgis field name to get its type. 
 160  ''' 
 161   
162 -def encode(params, validate=False):
163 '''Create a imo_met_hydro binary message payload to pack into an AIS Msg imo_met_hydro. 164 165 Fields in params: 166 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 167 - RepeatIndicator(uint): Indicated how many times a message has been repeated 168 - UserID(uint): Unique ship identification number (MMSI) 169 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 170 - dac(uint): Designated Area Code - part 1 of the IAI (field automatically set to "1") 171 - fid(uint): Functional Identifier - part 2 of the IAI (field automatically set to "11") 172 - longitude(decimal): Location of the vessel. East West location 173 - latitude(decimal): Location of the vessel. North South location 174 - day(uint): Day 0..31 175 - hour(uint): Hour 0..23 176 - min(uint): Min 177 - avewind(uint): Average wind speed values for the last 10 minutes. 178 - windgust(uint): Wind gust is the max wind speed value reading during the last 10 minutes. 179 - winddir(uint): Wind direction 180 - windgustdir(uint): Wind direction for the gust. 181 - airtemp(decimal): Bry bulb temperature 182 - relhumid(uint): Relative humidity 183 - dewpoint(decimal): Bry bulb temperature - FIX: should this be a udecimal?? 184 - airpressure(udecimal): Air pressure. FIX: 9 bits only goes 0..511 185 - airpressuretrend(uint): Air pressure trend 186 - horizvis(udecimal): Horizontal visibility 187 - waterlevel(decimal): Water level (incl. tide) 188 - waterleveltrend(uint): Water level trend 189 - surfcurspeed(udecimal): Surace current speed 190 - surfcurdir(uint): Surface current direction 191 - curspeed2(udecimal): Level 2 current speed 192 - curdir2(uint): Level 2 current direction 193 - curlevel2(uint): Measuring level below sea surface for level 2 194 - curspeed3(udecimal): Level 3 current speed 195 - curdir3(uint): Level 3 current direction 196 - curlevel3(uint): Measuring level below sea surface for level 3 197 - sigwaveheight(udecimal): Significan wave height 198 - waveperiod(uint): Wave period - FIX: How does to fit to the power spectrum? 199 - wavedir(uint): Wave direction - FIX: please define this better 200 - swellheight(udecimal): Swell height 201 - swellperiod(uint): Swell period - FIX: How does to fit to the power spectrum? 202 - swelldir(uint): Swell direction - FIX: please define this better 203 - seastate(uint): Sea state according to the Beaufort scale 204 - watertemp(decimal): Water temp (FIX: at surface? Any requirements on how measured?) 205 - preciptype(uint): According to WMO 206 - salinity(decimal): Salinity - FIX: by what standard? Measured how? 207 - ice(bool): Yes or no for the presence of ice. FIX: what types of ice constitute a yes?? 208 - Spare(uint): Must be zero. FIX: this does not seem slot aligned. (field automatically set to "0") 209 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing 210 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 211 @rtype: BitVector 212 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 213 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits. 214 ''' 215 216 bvList = [] 217 bvList.append(binary.setBitVectorSize(BitVector(intVal=8),6)) 218 if 'RepeatIndicator' in params: 219 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2)) 220 else: 221 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 222 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30)) 223 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 224 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),10)) 225 bvList.append(binary.setBitVectorSize(BitVector(intVal=11),6)) 226 if 'longitude' in params: 227 bvList.append(binary.bvFromSignedInt(int(Decimal(params['longitude'])*Decimal('60000')),25)) 228 else: 229 bvList.append(binary.bvFromSignedInt(10860000,25)) 230 if 'latitude' in params: 231 bvList.append(binary.bvFromSignedInt(int(Decimal(params['latitude'])*Decimal('60000')),24)) 232 else: 233 bvList.append(binary.bvFromSignedInt(5460000,24)) 234 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['day']),5)) 235 if 'hour' in params: 236 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['hour']),5)) 237 else: 238 bvList.append(binary.setBitVectorSize(BitVector(intVal=31),5)) 239 if 'min' in params: 240 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['min']),6)) 241 else: 242 bvList.append(binary.setBitVectorSize(BitVector(intVal=63),6)) 243 if 'avewind' in params: 244 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['avewind']),7)) 245 else: 246 bvList.append(binary.setBitVectorSize(BitVector(intVal=127),7)) 247 if 'windgust' in params: 248 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['windgust']),7)) 249 else: 250 bvList.append(binary.setBitVectorSize(BitVector(intVal=127),7)) 251 if 'winddir' in params: 252 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['winddir']),9)) 253 else: 254 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 255 if 'windgustdir' in params: 256 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['windgustdir']),9)) 257 else: 258 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 259 if 'airtemp' in params: 260 bvList.append(binary.bvFromSignedInt(int(Decimal(params['airtemp'])*Decimal('10')),11)) 261 else: 262 bvList.append(binary.bvFromSignedInt(1023,11)) 263 if 'relhumid' in params: 264 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['relhumid']),7)) 265 else: 266 bvList.append(binary.setBitVectorSize(BitVector(intVal=127),7)) 267 if 'dewpoint' in params: 268 bvList.append(binary.bvFromSignedInt(int(Decimal(params['dewpoint'])*Decimal('10')),10)) 269 else: 270 bvList.append(binary.bvFromSignedInt(511,10)) 271 if 'airpressure' in params: 272 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['airpressure'])*Decimal('1')))),9)) 273 else: 274 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(1311)),9)) 275 if 'airpressuretrend' in params: 276 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['airpressuretrend']),2)) 277 else: 278 bvList.append(binary.setBitVectorSize(BitVector(intVal=3),2)) 279 if 'horizvis' in params: 280 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['horizvis'])*Decimal('10')))),8)) 281 else: 282 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 283 bvList.append(binary.bvFromSignedInt(int(Decimal(params['waterlevel'])*Decimal('10')),9)) 284 if 'waterleveltrend' in params: 285 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['waterleveltrend']),2)) 286 else: 287 bvList.append(binary.setBitVectorSize(BitVector(intVal=3),2)) 288 if 'surfcurspeed' in params: 289 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['surfcurspeed'])*Decimal('10')))),8)) 290 else: 291 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 292 if 'surfcurdir' in params: 293 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['surfcurdir']),9)) 294 else: 295 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 296 if 'curspeed2' in params: 297 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['curspeed2'])*Decimal('10')))),8)) 298 else: 299 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 300 if 'curdir2' in params: 301 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['curdir2']),9)) 302 else: 303 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 304 if 'curlevel2' in params: 305 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['curlevel2']),5)) 306 else: 307 bvList.append(binary.setBitVectorSize(BitVector(intVal=31),5)) 308 if 'curspeed3' in params: 309 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['curspeed3'])*Decimal('10')))),8)) 310 else: 311 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 312 if 'curdir3' in params: 313 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['curdir3']),9)) 314 else: 315 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 316 if 'curlevel3' in params: 317 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['curlevel3']),5)) 318 else: 319 bvList.append(binary.setBitVectorSize(BitVector(intVal=31),5)) 320 if 'sigwaveheight' in params: 321 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['sigwaveheight'])*Decimal('10')))),8)) 322 else: 323 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 324 if 'waveperiod' in params: 325 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['waveperiod']),8)) 326 else: 327 bvList.append(binary.setBitVectorSize(BitVector(intVal=63),8)) 328 if 'wavedir' in params: 329 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['wavedir']),9)) 330 else: 331 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 332 if 'swellheight' in params: 333 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['swellheight'])*Decimal('10')))),8)) 334 else: 335 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8)) 336 if 'swellperiod' in params: 337 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['swellperiod']),8)) 338 else: 339 bvList.append(binary.setBitVectorSize(BitVector(intVal=63),8)) 340 if 'swelldir' in params: 341 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['swelldir']),9)) 342 else: 343 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9)) 344 if 'seastate' in params: 345 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['seastate']),4)) 346 else: 347 bvList.append(binary.setBitVectorSize(BitVector(intVal=15),4)) 348 if 'watertemp' in params: 349 bvList.append(binary.bvFromSignedInt(int(Decimal(params['watertemp'])*Decimal('10')),10)) 350 else: 351 bvList.append(binary.bvFromSignedInt(923,10)) 352 if 'preciptype' in params: 353 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['preciptype']),3)) 354 else: 355 bvList.append(binary.setBitVectorSize(BitVector(intVal=7),3)) 356 if 'salinity' in params: 357 bvList.append(binary.bvFromSignedInt(int(Decimal(params['salinity'])*Decimal('10')),9)) 358 else: 359 bvList.append(binary.bvFromSignedInt(923,9)) 360 if params["ice"]: bvList.append(TrueBV) 361 else: bvList.append(FalseBV) 362 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6)) 363 364 return binary.joinBV(bvList)
365
366 -def decode(bv, validate=False):
367 '''Unpack a imo_met_hydro message 368 369 Fields in params: 370 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 371 - RepeatIndicator(uint): Indicated how many times a message has been repeated 372 - UserID(uint): Unique ship identification number (MMSI) 373 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 374 - dac(uint): Designated Area Code - part 1 of the IAI (field automatically set to "1") 375 - fid(uint): Functional Identifier - part 2 of the IAI (field automatically set to "11") 376 - longitude(decimal): Location of the vessel. East West location 377 - latitude(decimal): Location of the vessel. North South location 378 - day(uint): Day 0..31 379 - hour(uint): Hour 0..23 380 - min(uint): Min 381 - avewind(uint): Average wind speed values for the last 10 minutes. 382 - windgust(uint): Wind gust is the max wind speed value reading during the last 10 minutes. 383 - winddir(uint): Wind direction 384 - windgustdir(uint): Wind direction for the gust. 385 - airtemp(decimal): Bry bulb temperature 386 - relhumid(uint): Relative humidity 387 - dewpoint(decimal): Bry bulb temperature - FIX: should this be a udecimal?? 388 - airpressure(udecimal): Air pressure. FIX: 9 bits only goes 0..511 389 - airpressuretrend(uint): Air pressure trend 390 - horizvis(udecimal): Horizontal visibility 391 - waterlevel(decimal): Water level (incl. tide) 392 - waterleveltrend(uint): Water level trend 393 - surfcurspeed(udecimal): Surace current speed 394 - surfcurdir(uint): Surface current direction 395 - curspeed2(udecimal): Level 2 current speed 396 - curdir2(uint): Level 2 current direction 397 - curlevel2(uint): Measuring level below sea surface for level 2 398 - curspeed3(udecimal): Level 3 current speed 399 - curdir3(uint): Level 3 current direction 400 - curlevel3(uint): Measuring level below sea surface for level 3 401 - sigwaveheight(udecimal): Significan wave height 402 - waveperiod(uint): Wave period - FIX: How does to fit to the power spectrum? 403 - wavedir(uint): Wave direction - FIX: please define this better 404 - swellheight(udecimal): Swell height 405 - swellperiod(uint): Swell period - FIX: How does to fit to the power spectrum? 406 - swelldir(uint): Swell direction - FIX: please define this better 407 - seastate(uint): Sea state according to the Beaufort scale 408 - watertemp(decimal): Water temp (FIX: at surface? Any requirements on how measured?) 409 - preciptype(uint): According to WMO 410 - salinity(decimal): Salinity - FIX: by what standard? Measured how? 411 - ice(bool): Yes or no for the presence of ice. FIX: what types of ice constitute a yes?? 412 - Spare(uint): Must be zero. FIX: this does not seem slot aligned. (field automatically set to "0") 413 @type bv: BitVector 414 @param bv: Bits defining a message 415 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented. 416 @rtype: dict 417 @return: params 418 ''' 419 420 #Would be nice to check the bit count here.. 421 #if validate: 422 # assert (len(bv)==FIX: SOME NUMBER) 423 r = {} 424 r['MessageID']=8 425 r['RepeatIndicator']=int(bv[6:8]) 426 r['UserID']=int(bv[8:38]) 427 r['Spare']=0 428 r['dac']=1 429 r['fid']=11 430 r['longitude']=Decimal(binary.signedIntFromBV(bv[56:81]))/Decimal('60000') 431 r['latitude']=Decimal(binary.signedIntFromBV(bv[81:105]))/Decimal('60000') 432 r['day']=int(bv[105:110]) 433 r['hour']=int(bv[110:115]) 434 r['min']=int(bv[115:121]) 435 r['avewind']=int(bv[121:128]) 436 r['windgust']=int(bv[128:135]) 437 r['winddir']=int(bv[135:144]) 438 r['windgustdir']=int(bv[144:153]) 439 r['airtemp']=Decimal(binary.signedIntFromBV(bv[153:164]))/Decimal('10') 440 r['relhumid']=int(bv[164:171]) 441 r['dewpoint']=Decimal(binary.signedIntFromBV(bv[171:181]))/Decimal('10') 442 r['airpressure']=Decimal(int(bv[181:190]))/Decimal('1') 443 r['airpressuretrend']=int(bv[190:192]) 444 r['horizvis']=Decimal(int(bv[192:200]))/Decimal('10') 445 r['waterlevel']=Decimal(binary.signedIntFromBV(bv[200:209]))/Decimal('10') 446 r['waterleveltrend']=int(bv[209:211]) 447 r['surfcurspeed']=Decimal(int(bv[211:219]))/Decimal('10') 448 r['surfcurdir']=int(bv[219:228]) 449 r['curspeed2']=Decimal(int(bv[228:236]))/Decimal('10') 450 r['curdir2']=int(bv[236:245]) 451 r['curlevel2']=int(bv[245:250]) 452 r['curspeed3']=Decimal(int(bv[250:258]))/Decimal('10') 453 r['curdir3']=int(bv[258:267]) 454 r['curlevel3']=int(bv[267:272]) 455 r['sigwaveheight']=Decimal(int(bv[272:280]))/Decimal('10') 456 r['waveperiod']=int(bv[280:288]) 457 r['wavedir']=int(bv[288:297]) 458 r['swellheight']=Decimal(int(bv[297:305]))/Decimal('10') 459 r['swellperiod']=int(bv[305:313]) 460 r['swelldir']=int(bv[313:322]) 461 r['seastate']=int(bv[322:326]) 462 r['watertemp']=Decimal(binary.signedIntFromBV(bv[326:336]))/Decimal('10') 463 r['preciptype']=int(bv[336:339]) 464 r['salinity']=Decimal(binary.signedIntFromBV(bv[339:348]))/Decimal('10') 465 r['ice']=bool(int(bv[348:349])) 466 r['Spare']=0 467 return r
468
469 -def decodeMessageID(bv, validate=False):
470 return 8
471
472 -def decodeRepeatIndicator(bv, validate=False):
473 return int(bv[6:8])
474
475 -def decodeUserID(bv, validate=False):
476 return int(bv[8:38])
477
478 -def decodeSpare(bv, validate=False):
479 return 0
480
481 -def decodedac(bv, validate=False):
482 return 1
483
484 -def decodefid(bv, validate=False):
485 return 11
486
487 -def decodelongitude(bv, validate=False):
488 return Decimal(binary.signedIntFromBV(bv[56:81]))/Decimal('60000')
489
490 -def decodelatitude(bv, validate=False):
491 return Decimal(binary.signedIntFromBV(bv[81:105]))/Decimal('60000')
492
493 -def decodeday(bv, validate=False):
494 return int(bv[105:110])
495
496 -def decodehour(bv, validate=False):
497 return int(bv[110:115])
498
499 -def decodemin(bv, validate=False):
500 return int(bv[115:121])
501
502 -def decodeavewind(bv, validate=False):
503 return int(bv[121:128])
504
505 -def decodewindgust(bv, validate=False):
506 return int(bv[128:135])
507
508 -def decodewinddir(bv, validate=False):
509 return int(bv[135:144])
510
511 -def decodewindgustdir(bv, validate=False):
512 return int(bv[144:153])
513
514 -def decodeairtemp(bv, validate=False):
515 return Decimal(binary.signedIntFromBV(bv[153:164]))/Decimal('10')
516
517 -def decoderelhumid(bv, validate=False):
518 return int(bv[164:171])
519
520 -def decodedewpoint(bv, validate=False):
521 return Decimal(binary.signedIntFromBV(bv[171:181]))/Decimal('10')
522
523 -def decodeairpressure(bv, validate=False):
524 return Decimal(int(bv[181:190]))/Decimal('1')
525
526 -def decodeairpressuretrend(bv, validate=False):
527 return int(bv[190:192])
528
529 -def decodehorizvis(bv, validate=False):
530 return Decimal(int(bv[192:200]))/Decimal('10')
531
532 -def decodewaterlevel(bv, validate=False):
533 return Decimal(binary.signedIntFromBV(bv[200:209]))/Decimal('10')
534
535 -def decodewaterleveltrend(bv, validate=False):
536 return int(bv[209:211])
537
538 -def decodesurfcurspeed(bv, validate=False):
539 return Decimal(int(bv[211:219]))/Decimal('10')
540
541 -def decodesurfcurdir(bv, validate=False):
542 return int(bv[219:228])
543
544 -def decodecurspeed2(bv, validate=False):
545 return Decimal(int(bv[228:236]))/Decimal('10')
546
547 -def decodecurdir2(bv, validate=False):
548 return int(bv[236:245])
549
550 -def decodecurlevel2(bv, validate=False):
551 return int(bv[245:250])
552
553 -def decodecurspeed3(bv, validate=False):
554 return Decimal(int(bv[250:258]))/Decimal('10')
555
556 -def decodecurdir3(bv, validate=False):
557 return int(bv[258:267])
558
559 -def decodecurlevel3(bv, validate=False):
560 return int(bv[267:272])
561
562 -def decodesigwaveheight(bv, validate=False):
563 return Decimal(int(bv[272:280]))/Decimal('10')
564
565 -def decodewaveperiod(bv, validate=False):
566 return int(bv[280:288])
567
568 -def decodewavedir(bv, validate=False):
569 return int(bv[288:297])
570
571 -def decodeswellheight(bv, validate=False):
572 return Decimal(int(bv[297:305]))/Decimal('10')
573
574 -def decodeswellperiod(bv, validate=False):
575 return int(bv[305:313])
576
577 -def decodeswelldir(bv, validate=False):
578 return int(bv[313:322])
579
580 -def decodeseastate(bv, validate=False):
581 return int(bv[322:326])
582
583 -def decodewatertemp(bv, validate=False):
584 return Decimal(binary.signedIntFromBV(bv[326:336]))/Decimal('10')
585
586 -def decodepreciptype(bv, validate=False):
587 return int(bv[336:339])
588
589 -def decodesalinity(bv, validate=False):
590 return Decimal(binary.signedIntFromBV(bv[339:348]))/Decimal('10')
591
592 -def decodeice(bv, validate=False):
593 return bool(int(bv[348:349]))
594
595 -def decodeSpare(bv, validate=False):
596 return 0
597 598
599 -def printHtml(params, out=sys.stdout):
600 out.write("<h3>imo_met_hydro<h3>\n") 601 out.write("<table border=\"1\">\n") 602 out.write("<tr bgcolor=\"orange\">\n") 603 out.write("<th align=\"left\">Field Name</th>\n") 604 out.write("<th align=\"left\">Type</th>\n") 605 out.write("<th align=\"left\">Value</th>\n") 606 out.write("<th align=\"left\">Value in Lookup Table</th>\n") 607 out.write("<th align=\"left\">Units</th>\n") 608 out.write("\n") 609 out.write("<tr>\n") 610 out.write("<td>MessageID</td>\n") 611 out.write("<td>uint</td>\n") 612 if 'MessageID' in params: 613 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 614 out.write(" <td>"+str(params['MessageID'])+"</td>\n") 615 out.write("</tr>\n") 616 out.write("\n") 617 out.write("<tr>\n") 618 out.write("<td>RepeatIndicator</td>\n") 619 out.write("<td>uint</td>\n") 620 if 'RepeatIndicator' in params: 621 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n") 622 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut: 623 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>") 624 else: 625 out.write("<td><i>Missing LUT entry</i></td>") 626 out.write("</tr>\n") 627 out.write("\n") 628 out.write("<tr>\n") 629 out.write("<td>UserID</td>\n") 630 out.write("<td>uint</td>\n") 631 if 'UserID' in params: 632 out.write(" <td>"+str(params['UserID'])+"</td>\n") 633 out.write(" <td>"+str(params['UserID'])+"</td>\n") 634 out.write("</tr>\n") 635 out.write("\n") 636 out.write("<tr>\n") 637 out.write("<td>Spare</td>\n") 638 out.write("<td>uint</td>\n") 639 if 'Spare' in params: 640 out.write(" <td>"+str(params['Spare'])+"</td>\n") 641 out.write(" <td>"+str(params['Spare'])+"</td>\n") 642 out.write("</tr>\n") 643 out.write("\n") 644 out.write("<tr>\n") 645 out.write("<td>dac</td>\n") 646 out.write("<td>uint</td>\n") 647 if 'dac' in params: 648 out.write(" <td>"+str(params['dac'])+"</td>\n") 649 out.write(" <td>"+str(params['dac'])+"</td>\n") 650 out.write("</tr>\n") 651 out.write("\n") 652 out.write("<tr>\n") 653 out.write("<td>fid</td>\n") 654 out.write("<td>uint</td>\n") 655 if 'fid' in params: 656 out.write(" <td>"+str(params['fid'])+"</td>\n") 657 out.write(" <td>"+str(params['fid'])+"</td>\n") 658 out.write("</tr>\n") 659 out.write("\n") 660 out.write("<tr>\n") 661 out.write("<td>longitude</td>\n") 662 out.write("<td>decimal</td>\n") 663 if 'longitude' in params: 664 out.write(" <td>"+str(params['longitude'])+"</td>\n") 665 out.write(" <td>"+str(params['longitude'])+"</td>\n") 666 out.write("<td>degrees</td>\n") 667 out.write("</tr>\n") 668 out.write("\n") 669 out.write("<tr>\n") 670 out.write("<td>latitude</td>\n") 671 out.write("<td>decimal</td>\n") 672 if 'latitude' in params: 673 out.write(" <td>"+str(params['latitude'])+"</td>\n") 674 out.write(" <td>"+str(params['latitude'])+"</td>\n") 675 out.write("<td>degrees</td>\n") 676 out.write("</tr>\n") 677 out.write("\n") 678 out.write("<tr>\n") 679 out.write("<td>day</td>\n") 680 out.write("<td>uint</td>\n") 681 if 'day' in params: 682 out.write(" <td>"+str(params['day'])+"</td>\n") 683 out.write(" <td>"+str(params['day'])+"</td>\n") 684 out.write("<td>days</td>\n") 685 out.write("</tr>\n") 686 out.write("\n") 687 out.write("<tr>\n") 688 out.write("<td>hour</td>\n") 689 out.write("<td>uint</td>\n") 690 if 'hour' in params: 691 out.write(" <td>"+str(params['hour'])+"</td>\n") 692 out.write(" <td>"+str(params['hour'])+"</td>\n") 693 out.write("<td>hours</td>\n") 694 out.write("</tr>\n") 695 out.write("\n") 696 out.write("<tr>\n") 697 out.write("<td>min</td>\n") 698 out.write("<td>uint</td>\n") 699 if 'min' in params: 700 out.write(" <td>"+str(params['min'])+"</td>\n") 701 out.write(" <td>"+str(params['min'])+"</td>\n") 702 out.write("<td>minutes</td>\n") 703 out.write("</tr>\n") 704 out.write("\n") 705 out.write("<tr>\n") 706 out.write("<td>avewind</td>\n") 707 out.write("<td>uint</td>\n") 708 if 'avewind' in params: 709 out.write(" <td>"+str(params['avewind'])+"</td>\n") 710 out.write(" <td>"+str(params['avewind'])+"</td>\n") 711 out.write("<td>knots</td>\n") 712 out.write("</tr>\n") 713 out.write("\n") 714 out.write("<tr>\n") 715 out.write("<td>windgust</td>\n") 716 out.write("<td>uint</td>\n") 717 if 'windgust' in params: 718 out.write(" <td>"+str(params['windgust'])+"</td>\n") 719 out.write(" <td>"+str(params['windgust'])+"</td>\n") 720 out.write("<td>knots</td>\n") 721 out.write("</tr>\n") 722 out.write("\n") 723 out.write("<tr>\n") 724 out.write("<td>winddir</td>\n") 725 out.write("<td>uint</td>\n") 726 if 'winddir' in params: 727 out.write(" <td>"+str(params['winddir'])+"</td>\n") 728 out.write(" <td>"+str(params['winddir'])+"</td>\n") 729 out.write("<td>degrees</td>\n") 730 out.write("</tr>\n") 731 out.write("\n") 732 out.write("<tr>\n") 733 out.write("<td>windgustdir</td>\n") 734 out.write("<td>uint</td>\n") 735 if 'windgustdir' in params: 736 out.write(" <td>"+str(params['windgustdir'])+"</td>\n") 737 out.write(" <td>"+str(params['windgustdir'])+"</td>\n") 738 out.write("<td>degrees</td>\n") 739 out.write("</tr>\n") 740 out.write("\n") 741 out.write("<tr>\n") 742 out.write("<td>airtemp</td>\n") 743 out.write("<td>decimal</td>\n") 744 if 'airtemp' in params: 745 out.write(" <td>"+str(params['airtemp'])+"</td>\n") 746 out.write(" <td>"+str(params['airtemp'])+"</td>\n") 747 out.write("<td>degrees Celsius</td>\n") 748 out.write("</tr>\n") 749 out.write("\n") 750 out.write("<tr>\n") 751 out.write("<td>relhumid</td>\n") 752 out.write("<td>uint</td>\n") 753 if 'relhumid' in params: 754 out.write(" <td>"+str(params['relhumid'])+"</td>\n") 755 out.write(" <td>"+str(params['relhumid'])+"</td>\n") 756 out.write("<td>percent</td>\n") 757 out.write("</tr>\n") 758 out.write("\n") 759 out.write("<tr>\n") 760 out.write("<td>dewpoint</td>\n") 761 out.write("<td>decimal</td>\n") 762 if 'dewpoint' in params: 763 out.write(" <td>"+str(params['dewpoint'])+"</td>\n") 764 out.write(" <td>"+str(params['dewpoint'])+"</td>\n") 765 out.write("<td>degrees Celsius</td>\n") 766 out.write("</tr>\n") 767 out.write("\n") 768 out.write("<tr>\n") 769 out.write("<td>airpressure</td>\n") 770 out.write("<td>udecimal</td>\n") 771 if 'airpressure' in params: 772 out.write(" <td>"+str(params['airpressure'])+"</td>\n") 773 out.write(" <td>"+str(params['airpressure'])+"</td>\n") 774 out.write("<td>hPa</td>\n") 775 out.write("</tr>\n") 776 out.write("\n") 777 out.write("<tr>\n") 778 out.write("<td>airpressuretrend</td>\n") 779 out.write("<td>uint</td>\n") 780 if 'airpressuretrend' in params: 781 out.write(" <td>"+str(params['airpressuretrend'])+"</td>\n") 782 if str(params['airpressuretrend']) in airpressuretrendDecodeLut: 783 out.write("<td>"+airpressuretrendDecodeLut[str(params['airpressuretrend'])]+"</td>") 784 else: 785 out.write("<td><i>Missing LUT entry</i></td>") 786 out.write("</tr>\n") 787 out.write("\n") 788 out.write("<tr>\n") 789 out.write("<td>horizvis</td>\n") 790 out.write("<td>udecimal</td>\n") 791 if 'horizvis' in params: 792 out.write(" <td>"+str(params['horizvis'])+"</td>\n") 793 out.write(" <td>"+str(params['horizvis'])+"</td>\n") 794 out.write("<td>nm</td>\n") 795 out.write("</tr>\n") 796 out.write("\n") 797 out.write("<tr>\n") 798 out.write("<td>waterlevel</td>\n") 799 out.write("<td>decimal</td>\n") 800 if 'waterlevel' in params: 801 out.write(" <td>"+str(params['waterlevel'])+"</td>\n") 802 out.write(" <td>"+str(params['waterlevel'])+"</td>\n") 803 out.write("<td>m</td>\n") 804 out.write("</tr>\n") 805 out.write("\n") 806 out.write("<tr>\n") 807 out.write("<td>waterleveltrend</td>\n") 808 out.write("<td>uint</td>\n") 809 if 'waterleveltrend' in params: 810 out.write(" <td>"+str(params['waterleveltrend'])+"</td>\n") 811 if str(params['waterleveltrend']) in waterleveltrendDecodeLut: 812 out.write("<td>"+waterleveltrendDecodeLut[str(params['waterleveltrend'])]+"</td>") 813 else: 814 out.write("<td><i>Missing LUT entry</i></td>") 815 out.write("</tr>\n") 816 out.write("\n") 817 out.write("<tr>\n") 818 out.write("<td>surfcurspeed</td>\n") 819 out.write("<td>udecimal</td>\n") 820 if 'surfcurspeed' in params: 821 out.write(" <td>"+str(params['surfcurspeed'])+"</td>\n") 822 out.write(" <td>"+str(params['surfcurspeed'])+"</td>\n") 823 out.write("<td>knots</td>\n") 824 out.write("</tr>\n") 825 out.write("\n") 826 out.write("<tr>\n") 827 out.write("<td>surfcurdir</td>\n") 828 out.write("<td>uint</td>\n") 829 if 'surfcurdir' in params: 830 out.write(" <td>"+str(params['surfcurdir'])+"</td>\n") 831 out.write(" <td>"+str(params['surfcurdir'])+"</td>\n") 832 out.write("<td>degrees</td>\n") 833 out.write("</tr>\n") 834 out.write("\n") 835 out.write("<tr>\n") 836 out.write("<td>curspeed2</td>\n") 837 out.write("<td>udecimal</td>\n") 838 if 'curspeed2' in params: 839 out.write(" <td>"+str(params['curspeed2'])+"</td>\n") 840 out.write(" <td>"+str(params['curspeed2'])+"</td>\n") 841 out.write("<td>knots</td>\n") 842 out.write("</tr>\n") 843 out.write("\n") 844 out.write("<tr>\n") 845 out.write("<td>curdir2</td>\n") 846 out.write("<td>uint</td>\n") 847 if 'curdir2' in params: 848 out.write(" <td>"+str(params['curdir2'])+"</td>\n") 849 out.write(" <td>"+str(params['curdir2'])+"</td>\n") 850 out.write("<td>degrees</td>\n") 851 out.write("</tr>\n") 852 out.write("\n") 853 out.write("<tr>\n") 854 out.write("<td>curlevel2</td>\n") 855 out.write("<td>uint</td>\n") 856 if 'curlevel2' in params: 857 out.write(" <td>"+str(params['curlevel2'])+"</td>\n") 858 out.write(" <td>"+str(params['curlevel2'])+"</td>\n") 859 out.write("<td>m</td>\n") 860 out.write("</tr>\n") 861 out.write("\n") 862 out.write("<tr>\n") 863 out.write("<td>curspeed3</td>\n") 864 out.write("<td>udecimal</td>\n") 865 if 'curspeed3' in params: 866 out.write(" <td>"+str(params['curspeed3'])+"</td>\n") 867 out.write(" <td>"+str(params['curspeed3'])+"</td>\n") 868 out.write("<td>knots</td>\n") 869 out.write("</tr>\n") 870 out.write("\n") 871 out.write("<tr>\n") 872 out.write("<td>curdir3</td>\n") 873 out.write("<td>uint</td>\n") 874 if 'curdir3' in params: 875 out.write(" <td>"+str(params['curdir3'])+"</td>\n") 876 out.write(" <td>"+str(params['curdir3'])+"</td>\n") 877 out.write("<td>degrees</td>\n") 878 out.write("</tr>\n") 879 out.write("\n") 880 out.write("<tr>\n") 881 out.write("<td>curlevel3</td>\n") 882 out.write("<td>uint</td>\n") 883 if 'curlevel3' in params: 884 out.write(" <td>"+str(params['curlevel3'])+"</td>\n") 885 out.write(" <td>"+str(params['curlevel3'])+"</td>\n") 886 out.write("<td>m</td>\n") 887 out.write("</tr>\n") 888 out.write("\n") 889 out.write("<tr>\n") 890 out.write("<td>sigwaveheight</td>\n") 891 out.write("<td>udecimal</td>\n") 892 if 'sigwaveheight' in params: 893 out.write(" <td>"+str(params['sigwaveheight'])+"</td>\n") 894 out.write(" <td>"+str(params['sigwaveheight'])+"</td>\n") 895 out.write("<td>m</td>\n") 896 out.write("</tr>\n") 897 out.write("\n") 898 out.write("<tr>\n") 899 out.write("<td>waveperiod</td>\n") 900 out.write("<td>uint</td>\n") 901 if 'waveperiod' in params: 902 out.write(" <td>"+str(params['waveperiod'])+"</td>\n") 903 out.write(" <td>"+str(params['waveperiod'])+"</td>\n") 904 out.write("<td>sec</td>\n") 905 out.write("</tr>\n") 906 out.write("\n") 907 out.write("<tr>\n") 908 out.write("<td>wavedir</td>\n") 909 out.write("<td>uint</td>\n") 910 if 'wavedir' in params: 911 out.write(" <td>"+str(params['wavedir'])+"</td>\n") 912 out.write(" <td>"+str(params['wavedir'])+"</td>\n") 913 out.write("<td>degrees</td>\n") 914 out.write("</tr>\n") 915 out.write("\n") 916 out.write("<tr>\n") 917 out.write("<td>swellheight</td>\n") 918 out.write("<td>udecimal</td>\n") 919 if 'swellheight' in params: 920 out.write(" <td>"+str(params['swellheight'])+"</td>\n") 921 out.write(" <td>"+str(params['swellheight'])+"</td>\n") 922 out.write("<td>m</td>\n") 923 out.write("</tr>\n") 924 out.write("\n") 925 out.write("<tr>\n") 926 out.write("<td>swellperiod</td>\n") 927 out.write("<td>uint</td>\n") 928 if 'swellperiod' in params: 929 out.write(" <td>"+str(params['swellperiod'])+"</td>\n") 930 out.write(" <td>"+str(params['swellperiod'])+"</td>\n") 931 out.write("<td>sec</td>\n") 932 out.write("</tr>\n") 933 out.write("\n") 934 out.write("<tr>\n") 935 out.write("<td>swelldir</td>\n") 936 out.write("<td>uint</td>\n") 937 if 'swelldir' in params: 938 out.write(" <td>"+str(params['swelldir'])+"</td>\n") 939 out.write(" <td>"+str(params['swelldir'])+"</td>\n") 940 out.write("<td>degrees</td>\n") 941 out.write("</tr>\n") 942 out.write("\n") 943 out.write("<tr>\n") 944 out.write("<td>seastate</td>\n") 945 out.write("<td>uint</td>\n") 946 if 'seastate' in params: 947 out.write(" <td>"+str(params['seastate'])+"</td>\n") 948 if str(params['seastate']) in seastateDecodeLut: 949 out.write("<td>"+seastateDecodeLut[str(params['seastate'])]+"</td>") 950 else: 951 out.write("<td><i>Missing LUT entry</i></td>") 952 out.write("<td>Beaufort scale</td>\n") 953 out.write("</tr>\n") 954 out.write("\n") 955 out.write("<tr>\n") 956 out.write("<td>watertemp</td>\n") 957 out.write("<td>decimal</td>\n") 958 if 'watertemp' in params: 959 out.write(" <td>"+str(params['watertemp'])+"</td>\n") 960 out.write(" <td>"+str(params['watertemp'])+"</td>\n") 961 out.write("<td>degrees Celsius</td>\n") 962 out.write("</tr>\n") 963 out.write("\n") 964 out.write("<tr>\n") 965 out.write("<td>preciptype</td>\n") 966 out.write("<td>uint</td>\n") 967 if 'preciptype' in params: 968 out.write(" <td>"+str(params['preciptype'])+"</td>\n") 969 if str(params['preciptype']) in preciptypeDecodeLut: 970 out.write("<td>"+preciptypeDecodeLut[str(params['preciptype'])]+"</td>") 971 else: 972 out.write("<td><i>Missing LUT entry</i></td>") 973 out.write("<td>WMO scale index</td>\n") 974 out.write("</tr>\n") 975 out.write("\n") 976 out.write("<tr>\n") 977 out.write("<td>salinity</td>\n") 978 out.write("<td>decimal</td>\n") 979 if 'salinity' in params: 980 out.write(" <td>"+str(params['salinity'])+"</td>\n") 981 out.write(" <td>"+str(params['salinity'])+"</td>\n") 982 out.write("<td>0/00</td>\n") 983 out.write("</tr>\n") 984 out.write("\n") 985 out.write("<tr>\n") 986 out.write("<td>ice</td>\n") 987 out.write("<td>bool</td>\n") 988 if 'ice' in params: 989 out.write(" <td>"+str(params['ice'])+"</td>\n") 990 out.write(" <td>"+str(params['ice'])+"</td>\n") 991 out.write("</tr>\n") 992 out.write("\n") 993 out.write("<tr>\n") 994 out.write("<td>Spare</td>\n") 995 out.write("<td>uint</td>\n") 996 if 'Spare' in params: 997 out.write(" <td>"+str(params['Spare'])+"</td>\n") 998 out.write(" <td>"+str(params['Spare'])+"</td>\n") 999 out.write("</tr>\n") 1000 out.write("</table>\n")
1001 1002
1003 -def printKml(params, out=sys.stdout):
1004 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer''' 1005 out.write("\ <Placemark>\n") 1006 out.write("\t <name>"+str(params['UserID'])+"</name>\n") 1007 out.write("\t\t<description>\n") 1008 import StringIO 1009 buf = StringIO.StringIO() 1010 printHtml(params,buf) 1011 import cgi 1012 out.write(cgi.escape(buf.getvalue())) 1013 out.write("\t\t</description>\n") 1014 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n") 1015 out.write("\t\t<Point>\n") 1016 out.write("\t\t\t<coordinates>") 1017 out.write(str(params['longitude'])) 1018 out.write(',') 1019 out.write(str(params['latitude'])) 1020 out.write(",0</coordinates>\n") 1021 out.write("\t\t</Point>\n") 1022 out.write("\t</Placemark>\n")
1023
1024 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
1025 '''Print a imo_met_hydro message to stdout. 1026 1027 Fields in params: 1028 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8") 1029 - RepeatIndicator(uint): Indicated how many times a message has been repeated 1030 - UserID(uint): Unique ship identification number (MMSI) 1031 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0") 1032 - dac(uint): Designated Area Code - part 1 of the IAI (field automatically set to "1") 1033 - fid(uint): Functional Identifier - part 2 of the IAI (field automatically set to "11") 1034 - longitude(decimal): Location of the vessel. East West location 1035 - latitude(decimal): Location of the vessel. North South location 1036 - day(uint): Day 0..31 1037 - hour(uint): Hour 0..23 1038 - min(uint): Min 1039 - avewind(uint): Average wind speed values for the last 10 minutes. 1040 - windgust(uint): Wind gust is the max wind speed value reading during the last 10 minutes. 1041 - winddir(uint): Wind direction 1042 - windgustdir(uint): Wind direction for the gust. 1043 - airtemp(decimal): Bry bulb temperature 1044 - relhumid(uint): Relative humidity 1045 - dewpoint(decimal): Bry bulb temperature - FIX: should this be a udecimal?? 1046 - airpressure(udecimal): Air pressure. FIX: 9 bits only goes 0..511 1047 - airpressuretrend(uint): Air pressure trend 1048 - horizvis(udecimal): Horizontal visibility 1049 - waterlevel(decimal): Water level (incl. tide) 1050 - waterleveltrend(uint): Water level trend 1051 - surfcurspeed(udecimal): Surace current speed 1052 - surfcurdir(uint): Surface current direction 1053 - curspeed2(udecimal): Level 2 current speed 1054 - curdir2(uint): Level 2 current direction 1055 - curlevel2(uint): Measuring level below sea surface for level 2 1056 - curspeed3(udecimal): Level 3 current speed 1057 - curdir3(uint): Level 3 current direction 1058 - curlevel3(uint): Measuring level below sea surface for level 3 1059 - sigwaveheight(udecimal): Significan wave height 1060 - waveperiod(uint): Wave period - FIX: How does to fit to the power spectrum? 1061 - wavedir(uint): Wave direction - FIX: please define this better 1062 - swellheight(udecimal): Swell height 1063 - swellperiod(uint): Swell period - FIX: How does to fit to the power spectrum? 1064 - swelldir(uint): Swell direction - FIX: please define this better 1065 - seastate(uint): Sea state according to the Beaufort scale 1066 - watertemp(decimal): Water temp (FIX: at surface? Any requirements on how measured?) 1067 - preciptype(uint): According to WMO 1068 - salinity(decimal): Salinity - FIX: by what standard? Measured how? 1069 - ice(bool): Yes or no for the presence of ice. FIX: what types of ice constitute a yes?? 1070 - Spare(uint): Must be zero. FIX: this does not seem slot aligned. (field automatically set to "0") 1071 @param params: Dictionary of field names/values. 1072 @param out: File like object to write to 1073 @rtype: stdout 1074 @return: text to out 1075 ''' 1076 1077 if 'std'==format: 1078 out.write("imo_met_hydro:\n") 1079 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n") 1080 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n") 1081 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n") 1082 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n") 1083 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n") 1084 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n") 1085 if 'longitude' in params: out.write(" longitude: "+str(params['longitude'])+"\n") 1086 if 'latitude' in params: out.write(" latitude: "+str(params['latitude'])+"\n") 1087 if 'day' in params: out.write(" day: "+str(params['day'])+"\n") 1088 if 'hour' in params: out.write(" hour: "+str(params['hour'])+"\n") 1089 if 'min' in params: out.write(" min: "+str(params['min'])+"\n") 1090 if 'avewind' in params: out.write(" avewind: "+str(params['avewind'])+"\n") 1091 if 'windgust' in params: out.write(" windgust: "+str(params['windgust'])+"\n") 1092 if 'winddir' in params: out.write(" winddir: "+str(params['winddir'])+"\n") 1093 if 'windgustdir' in params: out.write(" windgustdir: "+str(params['windgustdir'])+"\n") 1094 if 'airtemp' in params: out.write(" airtemp: "+str(params['airtemp'])+"\n") 1095 if 'relhumid' in params: out.write(" relhumid: "+str(params['relhumid'])+"\n") 1096 if 'dewpoint' in params: out.write(" dewpoint: "+str(params['dewpoint'])+"\n") 1097 if 'airpressure' in params: out.write(" airpressure: "+str(params['airpressure'])+"\n") 1098 if 'airpressuretrend' in params: out.write(" airpressuretrend: "+str(params['airpressuretrend'])+"\n") 1099 if 'horizvis' in params: out.write(" horizvis: "+str(params['horizvis'])+"\n") 1100 if 'waterlevel' in params: out.write(" waterlevel: "+str(params['waterlevel'])+"\n") 1101 if 'waterleveltrend' in params: out.write(" waterleveltrend: "+str(params['waterleveltrend'])+"\n") 1102 if 'surfcurspeed' in params: out.write(" surfcurspeed: "+str(params['surfcurspeed'])+"\n") 1103 if 'surfcurdir' in params: out.write(" surfcurdir: "+str(params['surfcurdir'])+"\n") 1104 if 'curspeed2' in params: out.write(" curspeed2: "+str(params['curspeed2'])+"\n") 1105 if 'curdir2' in params: out.write(" curdir2: "+str(params['curdir2'])+"\n") 1106 if 'curlevel2' in params: out.write(" curlevel2: "+str(params['curlevel2'])+"\n") 1107 if 'curspeed3' in params: out.write(" curspeed3: "+str(params['curspeed3'])+"\n") 1108 if 'curdir3' in params: out.write(" curdir3: "+str(params['curdir3'])+"\n") 1109 if 'curlevel3' in params: out.write(" curlevel3: "+str(params['curlevel3'])+"\n") 1110 if 'sigwaveheight' in params: out.write(" sigwaveheight: "+str(params['sigwaveheight'])+"\n") 1111 if 'waveperiod' in params: out.write(" waveperiod: "+str(params['waveperiod'])+"\n") 1112 if 'wavedir' in params: out.write(" wavedir: "+str(params['wavedir'])+"\n") 1113 if 'swellheight' in params: out.write(" swellheight: "+str(params['swellheight'])+"\n") 1114 if 'swellperiod' in params: out.write(" swellperiod: "+str(params['swellperiod'])+"\n") 1115 if 'swelldir' in params: out.write(" swelldir: "+str(params['swelldir'])+"\n") 1116 if 'seastate' in params: out.write(" seastate: "+str(params['seastate'])+"\n") 1117 if 'watertemp' in params: out.write(" watertemp: "+str(params['watertemp'])+"\n") 1118 if 'preciptype' in params: out.write(" preciptype: "+str(params['preciptype'])+"\n") 1119 if 'salinity' in params: out.write(" salinity: "+str(params['salinity'])+"\n") 1120 if 'ice' in params: out.write(" ice: "+str(params['ice'])+"\n") 1121 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n") 1122 elif 'csv'==format: 1123 if None == options.fieldList: 1124 options.fieldList = fieldList 1125 needComma = False; 1126 for field in fieldList: 1127 if needComma: out.write(',') 1128 needComma = True 1129 if field in params: 1130 out.write(str(params[field])) 1131 # else: leave it empty 1132 out.write("\n") 1133 elif 'html'==format: 1134 printHtml(params,out) 1135 elif 'sql'==format: 1136 sqlInsertStr(params,out,dbType=dbType) 1137 elif 'kml'==format: 1138 printKml(params,out) 1139 elif 'kml-full'==format: 1140 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") 1141 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n") 1142 out.write("<Document>\n") 1143 out.write(" <name>imo_met_hydro</name>\n") 1144 printKml(params,out) 1145 out.write("</Document>\n") 1146 out.write("</kml>\n") 1147 else: 1148 print "ERROR: unknown format:",format 1149 assert False 1150 1151 return # Nothing to return
1152 1153 RepeatIndicatorEncodeLut = { 1154 'default':'0', 1155 'do not repeat any more':'3', 1156 } #RepeatIndicatorEncodeLut 1157 1158 RepeatIndicatorDecodeLut = { 1159 '0':'default', 1160 '3':'do not repeat any more', 1161 } # RepeatIndicatorEncodeLut 1162 1163 airpressuretrendEncodeLut = { 1164 'steady':'0', 1165 'decreasing':'1', 1166 'increasing':'2', 1167 'unavailable':'3', 1168 } #airpressuretrendEncodeLut 1169 1170 airpressuretrendDecodeLut = { 1171 '0':'steady', 1172 '1':'decreasing', 1173 '2':'increasing', 1174 '3':'unavailable', 1175 } # airpressuretrendEncodeLut 1176 1177 waterleveltrendEncodeLut = { 1178 'steady':'0', 1179 'decreasing':'1', 1180 'increasing':'2', 1181 'unavailable':'3', 1182 } #waterleveltrendEncodeLut 1183 1184 waterleveltrendDecodeLut = { 1185 '0':'steady', 1186 '1':'decreasing', 1187 '2':'increasing', 1188 '3':'unavailable', 1189 } # waterleveltrendEncodeLut 1190 1191 seastateEncodeLut = { 1192 'Calm':'0', 1193 'Light air':'1', 1194 'Light breeze':'2', 1195 'Gentle breeze':'3', 1196 'Moderate breeze':'4', 1197 'Fresh breeze':'5', 1198 'Strong breeze':'6', 1199 'Near gale':'7', 1200 'Gale':'8', 1201 'Strong gale':'9', 1202 'Storm':'10', 1203 'Violent storm':'11', 1204 'Hurricane':'12', 1205 'unavailable':'15', 1206 } #seastateEncodeLut 1207 1208 seastateDecodeLut = { 1209 '0':'Calm', 1210 '1':'Light air', 1211 '2':'Light breeze', 1212 '3':'Gentle breeze', 1213 '4':'Moderate breeze', 1214 '5':'Fresh breeze', 1215 '6':'Strong breeze', 1216 '7':'Near gale', 1217 '8':'Gale', 1218 '9':'Strong gale', 1219 '10':'Storm', 1220 '11':'Violent storm', 1221 '12':'Hurricane', 1222 '15':'unavailable', 1223 } # seastateEncodeLut 1224 1225 preciptypeEncodeLut = { 1226 'FIX: find the WMO list of types':'0', 1227 'unavailable':'7', 1228 } #preciptypeEncodeLut 1229 1230 preciptypeDecodeLut = { 1231 '0':'FIX: find the WMO list of types', 1232 '7':'unavailable', 1233 } # preciptypeEncodeLut 1234 1235 ###################################################################### 1236 # SQL SUPPORT 1237 ###################################################################### 1238
1239 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 1240 ,addCoastGuardFields=True 1241 ,dbType='postgres' 1242 ):
1243 ''' 1244 Return the SQL CREATE command for this message type 1245 @param outfile: file like object to print to. 1246 @param fields: which fields to put in the create. Defaults to all. 1247 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 1248 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 1249 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 1250 @type addCoastGuardFields: bool 1251 @return: sql create string 1252 @rtype: str 1253 1254 @see: sqlCreate 1255 ''' 1256 # FIX: should this sqlCreate be the same as in LaTeX (createFuncName) rather than hard coded? 1257 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
1258
1259 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
1260 ''' 1261 Return the sqlhelp object to create the table. 1262 1263 @param fields: which fields to put in the create. Defaults to all. 1264 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 1265 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 1266 @type addCoastGuardFields: bool 1267 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 1268 @return: An object that can be used to generate a return 1269 @rtype: sqlhelp.create 1270 ''' 1271 if None == fields: fields = fieldList 1272 import sqlhelp 1273 c = sqlhelp.create('imo_met_hydro',dbType=dbType) 1274 c.addPrimaryKey() 1275 if 'MessageID' in fields: c.addInt ('MessageID') 1276 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator') 1277 if 'UserID' in fields: c.addInt ('UserID') 1278 if 'Spare' in fields: c.addInt ('Spare') 1279 if 'dac' in fields: c.addInt ('dac') 1280 if 'fid' in fields: c.addInt ('fid') 1281 if dbType != 'postgres': 1282 if 'longitude' in fields: c.addDecimal('longitude',7,4) 1283 if dbType != 'postgres': 1284 if 'latitude' in fields: c.addDecimal('latitude',7,4) 1285 if 'day' in fields: c.addInt ('day') 1286 if 'hour' in fields: c.addInt ('hour') 1287 if 'min' in fields: c.addInt ('min') 1288 if 'avewind' in fields: c.addInt ('avewind') 1289 if 'windgust' in fields: c.addInt ('windgust') 1290 if 'winddir' in fields: c.addInt ('winddir') 1291 if 'windgustdir' in fields: c.addInt ('windgustdir') 1292 if 'airtemp' in fields: c.addDecimal('airtemp',4,1) 1293 if 'relhumid' in fields: c.addInt ('relhumid') 1294 if 'dewpoint' in fields: c.addDecimal('dewpoint',4,1) 1295 if 'airpressure' in fields: c.addDecimal('airpressure',3,0) 1296 if 'airpressuretrend' in fields: c.addInt ('airpressuretrend') 1297 if 'horizvis' in fields: c.addDecimal('horizvis',3,1) 1298 if 'waterlevel' in fields: c.addDecimal('waterlevel',3,1) 1299 if 'waterleveltrend' in fields: c.addInt ('waterleveltrend') 1300 if 'surfcurspeed' in fields: c.addDecimal('surfcurspeed',3,1) 1301 if 'surfcurdir' in fields: c.addInt ('surfcurdir') 1302 if 'curspeed2' in fields: c.addDecimal('curspeed2',3,1) 1303 if 'curdir2' in fields: c.addInt ('curdir2') 1304 if 'curlevel2' in fields: c.addInt ('curlevel2') 1305 if 'curspeed3' in fields: c.addDecimal('curspeed3',3,1) 1306 if 'curdir3' in fields: c.addInt ('curdir3') 1307 if 'curlevel3' in fields: c.addInt ('curlevel3') 1308 if 'sigwaveheight' in fields: c.addDecimal('sigwaveheight',3,1) 1309 if 'waveperiod' in fields: c.addInt ('waveperiod') 1310 if 'wavedir' in fields: c.addInt ('wavedir') 1311 if 'swellheight' in fields: c.addDecimal('swellheight',3,1) 1312 if 'swellperiod' in fields: c.addInt ('swellperiod') 1313 if 'swelldir' in fields: c.addInt ('swelldir') 1314 if 'seastate' in fields: c.addInt ('seastate') 1315 if 'watertemp' in fields: c.addDecimal('watertemp',4,1) 1316 if 'preciptype' in fields: c.addInt ('preciptype') 1317 if 'salinity' in fields: c.addDecimal('salinity',3,1) 1318 if 'ice' in fields: c.addBool('ice') 1319 if 'Spare' in fields: c.addInt ('Spare') 1320 1321 if addCoastGuardFields: 1322 # c.addInt('cg_rssi') # Relative signal strength indicator 1323 # c.addInt('cg_d') # dBm receive strength 1324 # c.addInt('cg_T') # Receive timestamp from the AIS equipment 1325 # c.addInt('cg_S') # Slot received in 1326 # c.addVarChar('cg_x',10) # Idonno 1327 c.addVarChar('cg_r',15) # Receiver station ID - should usually be an MMSI, but sometimes is a string 1328 c.addInt('cg_sec') # UTC seconds since the epoch 1329 1330 c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream 1331 1332 if dbType == 'postgres': 1333 c.addPostGIS('Position','POINT',2); 1334 1335 return c
1336
1337 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
1338 ''' 1339 Return the SQL INSERT command for this message type 1340 @param params: dictionary of values keyed by field name 1341 @param outfile: file like object to print to. 1342 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 1343 @return: sql create string 1344 @rtype: str 1345 1346 @see: sqlCreate 1347 ''' 1348 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
1349 1350
1351 -def sqlInsert(params,extraParams=None,dbType='postgres'):
1352 ''' 1353 Give the SQL INSERT statement 1354 @param params: dict keyed by field name of values 1355 @param extraParams: any extra fields that you have created beyond the normal ais message fields 1356 @rtype: sqlhelp.insert 1357 @return: insert class instance 1358 @todo: allow optional type checking of params? 1359 @warning: this will take invalid keys happily and do what??? 1360 ''' 1361 import sqlhelp 1362 i = sqlhelp.insert('imo_met_hydro',dbType=dbType) 1363 1364 if dbType=='postgres': 1365 finished = [] 1366 for key in params: 1367 if key in finished: 1368 continue 1369 1370 if key not in toPgFields and key not in fromPgFields: 1371 if type(params[key])==Decimal: i.add(key,float(params[key])) 1372 else: i.add(key,params[key]) 1373 else: 1374 if key in fromPgFields: 1375 val = params[key] 1376 # Had better be a WKT type like POINT(-88.1 30.321) 1377 i.addPostGIS(key,val) 1378 finished.append(key) 1379 else: 1380 # Need to construct the type. 1381 pgName = toPgFields[key] 1382 #valStr='GeomFromText(\''+pgTypes[pgName]+'(' 1383 valStr=pgTypes[pgName]+'(' 1384 vals = [] 1385 for nonPgKey in fromPgFields[pgName]: 1386 vals.append(str(params[nonPgKey])) 1387 finished.append(nonPgKey) 1388 valStr+=' '.join(vals)+')' 1389 i.addPostGIS(pgName,valStr) 1390 else: 1391 for key in params: 1392 if type(params[key])==Decimal: i.add(key,float(params[key])) 1393 else: i.add(key,params[key]) 1394 1395 if None != extraParams: 1396 for key in extraParams: 1397 i.add(key,extraParams[key]) 1398 1399 return i
1400 1401 ###################################################################### 1402 # LATEX SUPPORT 1403 ###################################################################### 1404
1405 -def latexDefinitionTable(outfile=sys.stdout 1406 ):
1407 ''' 1408 Return the LaTeX definition table for this message type 1409 @param outfile: file like object to print to. 1410 @type outfile: file obj 1411 @return: LaTeX table string via the outfile 1412 @rtype: str 1413 1414 ''' 1415 o = outfile 1416 1417 o.write(''' 1418 \\begin{table}%[htb] 1419 \\centering 1420 \\begin{tabular}{|l|c|l|} 1421 \\hline 1422 Parameter & Number of bits & Description 1423 \\\\ \\hline\\hline 1424 MessageID & 6 & AIS message number. Must be 8 \\\\ \hline 1425 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline 1426 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline 1427 Spare & 2 & Reserved for definition by a regional authority. \\\\ \hline 1428 dac & 10 & Designated Area Code - part 1 of the IAI \\\\ \hline 1429 fid & 6 & Functional Identifier - part 2 of the IAI \\\\ \hline 1430 longitude & 25 & Location of the vessel. East West location \\\\ \hline 1431 latitude & 24 & Location of the vessel. North South location \\\\ \hline 1432 day & 5 & Day 0..31 \\\\ \hline 1433 hour & 5 & Hour 0..23 \\\\ \hline 1434 min & 6 & Min \\\\ \hline 1435 avewind & 7 & Average wind speed values for the last 10 minutes. \\\\ \hline 1436 windgust & 7 & Wind gust is the max wind speed value reading during the last 10 minutes. \\\\ \hline 1437 winddir & 9 & Wind direction \\\\ \hline 1438 windgustdir & 9 & Wind direction for the gust. \\\\ \hline 1439 airtemp & 11 & Bry bulb temperature \\\\ \hline 1440 relhumid & 7 & Relative humidity \\\\ \hline 1441 dewpoint & 10 & Bry bulb temperature - FIX: should this be a udecimal?? \\\\ \hline 1442 airpressure & 9 & Air pressure. FIX: 9 bits only goes 0..511 \\\\ \hline 1443 airpressuretrend & 2 & Air pressure trend \\\\ \hline 1444 horizvis & 8 & Horizontal visibility \\\\ \hline 1445 waterlevel & 9 & Water level (incl. tide) \\\\ \hline 1446 waterleveltrend & 2 & Water level trend \\\\ \hline 1447 surfcurspeed & 8 & Surace current speed \\\\ \hline 1448 surfcurdir & 9 & Surface current direction \\\\ \hline 1449 curspeed2 & 8 & Level 2 current speed \\\\ \hline 1450 curdir2 & 9 & Level 2 current direction \\\\ \hline 1451 curlevel2 & 5 & Measuring level below sea surface for level 2 \\\\ \hline 1452 curspeed3 & 8 & Level 3 current speed \\\\ \hline 1453 curdir3 & 9 & Level 3 current direction \\\\ \hline 1454 curlevel3 & 5 & Measuring level below sea surface for level 3 \\\\ \hline 1455 sigwaveheight & 8 & Significan wave height \\\\ \hline 1456 waveperiod & 8 & Wave period - FIX: How does to fit to the power spectrum? \\\\ \hline 1457 wavedir & 9 & Wave direction - FIX: please define this better \\\\ \hline 1458 swellheight & 8 & Swell height \\\\ \hline 1459 swellperiod & 8 & Swell period - FIX: How does to fit to the power spectrum? \\\\ \hline 1460 swelldir & 9 & Swell direction - FIX: please define this better \\\\ \hline 1461 seastate & 4 & Sea state according to the Beaufort scale \\\\ \hline 1462 watertemp & 10 & Water temp (FIX: at surface? Any requirements on how measured?) \\\\ \hline 1463 preciptype & 3 & According to WMO \\\\ \hline 1464 salinity & 9 & Salinity - FIX: by what standard? Measured how? \\\\ \hline 1465 ice & 1 & Yes or no for the presence of ice. FIX: what types of ice constitute a yes?? \\\\ \hline 1466 Spare & 6 & Must be zero. FIX: this does not seem slot aligned.\\\\ \\hline \\hline 1467 Total bits & 355 & Appears to take 2 slots with 69 pad bits to fill the last slot \\\\ \\hline 1468 \\end{tabular} 1469 \\caption{AIS message number 8: IMO meteorological and hydroglogical data. Specified in SN\\Circ.236 Annex 2. Also defined in IALA Guidelines on AIS, Vol 1, Part 1, Ed. 1.3. Guildeline No 1028. } 1470 \\label{tab:imo_met_hydro} 1471 \\end{table} 1472 ''')
1473 1474 1475 ###################################################################### 1476 # UNIT TESTING 1477 ###################################################################### 1478 import unittest
1479 -def testParams():
1480 '''Return a params file base on the testvalue tags. 1481 @rtype: dict 1482 @return: params based on testvalue tags 1483 ''' 1484 params = {} 1485 params['MessageID'] = 8 1486 params['RepeatIndicator'] = 1 1487 params['UserID'] = 1193046 1488 params['Spare'] = 0 1489 params['dac'] = 1 1490 params['fid'] = 11 1491 params['longitude'] = Decimal('-122.16328') 1492 params['latitude'] = Decimal('37.42446') 1493 params['day'] = 3 1494 params['hour'] = 21 1495 params['min'] = 58 1496 params['avewind'] = 23 1497 params['windgust'] = 35 1498 params['winddir'] = 329 1499 params['windgustdir'] = 293 1500 params['airtemp'] = Decimal('-40.1') 1501 params['relhumid'] = 99 1502 params['dewpoint'] = Decimal('-19.2') 1503 params['airpressure'] = Decimal('1150') 1504 params['airpressuretrend'] = 2 1505 params['horizvis'] = Decimal('11.9') 1506 params['waterlevel'] = Decimal('-8.9') 1507 params['waterleveltrend'] = 0 1508 params['surfcurspeed'] = Decimal('22.3') 1509 params['surfcurdir'] = 321 1510 params['curspeed2'] = Decimal('12.7') 1511 params['curdir2'] = 122 1512 params['curlevel2'] = 29 1513 params['curspeed3'] = Decimal('19.2') 1514 params['curdir3'] = 93 1515 params['curlevel3'] = 28 1516 params['sigwaveheight'] = Decimal('22.8') 1517 params['waveperiod'] = 2 1518 params['wavedir'] = 187 1519 params['swellheight'] = Decimal('0.2') 1520 params['swellperiod'] = 59 1521 params['swelldir'] = 1 1522 params['seastate'] = 12 1523 params['watertemp'] = Decimal('48.8') 1524 params['preciptype'] = 2 1525 params['salinity'] = Decimal('0.9') 1526 params['ice'] = True 1527 params['Spare'] = 0 1528 1529 return params
1530
1531 -class Testimo_met_hydro(unittest.TestCase):
1532 '''Use testvalue tag text from each type to build test case the imo_met_hydro message'''
1533 - def testEncodeDecode(self):
1534 1535 params = testParams() 1536 bits = encode(params) 1537 r = decode(bits) 1538 1539 # Check that each parameter came through ok. 1540 self.failUnlessEqual(r['MessageID'],params['MessageID']) 1541 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 1542 self.failUnlessEqual(r['UserID'],params['UserID']) 1543 self.failUnlessEqual(r['Spare'],params['Spare']) 1544 self.failUnlessEqual(r['dac'],params['dac']) 1545 self.failUnlessEqual(r['fid'],params['fid']) 1546 self.failUnlessAlmostEqual(r['longitude'],params['longitude'],4) 1547 self.failUnlessAlmostEqual(r['latitude'],params['latitude'],4) 1548 self.failUnlessEqual(r['day'],params['day']) 1549 self.failUnlessEqual(r['hour'],params['hour']) 1550 self.failUnlessEqual(r['min'],params['min']) 1551 self.failUnlessEqual(r['avewind'],params['avewind']) 1552 self.failUnlessEqual(r['windgust'],params['windgust']) 1553 self.failUnlessEqual(r['winddir'],params['winddir']) 1554 self.failUnlessEqual(r['windgustdir'],params['windgustdir']) 1555 self.failUnlessAlmostEqual(r['airtemp'],params['airtemp'],1) 1556 self.failUnlessEqual(r['relhumid'],params['relhumid']) 1557 self.failUnlessAlmostEqual(r['dewpoint'],params['dewpoint'],1) 1558 self.failUnlessAlmostEqual(r['airpressure'],params['airpressure'],0) 1559 self.failUnlessEqual(r['airpressuretrend'],params['airpressuretrend']) 1560 self.failUnlessAlmostEqual(r['horizvis'],params['horizvis'],1) 1561 self.failUnlessAlmostEqual(r['waterlevel'],params['waterlevel'],1) 1562 self.failUnlessEqual(r['waterleveltrend'],params['waterleveltrend']) 1563 self.failUnlessAlmostEqual(r['surfcurspeed'],params['surfcurspeed'],1) 1564 self.failUnlessEqual(r['surfcurdir'],params['surfcurdir']) 1565 self.failUnlessAlmostEqual(r['curspeed2'],params['curspeed2'],1) 1566 self.failUnlessEqual(r['curdir2'],params['curdir2']) 1567 self.failUnlessEqual(r['curlevel2'],params['curlevel2']) 1568 self.failUnlessAlmostEqual(r['curspeed3'],params['curspeed3'],1) 1569 self.failUnlessEqual(r['curdir3'],params['curdir3']) 1570 self.failUnlessEqual(r['curlevel3'],params['curlevel3']) 1571 self.failUnlessAlmostEqual(r['sigwaveheight'],params['sigwaveheight'],1) 1572 self.failUnlessEqual(r['waveperiod'],params['waveperiod']) 1573 self.failUnlessEqual(r['wavedir'],params['wavedir']) 1574 self.failUnlessAlmostEqual(r['swellheight'],params['swellheight'],1) 1575 self.failUnlessEqual(r['swellperiod'],params['swellperiod']) 1576 self.failUnlessEqual(r['swelldir'],params['swelldir']) 1577 self.failUnlessEqual(r['seastate'],params['seastate']) 1578 self.failUnlessAlmostEqual(r['watertemp'],params['watertemp'],1) 1579 self.failUnlessEqual(r['preciptype'],params['preciptype']) 1580 self.failUnlessAlmostEqual(r['salinity'],params['salinity'],1) 1581 self.failUnlessEqual(r['ice'],params['ice']) 1582 self.failUnlessEqual(r['Spare'],params['Spare'])
1583
1584 -def addMsgOptions(parser):
1585 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 1586 help='decode a "imo_met_hydro" AIS message') 1587 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 1588 help='encode a "imo_met_hydro" AIS message') 1589 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int' 1590 ,help='Field parameter value [default: %default]') 1591 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int' 1592 ,help='Field parameter value [default: %default]') 1593 parser.add_option('--longitude-field', dest='longitudeField',default=Decimal('181'),metavar='decimal',type='string' 1594 ,help='Field parameter value [default: %default]') 1595 parser.add_option('--latitude-field', dest='latitudeField',default=Decimal('91'),metavar='decimal',type='string' 1596 ,help='Field parameter value [default: %default]') 1597 parser.add_option('--day-field', dest='dayField',metavar='uint',type='int' 1598 ,help='Field parameter value [default: %default]') 1599 parser.add_option('--hour-field', dest='hourField',default=31,metavar='uint',type='int' 1600 ,help='Field parameter value [default: %default]') 1601 parser.add_option('--min-field', dest='minField',default=63,metavar='uint',type='int' 1602 ,help='Field parameter value [default: %default]') 1603 parser.add_option('--avewind-field', dest='avewindField',default=127,metavar='uint',type='int' 1604 ,help='Field parameter value [default: %default]') 1605 parser.add_option('--windgust-field', dest='windgustField',default=127,metavar='uint',type='int' 1606 ,help='Field parameter value [default: %default]') 1607 parser.add_option('--winddir-field', dest='winddirField',default=511,metavar='uint',type='int' 1608 ,help='Field parameter value [default: %default]') 1609 parser.add_option('--windgustdir-field', dest='windgustdirField',default=511,metavar='uint',type='int' 1610 ,help='Field parameter value [default: %default]') 1611 parser.add_option('--airtemp-field', dest='airtempField',default=Decimal('102.3'),metavar='decimal',type='string' 1612 ,help='Field parameter value [default: %default]') 1613 parser.add_option('--relhumid-field', dest='relhumidField',default=127,metavar='uint',type='int' 1614 ,help='Field parameter value [default: %default]') 1615 parser.add_option('--dewpoint-field', dest='dewpointField',default=Decimal('51.1'),metavar='decimal',type='string' 1616 ,help='Field parameter value [default: %default]') 1617 parser.add_option('--airpressure-field', dest='airpressureField',default=Decimal('1311'),metavar='udecimal',type='string' 1618 ,help='Field parameter value [default: %default]') 1619 parser.add_option('--airpressuretrend-field', dest='airpressuretrendField',default=3,metavar='uint',type='int' 1620 ,help='Field parameter value [default: %default]') 1621 parser.add_option('--horizvis-field', dest='horizvisField',default=Decimal('25.5'),metavar='udecimal',type='string' 1622 ,help='Field parameter value [default: %default]') 1623 parser.add_option('--waterlevel-field', dest='waterlevelField',metavar='decimal',type='string' 1624 ,help='Field parameter value [default: %default]') 1625 parser.add_option('--waterleveltrend-field', dest='waterleveltrendField',default=3,metavar='uint',type='int' 1626 ,help='Field parameter value [default: %default]') 1627 parser.add_option('--surfcurspeed-field', dest='surfcurspeedField',default=Decimal('25.5'),metavar='udecimal',type='string' 1628 ,help='Field parameter value [default: %default]') 1629 parser.add_option('--surfcurdir-field', dest='surfcurdirField',default=511,metavar='uint',type='int' 1630 ,help='Field parameter value [default: %default]') 1631 parser.add_option('--curspeed2-field', dest='curspeed2Field',default=Decimal('25.5'),metavar='udecimal',type='string' 1632 ,help='Field parameter value [default: %default]') 1633 parser.add_option('--curdir2-field', dest='curdir2Field',default=511,metavar='uint',type='int' 1634 ,help='Field parameter value [default: %default]') 1635 parser.add_option('--curlevel2-field', dest='curlevel2Field',default=31,metavar='uint',type='int' 1636 ,help='Field parameter value [default: %default]') 1637 parser.add_option('--curspeed3-field', dest='curspeed3Field',default=Decimal('25.5'),metavar='udecimal',type='string' 1638 ,help='Field parameter value [default: %default]') 1639 parser.add_option('--curdir3-field', dest='curdir3Field',default=511,metavar='uint',type='int' 1640 ,help='Field parameter value [default: %default]') 1641 parser.add_option('--curlevel3-field', dest='curlevel3Field',default=31,metavar='uint',type='int' 1642 ,help='Field parameter value [default: %default]') 1643 parser.add_option('--sigwaveheight-field', dest='sigwaveheightField',default=Decimal('25.5'),metavar='udecimal',type='string' 1644 ,help='Field parameter value [default: %default]') 1645 parser.add_option('--waveperiod-field', dest='waveperiodField',default=63,metavar='uint',type='int' 1646 ,help='Field parameter value [default: %default]') 1647 parser.add_option('--wavedir-field', dest='wavedirField',default=511,metavar='uint',type='int' 1648 ,help='Field parameter value [default: %default]') 1649 parser.add_option('--swellheight-field', dest='swellheightField',default=Decimal('25.5'),metavar='udecimal',type='string' 1650 ,help='Field parameter value [default: %default]') 1651 parser.add_option('--swellperiod-field', dest='swellperiodField',default=63,metavar='uint',type='int' 1652 ,help='Field parameter value [default: %default]') 1653 parser.add_option('--swelldir-field', dest='swelldirField',default=511,metavar='uint',type='int' 1654 ,help='Field parameter value [default: %default]') 1655 parser.add_option('--seastate-field', dest='seastateField',default=15,metavar='uint',type='int' 1656 ,help='Field parameter value [default: %default]') 1657 parser.add_option('--watertemp-field', dest='watertempField',default=Decimal('92.3'),metavar='decimal',type='string' 1658 ,help='Field parameter value [default: %default]') 1659 parser.add_option('--preciptype-field', dest='preciptypeField',default=7,metavar='uint',type='int' 1660 ,help='Field parameter value [default: %default]') 1661 parser.add_option('--salinity-field', dest='salinityField',default=Decimal('92.3'),metavar='decimal',type='string' 1662 ,help='Field parameter value [default: %default]') 1663 parser.add_option('--ice-field', dest='iceField',metavar='bool',type='int' 1664 ,help='Field parameter value [default: %default]')
1665 1666 ############################################################ 1667 if __name__=='__main__': 1668 1669 from optparse import OptionParser 1670 parser = OptionParser(usage="%prog [options]", 1671 version="%prog "+__version__) 1672 1673 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 1674 help='run the documentation tests') 1675 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 1676 help='run the unit tests') 1677 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 1678 help='Make the test output verbose') 1679 1680 # FIX: remove nmea from binary messages. No way to build the whole packet? 1681 # FIX: or build the surrounding msg 8 for a broadcast? 1682 typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message? 1683 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 1684 ,default='nmeapayload' 1685 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 1686 1687 1688 outputChoices = ('std','html','csv','sql' , 'kml','kml-full') 1689 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 1690 ,default='std' 1691 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 1692 1693 parser.add_option('-o','--output',dest='outputFileName',default=None, 1694 help='Name of the python file to write [default: stdout]') 1695 1696 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 1697 choices=fieldList, 1698 help='Which fields to include in the output. Currently only for csv output [default: all]') 1699 1700 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 1701 help='Print the field name for csv') 1702 1703 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 1704 help='Print out an sql create command for the table.') 1705 1706 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true', 1707 help='Print a LaTeX table of the type') 1708 1709 dbChoices = ('sqlite','postgres') 1710 parser.add_option('-D','--db-type',dest='dbType',default='postgres' 1711 ,choices=dbChoices,type='choice' 1712 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 1713 1714 addMsgOptions(parser) 1715 1716 (options,args) = parser.parse_args() 1717 success=True 1718 1719 if options.doctest: 1720 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 1721 sys.argv= [sys.argv[0]] 1722 if options.verbose: sys.argv.append('-v') 1723 import doctest 1724 numfail,numtests=doctest.testmod() 1725 if numfail==0: print 'ok' 1726 else: 1727 print 'FAILED' 1728 success=False 1729 1730 if not success: sys.exit('Something Failed') 1731 del success # Hide success from epydoc 1732 1733 if options.unittest: 1734 sys.argv = [sys.argv[0]] 1735 if options.verbose: sys.argv.append('-v') 1736 unittest.main() 1737 1738 outfile = sys.stdout 1739 if None!=options.outputFileName: 1740 outfile = file(options.outputFileName,'w') 1741 1742 1743 if options.doEncode: 1744 # First make sure all non required options are specified 1745 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField") 1746 if None==options.UserIDField: parser.error("missing value for UserIDField") 1747 if None==options.longitudeField: parser.error("missing value for longitudeField") 1748 if None==options.latitudeField: parser.error("missing value for latitudeField") 1749 if None==options.dayField: parser.error("missing value for dayField") 1750 if None==options.hourField: parser.error("missing value for hourField") 1751 if None==options.minField: parser.error("missing value for minField") 1752 if None==options.avewindField: parser.error("missing value for avewindField") 1753 if None==options.windgustField: parser.error("missing value for windgustField") 1754 if None==options.winddirField: parser.error("missing value for winddirField") 1755 if None==options.windgustdirField: parser.error("missing value for windgustdirField") 1756 if None==options.airtempField: parser.error("missing value for airtempField") 1757 if None==options.relhumidField: parser.error("missing value for relhumidField") 1758 if None==options.dewpointField: parser.error("missing value for dewpointField") 1759 if None==options.airpressureField: parser.error("missing value for airpressureField") 1760 if None==options.airpressuretrendField: parser.error("missing value for airpressuretrendField") 1761 if None==options.horizvisField: parser.error("missing value for horizvisField") 1762 if None==options.waterlevelField: parser.error("missing value for waterlevelField") 1763 if None==options.waterleveltrendField: parser.error("missing value for waterleveltrendField") 1764 if None==options.surfcurspeedField: parser.error("missing value for surfcurspeedField") 1765 if None==options.surfcurdirField: parser.error("missing value for surfcurdirField") 1766 if None==options.curspeed2Field: parser.error("missing value for curspeed2Field") 1767 if None==options.curdir2Field: parser.error("missing value for curdir2Field") 1768 if None==options.curlevel2Field: parser.error("missing value for curlevel2Field") 1769 if None==options.curspeed3Field: parser.error("missing value for curspeed3Field") 1770 if None==options.curdir3Field: parser.error("missing value for curdir3Field") 1771 if None==options.curlevel3Field: parser.error("missing value for curlevel3Field") 1772 if None==options.sigwaveheightField: parser.error("missing value for sigwaveheightField") 1773 if None==options.waveperiodField: parser.error("missing value for waveperiodField") 1774 if None==options.wavedirField: parser.error("missing value for wavedirField") 1775 if None==options.swellheightField: parser.error("missing value for swellheightField") 1776 if None==options.swellperiodField: parser.error("missing value for swellperiodField") 1777 if None==options.swelldirField: parser.error("missing value for swelldirField") 1778 if None==options.seastateField: parser.error("missing value for seastateField") 1779 if None==options.watertempField: parser.error("missing value for watertempField") 1780 if None==options.preciptypeField: parser.error("missing value for preciptypeField") 1781 if None==options.salinityField: parser.error("missing value for salinityField") 1782 if None==options.iceField: parser.error("missing value for iceField") 1783 msgDict={ 1784 'MessageID': '8', 1785 'RepeatIndicator': options.RepeatIndicatorField, 1786 'UserID': options.UserIDField, 1787 'Spare': '0', 1788 'dac': '1', 1789 'fid': '11', 1790 'longitude': options.longitudeField, 1791 'latitude': options.latitudeField, 1792 'day': options.dayField, 1793 'hour': options.hourField, 1794 'min': options.minField, 1795 'avewind': options.avewindField, 1796 'windgust': options.windgustField, 1797 'winddir': options.winddirField, 1798 'windgustdir': options.windgustdirField, 1799 'airtemp': options.airtempField, 1800 'relhumid': options.relhumidField, 1801 'dewpoint': options.dewpointField, 1802 'airpressure': options.airpressureField, 1803 'airpressuretrend': options.airpressuretrendField, 1804 'horizvis': options.horizvisField, 1805 'waterlevel': options.waterlevelField, 1806 'waterleveltrend': options.waterleveltrendField, 1807 'surfcurspeed': options.surfcurspeedField, 1808 'surfcurdir': options.surfcurdirField, 1809 'curspeed2': options.curspeed2Field, 1810 'curdir2': options.curdir2Field, 1811 'curlevel2': options.curlevel2Field, 1812 'curspeed3': options.curspeed3Field, 1813 'curdir3': options.curdir3Field, 1814 'curlevel3': options.curlevel3Field, 1815 'sigwaveheight': options.sigwaveheightField, 1816 'waveperiod': options.waveperiodField, 1817 'wavedir': options.wavedirField, 1818 'swellheight': options.swellheightField, 1819 'swellperiod': options.swellperiodField, 1820 'swelldir': options.swelldirField, 1821 'seastate': options.seastateField, 1822 'watertemp': options.watertempField, 1823 'preciptype': options.preciptypeField, 1824 'salinity': options.salinityField, 1825 'ice': options.iceField, 1826 'Spare': '0', 1827 } 1828 1829 bits = encode(msgDict) 1830 if 'binary'==options.ioType: print str(bits) 1831 elif 'nmeapayload'==options.ioType: 1832 # FIX: figure out if this might be necessary at compile time 1833 print "bitLen",len(bits) 1834 bitLen=len(bits) 1835 if bitLen%6!=0: 1836 bits = bits + BitVector(size=(6 - (bitLen%6))) # Pad out to multiple of 6 1837 print "result:",binary.bitvectoais6(bits)[0] 1838 1839 1840 # FIX: Do not emit this option for the binary message payloads. Does not make sense. 1841 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 1842 else: sys.exit('ERROR: unknown ioType. Help!') 1843 1844 1845 if options.sqlCreate: 1846 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 1847 1848 if options.latexDefinitionTable: 1849 latexDefinitionTable(outfile) 1850 1851 if options.printCsvfieldList: 1852 # Make a csv separated list of fields that will be displayed for csv 1853 if None == options.fieldList: options.fieldList = fieldList 1854 import StringIO 1855 buf = StringIO.StringIO() 1856 for field in options.fieldList: 1857 buf.write(field+',') 1858 result = buf.getvalue() 1859 if result[-1] == ',': print result[:-1] 1860 else: print result 1861 1862 if options.doDecode: 1863 for msg in args: 1864 bv = None 1865 1866 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 1867 # Found nmea 1868 # FIX: do checksum 1869 bv = binary.ais6tobitvec(msg.split(',')[5]) 1870 else: # either binary or nmeapayload... expect mostly nmeapayloads 1871 # assumes that an all 0 and 1 string can not be a nmeapayload 1872 binaryMsg=True 1873 for c in msg: 1874 if c not in ('0','1'): 1875 binaryMsg=False 1876 break 1877 if binaryMsg: 1878 bv = BitVector(bitstring=msg) 1879 else: # nmeapayload 1880 bv = binary.ais6tobitvec(msg) 1881 1882 printFields(decode(bv) 1883 ,out=outfile 1884 ,format=options.outputType 1885 ,fieldList=options.fieldList 1886 ,dbType=options.dbType 1887 ) 1888