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

Source Code for Module ais.imo_001_11

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