1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-11-07 $'.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
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 'latitude',
57 'longitude',
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',
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 'latitude':'Position',
142 'longitude':'Position',
143 }
144 '''
145 Go to the Postgis field names from the straight field name
146 '''
147
148 fromPgFields = {
149 'Position':('latitude','longitude',),
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): MMSI number of transmitter broadcasting the message
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 - latitude(decimal): Location of the vessel. North South location
173 - longitude(decimal): Location of the vessel. East West 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): Dry bulb temperature
182 - relhumid(uint): Relative humidity
183 - dewpoint(decimal): Dew Point
184 - airpressure(udecimal): Air pressure
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): Surface 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): Significant wave height
198 - waveperiod(uint): Wave period
199 - wavedir(uint): Wave direction
200 - swellheight(udecimal): Swell height
201 - swellperiod(uint): Swell period
202 - swelldir(uint): Swell direction
203 - seastate(uint): Sea state according to the Beaufort scale
204 - watertemp(udecimal): Water temperature
205 - preciptype(uint): According to WMO
206 - salinity(decimal): Salinity
207 - ice(uint): Yes or no for the presence of ice
208 - Spare(uint): Must be zero (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 'latitude' in params:
227 bvList.append(binary.bvFromSignedInt(int(Decimal(params['latitude'])*Decimal('60000')),24))
228 else:
229 bvList.append(binary.bvFromSignedInt(5460000,24))
230 if 'longitude' in params:
231 bvList.append(binary.bvFromSignedInt(int(Decimal(params['longitude'])*Decimal('60000')),25))
232 else:
233 bvList.append(binary.bvFromSignedInt(10860000,25))
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']-(800))*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']),6))
326 else:
327 bvList.append(binary.setBitVectorSize(BitVector(intVal=63),6))
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']),6))
338 else:
339 bvList.append(binary.setBitVectorSize(BitVector(intVal=63),6))
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.setBitVectorSize(BitVector(intVal=int((Decimal(params['watertemp']-(-10))*Decimal('10')))),10))
350 else:
351 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(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 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ice']),2))
361 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6))
362
363 return binary.joinBV(bvList)
364
365 -def decode(bv, validate=False):
366 '''Unpack a imo_met_hydro message
367
368 Fields in params:
369 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8")
370 - RepeatIndicator(uint): Indicated how many times a message has been repeated
371 - UserID(uint): MMSI number of transmitter broadcasting the message
372 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
373 - dac(uint): Designated Area Code - part 1 of the IAI (field automatically set to "1")
374 - fid(uint): Functional Identifier - part 2 of the IAI (field automatically set to "11")
375 - latitude(decimal): Location of the vessel. North South location
376 - longitude(decimal): Location of the vessel. East West location
377 - day(uint): Day 0..31
378 - hour(uint): Hour 0..23
379 - min(uint): Min
380 - avewind(uint): Average wind speed values for the last 10 minutes.
381 - windgust(uint): Wind gust is the max wind speed value reading during the last 10 minutes.
382 - winddir(uint): Wind direction
383 - windgustdir(uint): Wind direction for the gust.
384 - airtemp(decimal): Dry bulb temperature
385 - relhumid(uint): Relative humidity
386 - dewpoint(decimal): Dew Point
387 - airpressure(udecimal): Air pressure
388 - airpressuretrend(uint): Air pressure trend
389 - horizvis(udecimal): Horizontal visibility
390 - waterlevel(decimal): Water level (incl. tide)
391 - waterleveltrend(uint): Water level trend
392 - surfcurspeed(udecimal): Surface current speed
393 - surfcurdir(uint): Surface current direction
394 - curspeed2(udecimal): Level 2 current speed
395 - curdir2(uint): Level 2 current direction
396 - curlevel2(uint): Measuring level below sea surface for level 2
397 - curspeed3(udecimal): Level 3 current speed
398 - curdir3(uint): Level 3 current direction
399 - curlevel3(uint): Measuring level below sea surface for level 3
400 - sigwaveheight(udecimal): Significant wave height
401 - waveperiod(uint): Wave period
402 - wavedir(uint): Wave direction
403 - swellheight(udecimal): Swell height
404 - swellperiod(uint): Swell period
405 - swelldir(uint): Swell direction
406 - seastate(uint): Sea state according to the Beaufort scale
407 - watertemp(udecimal): Water temperature
408 - preciptype(uint): According to WMO
409 - salinity(decimal): Salinity
410 - ice(uint): Yes or no for the presence of ice
411 - Spare(uint): Must be zero (field automatically set to "0")
412 @type bv: BitVector
413 @param bv: Bits defining a message
414 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
415 @rtype: dict
416 @return: params
417 '''
418
419
420
421
422 r = {}
423 r['MessageID']=8
424 r['RepeatIndicator']=int(bv[6:8])
425 r['UserID']=int(bv[8:38])
426 r['Spare']=0
427 r['dac']=1
428 r['fid']=11
429 r['latitude']=Decimal(binary.signedIntFromBV(bv[56:80]))/Decimal('60000')
430 r['longitude']=Decimal(binary.signedIntFromBV(bv[80:105]))/Decimal('60000')
431 r['day']=int(bv[105:110])
432 r['hour']=int(bv[110:115])
433 r['min']=int(bv[115:121])
434 r['avewind']=int(bv[121:128])
435 r['windgust']=int(bv[128:135])
436 r['winddir']=int(bv[135:144])
437 r['windgustdir']=int(bv[144:153])
438 r['airtemp']=Decimal(binary.signedIntFromBV(bv[153:164]))/Decimal('10')
439 r['relhumid']=int(bv[164:171])
440 r['dewpoint']=Decimal(binary.signedIntFromBV(bv[171:181]))/Decimal('10')
441 r['airpressure']=Decimal(int(bv[181:190]))/Decimal('1')+Decimal('800')
442 r['airpressuretrend']=int(bv[190:192])
443 r['horizvis']=Decimal(int(bv[192:200]))/Decimal('10')
444 r['waterlevel']=Decimal(binary.signedIntFromBV(bv[200:209]))/Decimal('10')
445 r['waterleveltrend']=int(bv[209:211])
446 r['surfcurspeed']=Decimal(int(bv[211:219]))/Decimal('10')
447 r['surfcurdir']=int(bv[219:228])
448 r['curspeed2']=Decimal(int(bv[228:236]))/Decimal('10')
449 r['curdir2']=int(bv[236:245])
450 r['curlevel2']=int(bv[245:250])
451 r['curspeed3']=Decimal(int(bv[250:258]))/Decimal('10')
452 r['curdir3']=int(bv[258:267])
453 r['curlevel3']=int(bv[267:272])
454 r['sigwaveheight']=Decimal(int(bv[272:280]))/Decimal('10')
455 r['waveperiod']=int(bv[280:286])
456 r['wavedir']=int(bv[286:295])
457 r['swellheight']=Decimal(int(bv[295:303]))/Decimal('10')
458 r['swellperiod']=int(bv[303:309])
459 r['swelldir']=int(bv[309:318])
460 r['seastate']=int(bv[318:322])
461 r['watertemp']=Decimal(int(bv[322:332]))/Decimal('10')+Decimal('-10')
462 r['preciptype']=int(bv[332:335])
463 r['salinity']=Decimal(binary.signedIntFromBV(bv[335:344]))/Decimal('10')
464 r['ice']=int(bv[344:346])
465 r['Spare']=0
466 return r
467
470
473
476
479
482
485
488
491
493 return int(bv[105:110])
494
496 return int(bv[110:115])
497
499 return int(bv[115:121])
500
502 return int(bv[121:128])
503
505 return int(bv[128:135])
506
508 return int(bv[135:144])
509
511 return int(bv[144:153])
512
515
517 return int(bv[164:171])
518
521
523 return Decimal(int(bv[181:190]))/Decimal('1')+Decimal('800')
524
526 return int(bv[190:192])
527
529 return Decimal(int(bv[192:200]))/Decimal('10')
530
533
535 return int(bv[209:211])
536
538 return Decimal(int(bv[211:219]))/Decimal('10')
539
541 return int(bv[219:228])
542
544 return Decimal(int(bv[228:236]))/Decimal('10')
545
547 return int(bv[236:245])
548
550 return int(bv[245:250])
551
553 return Decimal(int(bv[250:258]))/Decimal('10')
554
556 return int(bv[258:267])
557
559 return int(bv[267:272])
560
562 return Decimal(int(bv[272:280]))/Decimal('10')
563
565 return int(bv[280:286])
566
568 return int(bv[286:295])
569
571 return Decimal(int(bv[295:303]))/Decimal('10')
572
574 return int(bv[303:309])
575
577 return int(bv[309:318])
578
580 return int(bv[318:322])
581
583 return Decimal(int(bv[322:332]))/Decimal('10')+Decimal('-10')
584
586 return int(bv[332:335])
587
590
592 return int(bv[344:346])
593
596
597
599 out.write("<h3>imo_met_hydro</h3>\n")
600 out.write("<table border=\"1\">\n")
601 out.write("<tr bgcolor=\"orange\">\n")
602 out.write("<th align=\"left\">Field Name</th>\n")
603 out.write("<th align=\"left\">Type</th>\n")
604 out.write("<th align=\"left\">Value</th>\n")
605 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
606 out.write("<th align=\"left\">Units</th>\n")
607 out.write("\n")
608 out.write("<tr>\n")
609 out.write("<td>MessageID</td>\n")
610 out.write("<td>uint</td>\n")
611 if 'MessageID' in params:
612 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
613 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
614 out.write("</tr>\n")
615 out.write("\n")
616 out.write("<tr>\n")
617 out.write("<td>RepeatIndicator</td>\n")
618 out.write("<td>uint</td>\n")
619 if 'RepeatIndicator' in params:
620 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n")
621 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut:
622 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>")
623 else:
624 out.write("<td><i>Missing LUT entry</i></td>")
625 out.write("</tr>\n")
626 out.write("\n")
627 out.write("<tr>\n")
628 out.write("<td>UserID</td>\n")
629 out.write("<td>uint</td>\n")
630 if 'UserID' in params:
631 out.write(" <td>"+str(params['UserID'])+"</td>\n")
632 out.write(" <td>"+str(params['UserID'])+"</td>\n")
633 out.write("</tr>\n")
634 out.write("\n")
635 out.write("<tr>\n")
636 out.write("<td>Spare</td>\n")
637 out.write("<td>uint</td>\n")
638 if 'Spare' in params:
639 out.write(" <td>"+str(params['Spare'])+"</td>\n")
640 out.write(" <td>"+str(params['Spare'])+"</td>\n")
641 out.write("</tr>\n")
642 out.write("\n")
643 out.write("<tr>\n")
644 out.write("<td>dac</td>\n")
645 out.write("<td>uint</td>\n")
646 if 'dac' in params:
647 out.write(" <td>"+str(params['dac'])+"</td>\n")
648 out.write(" <td>"+str(params['dac'])+"</td>\n")
649 out.write("</tr>\n")
650 out.write("\n")
651 out.write("<tr>\n")
652 out.write("<td>fid</td>\n")
653 out.write("<td>uint</td>\n")
654 if 'fid' in params:
655 out.write(" <td>"+str(params['fid'])+"</td>\n")
656 out.write(" <td>"+str(params['fid'])+"</td>\n")
657 out.write("</tr>\n")
658 out.write("\n")
659 out.write("<tr>\n")
660 out.write("<td>latitude</td>\n")
661 out.write("<td>decimal</td>\n")
662 if 'latitude' in params:
663 out.write(" <td>"+str(params['latitude'])+"</td>\n")
664 out.write(" <td>"+str(params['latitude'])+"</td>\n")
665 out.write("<td>degrees</td>\n")
666 out.write("</tr>\n")
667 out.write("\n")
668 out.write("<tr>\n")
669 out.write("<td>longitude</td>\n")
670 out.write("<td>decimal</td>\n")
671 if 'longitude' in params:
672 out.write(" <td>"+str(params['longitude'])+"</td>\n")
673 out.write(" <td>"+str(params['longitude'])+"</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>day</td>\n")
679 out.write("<td>uint</td>\n")
680 if 'day' in params:
681 out.write(" <td>"+str(params['day'])+"</td>\n")
682 out.write(" <td>"+str(params['day'])+"</td>\n")
683 out.write("<td>days</td>\n")
684 out.write("</tr>\n")
685 out.write("\n")
686 out.write("<tr>\n")
687 out.write("<td>hour</td>\n")
688 out.write("<td>uint</td>\n")
689 if 'hour' in params:
690 out.write(" <td>"+str(params['hour'])+"</td>\n")
691 out.write(" <td>"+str(params['hour'])+"</td>\n")
692 out.write("<td>hours</td>\n")
693 out.write("</tr>\n")
694 out.write("\n")
695 out.write("<tr>\n")
696 out.write("<td>min</td>\n")
697 out.write("<td>uint</td>\n")
698 if 'min' in params:
699 out.write(" <td>"+str(params['min'])+"</td>\n")
700 out.write(" <td>"+str(params['min'])+"</td>\n")
701 out.write("<td>minutes</td>\n")
702 out.write("</tr>\n")
703 out.write("\n")
704 out.write("<tr>\n")
705 out.write("<td>avewind</td>\n")
706 out.write("<td>uint</td>\n")
707 if 'avewind' in params:
708 out.write(" <td>"+str(params['avewind'])+"</td>\n")
709 out.write(" <td>"+str(params['avewind'])+"</td>\n")
710 out.write("<td>knots</td>\n")
711 out.write("</tr>\n")
712 out.write("\n")
713 out.write("<tr>\n")
714 out.write("<td>windgust</td>\n")
715 out.write("<td>uint</td>\n")
716 if 'windgust' in params:
717 out.write(" <td>"+str(params['windgust'])+"</td>\n")
718 out.write(" <td>"+str(params['windgust'])+"</td>\n")
719 out.write("<td>knots</td>\n")
720 out.write("</tr>\n")
721 out.write("\n")
722 out.write("<tr>\n")
723 out.write("<td>winddir</td>\n")
724 out.write("<td>uint</td>\n")
725 if 'winddir' in params:
726 out.write(" <td>"+str(params['winddir'])+"</td>\n")
727 out.write(" <td>"+str(params['winddir'])+"</td>\n")
728 out.write("<td>degrees</td>\n")
729 out.write("</tr>\n")
730 out.write("\n")
731 out.write("<tr>\n")
732 out.write("<td>windgustdir</td>\n")
733 out.write("<td>uint</td>\n")
734 if 'windgustdir' in params:
735 out.write(" <td>"+str(params['windgustdir'])+"</td>\n")
736 out.write(" <td>"+str(params['windgustdir'])+"</td>\n")
737 out.write("<td>degrees</td>\n")
738 out.write("</tr>\n")
739 out.write("\n")
740 out.write("<tr>\n")
741 out.write("<td>airtemp</td>\n")
742 out.write("<td>decimal</td>\n")
743 if 'airtemp' in params:
744 out.write(" <td>"+str(params['airtemp'])+"</td>\n")
745 out.write(" <td>"+str(params['airtemp'])+"</td>\n")
746 out.write("<td>degrees Celsius</td>\n")
747 out.write("</tr>\n")
748 out.write("\n")
749 out.write("<tr>\n")
750 out.write("<td>relhumid</td>\n")
751 out.write("<td>uint</td>\n")
752 if 'relhumid' in params:
753 out.write(" <td>"+str(params['relhumid'])+"</td>\n")
754 out.write(" <td>"+str(params['relhumid'])+"</td>\n")
755 out.write("<td>percent</td>\n")
756 out.write("</tr>\n")
757 out.write("\n")
758 out.write("<tr>\n")
759 out.write("<td>dewpoint</td>\n")
760 out.write("<td>decimal</td>\n")
761 if 'dewpoint' in params:
762 out.write(" <td>"+str(params['dewpoint'])+"</td>\n")
763 out.write(" <td>"+str(params['dewpoint'])+"</td>\n")
764 out.write("<td>degrees Celsius</td>\n")
765 out.write("</tr>\n")
766 out.write("\n")
767 out.write("<tr>\n")
768 out.write("<td>airpressure</td>\n")
769 out.write("<td>udecimal</td>\n")
770 if 'airpressure' in params:
771 out.write(" <td>"+str(params['airpressure'])+"</td>\n")
772 out.write(" <td>"+str(params['airpressure'])+"</td>\n")
773 out.write("<td>hPa</td>\n")
774 out.write("</tr>\n")
775 out.write("\n")
776 out.write("<tr>\n")
777 out.write("<td>airpressuretrend</td>\n")
778 out.write("<td>uint</td>\n")
779 if 'airpressuretrend' in params:
780 out.write(" <td>"+str(params['airpressuretrend'])+"</td>\n")
781 if str(params['airpressuretrend']) in airpressuretrendDecodeLut:
782 out.write("<td>"+airpressuretrendDecodeLut[str(params['airpressuretrend'])]+"</td>")
783 else:
784 out.write("<td><i>Missing LUT entry</i></td>")
785 out.write("</tr>\n")
786 out.write("\n")
787 out.write("<tr>\n")
788 out.write("<td>horizvis</td>\n")
789 out.write("<td>udecimal</td>\n")
790 if 'horizvis' in params:
791 out.write(" <td>"+str(params['horizvis'])+"</td>\n")
792 out.write(" <td>"+str(params['horizvis'])+"</td>\n")
793 out.write("<td>nm</td>\n")
794 out.write("</tr>\n")
795 out.write("\n")
796 out.write("<tr>\n")
797 out.write("<td>waterlevel</td>\n")
798 out.write("<td>decimal</td>\n")
799 if 'waterlevel' in params:
800 out.write(" <td>"+str(params['waterlevel'])+"</td>\n")
801 out.write(" <td>"+str(params['waterlevel'])+"</td>\n")
802 out.write("<td>m</td>\n")
803 out.write("</tr>\n")
804 out.write("\n")
805 out.write("<tr>\n")
806 out.write("<td>waterleveltrend</td>\n")
807 out.write("<td>uint</td>\n")
808 if 'waterleveltrend' in params:
809 out.write(" <td>"+str(params['waterleveltrend'])+"</td>\n")
810 if str(params['waterleveltrend']) in waterleveltrendDecodeLut:
811 out.write("<td>"+waterleveltrendDecodeLut[str(params['waterleveltrend'])]+"</td>")
812 else:
813 out.write("<td><i>Missing LUT entry</i></td>")
814 out.write("</tr>\n")
815 out.write("\n")
816 out.write("<tr>\n")
817 out.write("<td>surfcurspeed</td>\n")
818 out.write("<td>udecimal</td>\n")
819 if 'surfcurspeed' in params:
820 out.write(" <td>"+str(params['surfcurspeed'])+"</td>\n")
821 out.write(" <td>"+str(params['surfcurspeed'])+"</td>\n")
822 out.write("<td>knots</td>\n")
823 out.write("</tr>\n")
824 out.write("\n")
825 out.write("<tr>\n")
826 out.write("<td>surfcurdir</td>\n")
827 out.write("<td>uint</td>\n")
828 if 'surfcurdir' in params:
829 out.write(" <td>"+str(params['surfcurdir'])+"</td>\n")
830 out.write(" <td>"+str(params['surfcurdir'])+"</td>\n")
831 out.write("<td>degrees</td>\n")
832 out.write("</tr>\n")
833 out.write("\n")
834 out.write("<tr>\n")
835 out.write("<td>curspeed2</td>\n")
836 out.write("<td>udecimal</td>\n")
837 if 'curspeed2' in params:
838 out.write(" <td>"+str(params['curspeed2'])+"</td>\n")
839 out.write(" <td>"+str(params['curspeed2'])+"</td>\n")
840 out.write("<td>knots</td>\n")
841 out.write("</tr>\n")
842 out.write("\n")
843 out.write("<tr>\n")
844 out.write("<td>curdir2</td>\n")
845 out.write("<td>uint</td>\n")
846 if 'curdir2' in params:
847 out.write(" <td>"+str(params['curdir2'])+"</td>\n")
848 out.write(" <td>"+str(params['curdir2'])+"</td>\n")
849 out.write("<td>degrees</td>\n")
850 out.write("</tr>\n")
851 out.write("\n")
852 out.write("<tr>\n")
853 out.write("<td>curlevel2</td>\n")
854 out.write("<td>uint</td>\n")
855 if 'curlevel2' in params:
856 out.write(" <td>"+str(params['curlevel2'])+"</td>\n")
857 out.write(" <td>"+str(params['curlevel2'])+"</td>\n")
858 out.write("<td>m</td>\n")
859 out.write("</tr>\n")
860 out.write("\n")
861 out.write("<tr>\n")
862 out.write("<td>curspeed3</td>\n")
863 out.write("<td>udecimal</td>\n")
864 if 'curspeed3' in params:
865 out.write(" <td>"+str(params['curspeed3'])+"</td>\n")
866 out.write(" <td>"+str(params['curspeed3'])+"</td>\n")
867 out.write("<td>knots</td>\n")
868 out.write("</tr>\n")
869 out.write("\n")
870 out.write("<tr>\n")
871 out.write("<td>curdir3</td>\n")
872 out.write("<td>uint</td>\n")
873 if 'curdir3' in params:
874 out.write(" <td>"+str(params['curdir3'])+"</td>\n")
875 out.write(" <td>"+str(params['curdir3'])+"</td>\n")
876 out.write("<td>degrees</td>\n")
877 out.write("</tr>\n")
878 out.write("\n")
879 out.write("<tr>\n")
880 out.write("<td>curlevel3</td>\n")
881 out.write("<td>uint</td>\n")
882 if 'curlevel3' in params:
883 out.write(" <td>"+str(params['curlevel3'])+"</td>\n")
884 out.write(" <td>"+str(params['curlevel3'])+"</td>\n")
885 out.write("<td>m</td>\n")
886 out.write("</tr>\n")
887 out.write("\n")
888 out.write("<tr>\n")
889 out.write("<td>sigwaveheight</td>\n")
890 out.write("<td>udecimal</td>\n")
891 if 'sigwaveheight' in params:
892 out.write(" <td>"+str(params['sigwaveheight'])+"</td>\n")
893 out.write(" <td>"+str(params['sigwaveheight'])+"</td>\n")
894 out.write("<td>m</td>\n")
895 out.write("</tr>\n")
896 out.write("\n")
897 out.write("<tr>\n")
898 out.write("<td>waveperiod</td>\n")
899 out.write("<td>uint</td>\n")
900 if 'waveperiod' in params:
901 out.write(" <td>"+str(params['waveperiod'])+"</td>\n")
902 out.write(" <td>"+str(params['waveperiod'])+"</td>\n")
903 out.write("<td>sec</td>\n")
904 out.write("</tr>\n")
905 out.write("\n")
906 out.write("<tr>\n")
907 out.write("<td>wavedir</td>\n")
908 out.write("<td>uint</td>\n")
909 if 'wavedir' in params:
910 out.write(" <td>"+str(params['wavedir'])+"</td>\n")
911 out.write(" <td>"+str(params['wavedir'])+"</td>\n")
912 out.write("<td>degrees</td>\n")
913 out.write("</tr>\n")
914 out.write("\n")
915 out.write("<tr>\n")
916 out.write("<td>swellheight</td>\n")
917 out.write("<td>udecimal</td>\n")
918 if 'swellheight' in params:
919 out.write(" <td>"+str(params['swellheight'])+"</td>\n")
920 out.write(" <td>"+str(params['swellheight'])+"</td>\n")
921 out.write("<td>m</td>\n")
922 out.write("</tr>\n")
923 out.write("\n")
924 out.write("<tr>\n")
925 out.write("<td>swellperiod</td>\n")
926 out.write("<td>uint</td>\n")
927 if 'swellperiod' in params:
928 out.write(" <td>"+str(params['swellperiod'])+"</td>\n")
929 out.write(" <td>"+str(params['swellperiod'])+"</td>\n")
930 out.write("<td>sec</td>\n")
931 out.write("</tr>\n")
932 out.write("\n")
933 out.write("<tr>\n")
934 out.write("<td>swelldir</td>\n")
935 out.write("<td>uint</td>\n")
936 if 'swelldir' in params:
937 out.write(" <td>"+str(params['swelldir'])+"</td>\n")
938 out.write(" <td>"+str(params['swelldir'])+"</td>\n")
939 out.write("<td>degrees</td>\n")
940 out.write("</tr>\n")
941 out.write("\n")
942 out.write("<tr>\n")
943 out.write("<td>seastate</td>\n")
944 out.write("<td>uint</td>\n")
945 if 'seastate' in params:
946 out.write(" <td>"+str(params['seastate'])+"</td>\n")
947 if str(params['seastate']) in seastateDecodeLut:
948 out.write("<td>"+seastateDecodeLut[str(params['seastate'])]+"</td>")
949 else:
950 out.write("<td><i>Missing LUT entry</i></td>")
951 out.write("<td>Beaufort scale</td>\n")
952 out.write("</tr>\n")
953 out.write("\n")
954 out.write("<tr>\n")
955 out.write("<td>watertemp</td>\n")
956 out.write("<td>udecimal</td>\n")
957 if 'watertemp' in params:
958 out.write(" <td>"+str(params['watertemp'])+"</td>\n")
959 out.write(" <td>"+str(params['watertemp'])+"</td>\n")
960 out.write("<td>degrees Celsius</td>\n")
961 out.write("</tr>\n")
962 out.write("\n")
963 out.write("<tr>\n")
964 out.write("<td>preciptype</td>\n")
965 out.write("<td>uint</td>\n")
966 if 'preciptype' in params:
967 out.write(" <td>"+str(params['preciptype'])+"</td>\n")
968 if str(params['preciptype']) in preciptypeDecodeLut:
969 out.write("<td>"+preciptypeDecodeLut[str(params['preciptype'])]+"</td>")
970 else:
971 out.write("<td><i>Missing LUT entry</i></td>")
972 out.write("<td>WMO scale index</td>\n")
973 out.write("</tr>\n")
974 out.write("\n")
975 out.write("<tr>\n")
976 out.write("<td>salinity</td>\n")
977 out.write("<td>decimal</td>\n")
978 if 'salinity' in params:
979 out.write(" <td>"+str(params['salinity'])+"</td>\n")
980 out.write(" <td>"+str(params['salinity'])+"</td>\n")
981 out.write("<td>0/00</td>\n")
982 out.write("</tr>\n")
983 out.write("\n")
984 out.write("<tr>\n")
985 out.write("<td>ice</td>\n")
986 out.write("<td>uint</td>\n")
987 if 'ice' in params:
988 out.write(" <td>"+str(params['ice'])+"</td>\n")
989 if str(params['ice']) in iceDecodeLut:
990 out.write("<td>"+iceDecodeLut[str(params['ice'])]+"</td>")
991 else:
992 out.write("<td><i>Missing LUT entry</i></td>")
993 out.write("</tr>\n")
994 out.write("\n")
995 out.write("<tr>\n")
996 out.write("<td>Spare</td>\n")
997 out.write("<td>uint</td>\n")
998 if 'Spare' in params:
999 out.write(" <td>"+str(params['Spare'])+"</td>\n")
1000 out.write(" <td>"+str(params['Spare'])+"</td>\n")
1001 out.write("</tr>\n")
1002 out.write("</table>\n")
1003
1004
1006 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
1007 out.write("\ <Placemark>\n")
1008 out.write("\t <name>"+str(params['UserID'])+"</name>\n")
1009 out.write("\t\t<description>\n")
1010 import StringIO
1011 buf = StringIO.StringIO()
1012 printHtml(params,buf)
1013 import cgi
1014 out.write(cgi.escape(buf.getvalue()))
1015 out.write("\t\t</description>\n")
1016 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
1017 out.write("\t\t<Point>\n")
1018 out.write("\t\t\t<coordinates>")
1019 out.write(str(params['longitude']))
1020 out.write(',')
1021 out.write(str(params['latitude']))
1022 out.write(",0</coordinates>\n")
1023 out.write("\t\t</Point>\n")
1024 out.write("\t</Placemark>\n")
1025
1026 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
1027 '''Print a imo_met_hydro message to stdout.
1028
1029 Fields in params:
1030 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8")
1031 - RepeatIndicator(uint): Indicated how many times a message has been repeated
1032 - UserID(uint): MMSI number of transmitter broadcasting the message
1033 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
1034 - dac(uint): Designated Area Code - part 1 of the IAI (field automatically set to "1")
1035 - fid(uint): Functional Identifier - part 2 of the IAI (field automatically set to "11")
1036 - latitude(decimal): Location of the vessel. North South location
1037 - longitude(decimal): Location of the vessel. East West location
1038 - day(uint): Day 0..31
1039 - hour(uint): Hour 0..23
1040 - min(uint): Min
1041 - avewind(uint): Average wind speed values for the last 10 minutes.
1042 - windgust(uint): Wind gust is the max wind speed value reading during the last 10 minutes.
1043 - winddir(uint): Wind direction
1044 - windgustdir(uint): Wind direction for the gust.
1045 - airtemp(decimal): Dry bulb temperature
1046 - relhumid(uint): Relative humidity
1047 - dewpoint(decimal): Dew Point
1048 - airpressure(udecimal): Air pressure
1049 - airpressuretrend(uint): Air pressure trend
1050 - horizvis(udecimal): Horizontal visibility
1051 - waterlevel(decimal): Water level (incl. tide)
1052 - waterleveltrend(uint): Water level trend
1053 - surfcurspeed(udecimal): Surface current speed
1054 - surfcurdir(uint): Surface current direction
1055 - curspeed2(udecimal): Level 2 current speed
1056 - curdir2(uint): Level 2 current direction
1057 - curlevel2(uint): Measuring level below sea surface for level 2
1058 - curspeed3(udecimal): Level 3 current speed
1059 - curdir3(uint): Level 3 current direction
1060 - curlevel3(uint): Measuring level below sea surface for level 3
1061 - sigwaveheight(udecimal): Significant wave height
1062 - waveperiod(uint): Wave period
1063 - wavedir(uint): Wave direction
1064 - swellheight(udecimal): Swell height
1065 - swellperiod(uint): Swell period
1066 - swelldir(uint): Swell direction
1067 - seastate(uint): Sea state according to the Beaufort scale
1068 - watertemp(udecimal): Water temperature
1069 - preciptype(uint): According to WMO
1070 - salinity(decimal): Salinity
1071 - ice(uint): Yes or no for the presence of ice
1072 - Spare(uint): Must be zero (field automatically set to "0")
1073 @param params: Dictionary of field names/values.
1074 @param out: File like object to write to
1075 @rtype: stdout
1076 @return: text to out
1077 '''
1078
1079 if 'std'==format:
1080 out.write("imo_met_hydro:\n")
1081 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n")
1082 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n")
1083 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n")
1084 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
1085 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n")
1086 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n")
1087 if 'latitude' in params: out.write(" latitude: "+str(params['latitude'])+"\n")
1088 if 'longitude' in params: out.write(" longitude: "+str(params['longitude'])+"\n")
1089 if 'day' in params: out.write(" day: "+str(params['day'])+"\n")
1090 if 'hour' in params: out.write(" hour: "+str(params['hour'])+"\n")
1091 if 'min' in params: out.write(" min: "+str(params['min'])+"\n")
1092 if 'avewind' in params: out.write(" avewind: "+str(params['avewind'])+"\n")
1093 if 'windgust' in params: out.write(" windgust: "+str(params['windgust'])+"\n")
1094 if 'winddir' in params: out.write(" winddir: "+str(params['winddir'])+"\n")
1095 if 'windgustdir' in params: out.write(" windgustdir: "+str(params['windgustdir'])+"\n")
1096 if 'airtemp' in params: out.write(" airtemp: "+str(params['airtemp'])+"\n")
1097 if 'relhumid' in params: out.write(" relhumid: "+str(params['relhumid'])+"\n")
1098 if 'dewpoint' in params: out.write(" dewpoint: "+str(params['dewpoint'])+"\n")
1099 if 'airpressure' in params: out.write(" airpressure: "+str(params['airpressure'])+"\n")
1100 if 'airpressuretrend' in params: out.write(" airpressuretrend: "+str(params['airpressuretrend'])+"\n")
1101 if 'horizvis' in params: out.write(" horizvis: "+str(params['horizvis'])+"\n")
1102 if 'waterlevel' in params: out.write(" waterlevel: "+str(params['waterlevel'])+"\n")
1103 if 'waterleveltrend' in params: out.write(" waterleveltrend: "+str(params['waterleveltrend'])+"\n")
1104 if 'surfcurspeed' in params: out.write(" surfcurspeed: "+str(params['surfcurspeed'])+"\n")
1105 if 'surfcurdir' in params: out.write(" surfcurdir: "+str(params['surfcurdir'])+"\n")
1106 if 'curspeed2' in params: out.write(" curspeed2: "+str(params['curspeed2'])+"\n")
1107 if 'curdir2' in params: out.write(" curdir2: "+str(params['curdir2'])+"\n")
1108 if 'curlevel2' in params: out.write(" curlevel2: "+str(params['curlevel2'])+"\n")
1109 if 'curspeed3' in params: out.write(" curspeed3: "+str(params['curspeed3'])+"\n")
1110 if 'curdir3' in params: out.write(" curdir3: "+str(params['curdir3'])+"\n")
1111 if 'curlevel3' in params: out.write(" curlevel3: "+str(params['curlevel3'])+"\n")
1112 if 'sigwaveheight' in params: out.write(" sigwaveheight: "+str(params['sigwaveheight'])+"\n")
1113 if 'waveperiod' in params: out.write(" waveperiod: "+str(params['waveperiod'])+"\n")
1114 if 'wavedir' in params: out.write(" wavedir: "+str(params['wavedir'])+"\n")
1115 if 'swellheight' in params: out.write(" swellheight: "+str(params['swellheight'])+"\n")
1116 if 'swellperiod' in params: out.write(" swellperiod: "+str(params['swellperiod'])+"\n")
1117 if 'swelldir' in params: out.write(" swelldir: "+str(params['swelldir'])+"\n")
1118 if 'seastate' in params: out.write(" seastate: "+str(params['seastate'])+"\n")
1119 if 'watertemp' in params: out.write(" watertemp: "+str(params['watertemp'])+"\n")
1120 if 'preciptype' in params: out.write(" preciptype: "+str(params['preciptype'])+"\n")
1121 if 'salinity' in params: out.write(" salinity: "+str(params['salinity'])+"\n")
1122 if 'ice' in params: out.write(" ice: "+str(params['ice'])+"\n")
1123 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
1124 elif 'csv'==format:
1125 if None == options.fieldList:
1126 options.fieldList = fieldList
1127 needComma = False;
1128 for field in fieldList:
1129 if needComma: out.write(',')
1130 needComma = True
1131 if field in params:
1132 out.write(str(params[field]))
1133
1134 out.write("\n")
1135 elif 'html'==format:
1136 printHtml(params,out)
1137 elif 'sql'==format:
1138 sqlInsertStr(params,out,dbType=dbType)
1139 elif 'kml'==format:
1140 printKml(params,out)
1141 elif 'kml-full'==format:
1142 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
1143 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
1144 out.write("<Document>\n")
1145 out.write(" <name>imo_met_hydro</name>\n")
1146 printKml(params,out)
1147 out.write("</Document>\n")
1148 out.write("</kml>\n")
1149 else:
1150 print "ERROR: unknown format:",format
1151 assert False
1152
1153 return
1154
1155 RepeatIndicatorEncodeLut = {
1156 'default':'0',
1157 'do not repeat any more':'3',
1158 }
1159
1160 RepeatIndicatorDecodeLut = {
1161 '0':'default',
1162 '3':'do not repeat any more',
1163 }
1164
1165 airpressuretrendEncodeLut = {
1166 'steady':'0',
1167 'decreasing':'1',
1168 'increasing':'2',
1169 'unavailable':'3',
1170 }
1171
1172 airpressuretrendDecodeLut = {
1173 '0':'steady',
1174 '1':'decreasing',
1175 '2':'increasing',
1176 '3':'unavailable',
1177 }
1178
1179 waterleveltrendEncodeLut = {
1180 'steady':'0',
1181 'decreasing':'1',
1182 'increasing':'2',
1183 'unavailable':'3',
1184 }
1185
1186 waterleveltrendDecodeLut = {
1187 '0':'steady',
1188 '1':'decreasing',
1189 '2':'increasing',
1190 '3':'unavailable',
1191 }
1192
1193 seastateEncodeLut = {
1194 'Calm':'0',
1195 'Light air':'1',
1196 'Light breeze':'2',
1197 'Gentle breeze':'3',
1198 'Moderate breeze':'4',
1199 'Fresh breeze':'5',
1200 'Strong breeze':'6',
1201 'Near gale':'7',
1202 'Gale':'8',
1203 'Strong gale':'9',
1204 'Storm':'10',
1205 'Violent storm':'11',
1206 'Hurricane':'12',
1207 'unavailable':'15',
1208 }
1209
1210 seastateDecodeLut = {
1211 '0':'Calm',
1212 '1':'Light air',
1213 '2':'Light breeze',
1214 '3':'Gentle breeze',
1215 '4':'Moderate breeze',
1216 '5':'Fresh breeze',
1217 '6':'Strong breeze',
1218 '7':'Near gale',
1219 '8':'Gale',
1220 '9':'Strong gale',
1221 '10':'Storm',
1222 '11':'Violent storm',
1223 '12':'Hurricane',
1224 '15':'unavailable',
1225 }
1226
1227 preciptypeEncodeLut = {
1228 'FIX: find the WMO list of types':'0',
1229 'unavailable':'7',
1230 }
1231
1232 preciptypeDecodeLut = {
1233 '0':'FIX: find the WMO list of types',
1234 '7':'unavailable',
1235 }
1236
1237 iceEncodeLut = {
1238 'Not sure. Maybe no ice?':'0',
1239 'Not sure. Maybe yes ice?':'1',
1240 'Not sure. Maybe not allowed?':'2',
1241 'Unknown?':'3',
1242 }
1243
1244 iceDecodeLut = {
1245 '0':'Not sure. Maybe no ice?',
1246 '1':'Not sure. Maybe yes ice?',
1247 '2':'Not sure. Maybe not allowed?',
1248 '3':'Unknown?',
1249 }
1250
1251
1252
1253
1254
1255 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
1256 ,addCoastGuardFields=True
1257 ,dbType='postgres'
1258 ):
1259 '''
1260 Return the SQL CREATE command for this message type
1261 @param outfile: file like object to print to.
1262 @param fields: which fields to put in the create. Defaults to all.
1263 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
1264 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
1265 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
1266 @type addCoastGuardFields: bool
1267 @return: sql create string
1268 @rtype: str
1269
1270 @see: sqlCreate
1271 '''
1272
1273 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
1274
1275 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
1276 '''
1277 Return the sqlhelp object to create the table.
1278
1279 @param fields: which fields to put in the create. Defaults to all.
1280 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
1281 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
1282 @type addCoastGuardFields: bool
1283 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
1284 @return: An object that can be used to generate a return
1285 @rtype: sqlhelp.create
1286 '''
1287 if None == fields: fields = fieldList
1288 import sqlhelp
1289 c = sqlhelp.create('imo_met_hydro',dbType=dbType)
1290 c.addPrimaryKey()
1291 if 'MessageID' in fields: c.addInt ('MessageID')
1292 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator')
1293 if 'UserID' in fields: c.addInt ('UserID')
1294 if 'Spare' in fields: c.addInt ('Spare')
1295 if 'dac' in fields: c.addInt ('dac')
1296 if 'fid' in fields: c.addInt ('fid')
1297 if dbType != 'postgres':
1298 if 'latitude' in fields: c.addDecimal('latitude',7,4)
1299 if dbType != 'postgres':
1300 if 'longitude' in fields: c.addDecimal('longitude',7,4)
1301 if 'day' in fields: c.addInt ('day')
1302 if 'hour' in fields: c.addInt ('hour')
1303 if 'min' in fields: c.addInt ('min')
1304 if 'avewind' in fields: c.addInt ('avewind')
1305 if 'windgust' in fields: c.addInt ('windgust')
1306 if 'winddir' in fields: c.addInt ('winddir')
1307 if 'windgustdir' in fields: c.addInt ('windgustdir')
1308 if 'airtemp' in fields: c.addDecimal('airtemp',4,1)
1309 if 'relhumid' in fields: c.addInt ('relhumid')
1310 if 'dewpoint' in fields: c.addDecimal('dewpoint',4,1)
1311 if 'airpressure' in fields: c.addDecimal('airpressure',3,0)
1312 if 'airpressuretrend' in fields: c.addInt ('airpressuretrend')
1313 if 'horizvis' in fields: c.addDecimal('horizvis',3,1)
1314 if 'waterlevel' in fields: c.addDecimal('waterlevel',3,1)
1315 if 'waterleveltrend' in fields: c.addInt ('waterleveltrend')
1316 if 'surfcurspeed' in fields: c.addDecimal('surfcurspeed',3,1)
1317 if 'surfcurdir' in fields: c.addInt ('surfcurdir')
1318 if 'curspeed2' in fields: c.addDecimal('curspeed2',3,1)
1319 if 'curdir2' in fields: c.addInt ('curdir2')
1320 if 'curlevel2' in fields: c.addInt ('curlevel2')
1321 if 'curspeed3' in fields: c.addDecimal('curspeed3',3,1)
1322 if 'curdir3' in fields: c.addInt ('curdir3')
1323 if 'curlevel3' in fields: c.addInt ('curlevel3')
1324 if 'sigwaveheight' in fields: c.addDecimal('sigwaveheight',3,1)
1325 if 'waveperiod' in fields: c.addInt ('waveperiod')
1326 if 'wavedir' in fields: c.addInt ('wavedir')
1327 if 'swellheight' in fields: c.addDecimal('swellheight',3,1)
1328 if 'swellperiod' in fields: c.addInt ('swellperiod')
1329 if 'swelldir' in fields: c.addInt ('swelldir')
1330 if 'seastate' in fields: c.addInt ('seastate')
1331 if 'watertemp' in fields: c.addDecimal('watertemp',4,1)
1332 if 'preciptype' in fields: c.addInt ('preciptype')
1333 if 'salinity' in fields: c.addDecimal('salinity',3,1)
1334 if 'ice' in fields: c.addInt ('ice')
1335 if 'Spare' in fields: c.addInt ('Spare')
1336
1337 if addCoastGuardFields:
1338
1339
1340
1341
1342
1343 c.addVarChar('cg_r',15)
1344 c.addInt('cg_sec')
1345
1346 c.addTimestamp('cg_timestamp')
1347
1348 if dbType == 'postgres':
1349
1350
1351 c.addPostGIS('Position','POINT',2,SRID=4326);
1352
1353 return c
1354
1355 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
1356 '''
1357 Return the SQL INSERT command for this message type
1358 @param params: dictionary of values keyed by field name
1359 @param outfile: file like object to print to.
1360 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
1361 @return: sql create string
1362 @rtype: str
1363
1364 @see: sqlCreate
1365 '''
1366 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
1367
1368
1369 -def sqlInsert(params,extraParams=None,dbType='postgres'):
1370 '''
1371 Give the SQL INSERT statement
1372 @param params: dict keyed by field name of values
1373 @param extraParams: any extra fields that you have created beyond the normal ais message fields
1374 @rtype: sqlhelp.insert
1375 @return: insert class instance
1376 @todo: allow optional type checking of params?
1377 @warning: this will take invalid keys happily and do what???
1378 '''
1379 import sqlhelp
1380 i = sqlhelp.insert('imo_met_hydro',dbType=dbType)
1381
1382 if dbType=='postgres':
1383 finished = []
1384 for key in params:
1385 if key in finished:
1386 continue
1387
1388 if key not in toPgFields and key not in fromPgFields:
1389 if type(params[key])==Decimal: i.add(key,float(params[key]))
1390 else: i.add(key,params[key])
1391 else:
1392 if key in fromPgFields:
1393 val = params[key]
1394
1395 i.addPostGIS(key,val)
1396 finished.append(key)
1397 else:
1398
1399 pgName = toPgFields[key]
1400
1401 valStr=pgTypes[pgName]+'('
1402 vals = []
1403 for nonPgKey in fromPgFields[pgName]:
1404 vals.append(str(params[nonPgKey]))
1405 finished.append(nonPgKey)
1406 valStr+=' '.join(vals)+')'
1407 i.addPostGIS(pgName,valStr)
1408 else:
1409 for key in params:
1410 if type(params[key])==Decimal: i.add(key,float(params[key]))
1411 else: i.add(key,params[key])
1412
1413 if None != extraParams:
1414 for key in extraParams:
1415 i.add(key,extraParams[key])
1416
1417 return i
1418
1419
1420
1421
1422
1425 '''
1426 Return the LaTeX definition table for this message type
1427 @param outfile: file like object to print to.
1428 @type outfile: file obj
1429 @return: LaTeX table string via the outfile
1430 @rtype: str
1431
1432 '''
1433 o = outfile
1434
1435 o.write('''
1436 \\begin{table}%[htb]
1437 \\centering
1438 \\begin{tabular}{|l|c|l|}
1439 \\hline
1440 Parameter & Number of bits & Description
1441 \\\\ \\hline\\hline
1442 MessageID & 6 & AIS message number. Must be 8 \\\\ \hline
1443 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline
1444 UserID & 30 & MMSI number of transmitter broadcasting the message \\\\ \hline
1445 Spare & 2 & Reserved for definition by a regional authority. \\\\ \hline
1446 dac & 10 & Designated Area Code - part 1 of the IAI \\\\ \hline
1447 fid & 6 & Functional Identifier - part 2 of the IAI \\\\ \hline
1448 latitude & 24 & Location of the vessel. North South location \\\\ \hline
1449 longitude & 25 & Location of the vessel. East West location \\\\ \hline
1450 day & 5 & Day 0..31 \\\\ \hline
1451 hour & 5 & Hour 0..23 \\\\ \hline
1452 min & 6 & Min \\\\ \hline
1453 avewind & 7 & Average wind speed values for the last 10 minutes. \\\\ \hline
1454 windgust & 7 & Wind gust is the max wind speed value reading during the last 10 minutes. \\\\ \hline
1455 winddir & 9 & Wind direction \\\\ \hline
1456 windgustdir & 9 & Wind direction for the gust. \\\\ \hline
1457 airtemp & 11 & Dry bulb temperature \\\\ \hline
1458 relhumid & 7 & Relative humidity \\\\ \hline
1459 dewpoint & 10 & Dew Point \\\\ \hline
1460 airpressure & 9 & Air pressure \\\\ \hline
1461 airpressuretrend & 2 & Air pressure trend \\\\ \hline
1462 horizvis & 8 & Horizontal visibility \\\\ \hline
1463 waterlevel & 9 & Water level (incl. tide) \\\\ \hline
1464 waterleveltrend & 2 & Water level trend \\\\ \hline
1465 surfcurspeed & 8 & Surface current speed \\\\ \hline
1466 surfcurdir & 9 & Surface current direction \\\\ \hline
1467 curspeed2 & 8 & Level 2 current speed \\\\ \hline
1468 curdir2 & 9 & Level 2 current direction \\\\ \hline
1469 curlevel2 & 5 & Measuring level below sea surface for level 2 \\\\ \hline
1470 curspeed3 & 8 & Level 3 current speed \\\\ \hline
1471 curdir3 & 9 & Level 3 current direction \\\\ \hline
1472 curlevel3 & 5 & Measuring level below sea surface for level 3 \\\\ \hline
1473 sigwaveheight & 8 & Significant wave height \\\\ \hline
1474 waveperiod & 6 & Wave period \\\\ \hline
1475 wavedir & 9 & Wave direction \\\\ \hline
1476 swellheight & 8 & Swell height \\\\ \hline
1477 swellperiod & 6 & Swell period \\\\ \hline
1478 swelldir & 9 & Swell direction \\\\ \hline
1479 seastate & 4 & Sea state according to the Beaufort scale \\\\ \hline
1480 watertemp & 10 & Water temperature \\\\ \hline
1481 preciptype & 3 & According to WMO \\\\ \hline
1482 salinity & 9 & Salinity \\\\ \hline
1483 ice & 2 & Yes or no for the presence of ice \\\\ \hline
1484 Spare & 6 & Must be zero\\\\ \\hline \\hline
1485 Total bits & 352 & Appears to take 2 slots with 72 pad bits to fill the last slot \\\\ \\hline
1486 \\end{tabular}
1487 \\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. }
1488 \\label{tab:imo_met_hydro}
1489 \\end{table}
1490 ''')
1491
1492
1493
1494
1495
1496 -def textDefinitionTable(outfile=sys.stdout
1497 ,delim='\t'
1498 ):
1499 '''
1500 Return the text definition table for this message type
1501 @param outfile: file like object to print to.
1502 @type outfile: file obj
1503 @return: text table string via the outfile
1504 @rtype: str
1505
1506 '''
1507 o = outfile
1508 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description
1509 MessageID'''+delim+'''6'''+delim+'''AIS message number. Must be 8
1510 RepeatIndicator'''+delim+'''2'''+delim+'''Indicated how many times a message has been repeated
1511 UserID'''+delim+'''30'''+delim+'''MMSI number of transmitter broadcasting the message
1512 Spare'''+delim+'''2'''+delim+'''Reserved for definition by a regional authority.
1513 dac'''+delim+'''10'''+delim+'''Designated Area Code - part 1 of the IAI
1514 fid'''+delim+'''6'''+delim+'''Functional Identifier - part 2 of the IAI
1515 latitude'''+delim+'''24'''+delim+'''Location of the vessel. North South location
1516 longitude'''+delim+'''25'''+delim+'''Location of the vessel. East West location
1517 day'''+delim+'''5'''+delim+'''Day 0..31
1518 hour'''+delim+'''5'''+delim+'''Hour 0..23
1519 min'''+delim+'''6'''+delim+'''Min
1520 avewind'''+delim+'''7'''+delim+'''Average wind speed values for the last 10 minutes.
1521 windgust'''+delim+'''7'''+delim+'''Wind gust is the max wind speed value reading during the last 10 minutes.
1522 winddir'''+delim+'''9'''+delim+'''Wind direction
1523 windgustdir'''+delim+'''9'''+delim+'''Wind direction for the gust.
1524 airtemp'''+delim+'''11'''+delim+'''Dry bulb temperature
1525 relhumid'''+delim+'''7'''+delim+'''Relative humidity
1526 dewpoint'''+delim+'''10'''+delim+'''Dew Point
1527 airpressure'''+delim+'''9'''+delim+'''Air pressure
1528 airpressuretrend'''+delim+'''2'''+delim+'''Air pressure trend
1529 horizvis'''+delim+'''8'''+delim+'''Horizontal visibility
1530 waterlevel'''+delim+'''9'''+delim+'''Water level (incl. tide)
1531 waterleveltrend'''+delim+'''2'''+delim+'''Water level trend
1532 surfcurspeed'''+delim+'''8'''+delim+'''Surface current speed
1533 surfcurdir'''+delim+'''9'''+delim+'''Surface current direction
1534 curspeed2'''+delim+'''8'''+delim+'''Level 2 current speed
1535 curdir2'''+delim+'''9'''+delim+'''Level 2 current direction
1536 curlevel2'''+delim+'''5'''+delim+'''Measuring level below sea surface for level 2
1537 curspeed3'''+delim+'''8'''+delim+'''Level 3 current speed
1538 curdir3'''+delim+'''9'''+delim+'''Level 3 current direction
1539 curlevel3'''+delim+'''5'''+delim+'''Measuring level below sea surface for level 3
1540 sigwaveheight'''+delim+'''8'''+delim+'''Significant wave height
1541 waveperiod'''+delim+'''6'''+delim+'''Wave period
1542 wavedir'''+delim+'''9'''+delim+'''Wave direction
1543 swellheight'''+delim+'''8'''+delim+'''Swell height
1544 swellperiod'''+delim+'''6'''+delim+'''Swell period
1545 swelldir'''+delim+'''9'''+delim+'''Swell direction
1546 seastate'''+delim+'''4'''+delim+'''Sea state according to the Beaufort scale
1547 watertemp'''+delim+'''10'''+delim+'''Water temperature
1548 preciptype'''+delim+'''3'''+delim+'''According to WMO
1549 salinity'''+delim+'''9'''+delim+'''Salinity
1550 ice'''+delim+'''2'''+delim+'''Yes or no for the presence of ice
1551 Spare'''+delim+'''6'''+delim+'''Must be zero
1552 Total bits'''+delim+'''352'''+delim+'''Appears to take 2 slots with 72 pad bits to fill the last slot''')
1553
1554
1555
1556
1557
1558 import unittest
1560 '''Return a params file base on the testvalue tags.
1561 @rtype: dict
1562 @return: params based on testvalue tags
1563 '''
1564 params = {}
1565 params['MessageID'] = 8
1566 params['RepeatIndicator'] = 1
1567 params['UserID'] = 1193046
1568 params['Spare'] = 0
1569 params['dac'] = 1
1570 params['fid'] = 11
1571 params['latitude'] = Decimal('37.42446')
1572 params['longitude'] = Decimal('-122.16328')
1573 params['day'] = 3
1574 params['hour'] = 21
1575 params['min'] = 58
1576 params['avewind'] = 23
1577 params['windgust'] = 35
1578 params['winddir'] = 329
1579 params['windgustdir'] = 293
1580 params['airtemp'] = Decimal('-40.1')
1581 params['relhumid'] = 99
1582 params['dewpoint'] = Decimal('-19.2')
1583 params['airpressure'] = Decimal('1150')
1584 params['airpressuretrend'] = 2
1585 params['horizvis'] = Decimal('11.9')
1586 params['waterlevel'] = Decimal('-8.9')
1587 params['waterleveltrend'] = 0
1588 params['surfcurspeed'] = Decimal('22.3')
1589 params['surfcurdir'] = 321
1590 params['curspeed2'] = Decimal('12.7')
1591 params['curdir2'] = 122
1592 params['curlevel2'] = 29
1593 params['curspeed3'] = Decimal('19.2')
1594 params['curdir3'] = 93
1595 params['curlevel3'] = 28
1596 params['sigwaveheight'] = Decimal('22.8')
1597 params['waveperiod'] = 2
1598 params['wavedir'] = 187
1599 params['swellheight'] = Decimal('0.2')
1600 params['swellperiod'] = 59
1601 params['swelldir'] = 1
1602 params['seastate'] = 12
1603 params['watertemp'] = Decimal('48.8')
1604 params['preciptype'] = 2
1605 params['salinity'] = Decimal('0.9')
1606 params['ice'] = 1
1607 params['Spare'] = 0
1608
1609 return params
1610
1612 '''Use testvalue tag text from each type to build test case the imo_met_hydro message'''
1614
1615 params = testParams()
1616 bits = encode(params)
1617 r = decode(bits)
1618
1619
1620 self.failUnlessEqual(r['MessageID'],params['MessageID'])
1621 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
1622 self.failUnlessEqual(r['UserID'],params['UserID'])
1623 self.failUnlessEqual(r['Spare'],params['Spare'])
1624 self.failUnlessEqual(r['dac'],params['dac'])
1625 self.failUnlessEqual(r['fid'],params['fid'])
1626 self.failUnlessAlmostEqual(r['latitude'],params['latitude'],4)
1627 self.failUnlessAlmostEqual(r['longitude'],params['longitude'],4)
1628 self.failUnlessEqual(r['day'],params['day'])
1629 self.failUnlessEqual(r['hour'],params['hour'])
1630 self.failUnlessEqual(r['min'],params['min'])
1631 self.failUnlessEqual(r['avewind'],params['avewind'])
1632 self.failUnlessEqual(r['windgust'],params['windgust'])
1633 self.failUnlessEqual(r['winddir'],params['winddir'])
1634 self.failUnlessEqual(r['windgustdir'],params['windgustdir'])
1635 self.failUnlessAlmostEqual(r['airtemp'],params['airtemp'],1)
1636 self.failUnlessEqual(r['relhumid'],params['relhumid'])
1637 self.failUnlessAlmostEqual(r['dewpoint'],params['dewpoint'],1)
1638 self.failUnlessAlmostEqual(r['airpressure'],params['airpressure'],0)
1639 self.failUnlessEqual(r['airpressuretrend'],params['airpressuretrend'])
1640 self.failUnlessAlmostEqual(r['horizvis'],params['horizvis'],1)
1641 self.failUnlessAlmostEqual(r['waterlevel'],params['waterlevel'],1)
1642 self.failUnlessEqual(r['waterleveltrend'],params['waterleveltrend'])
1643 self.failUnlessAlmostEqual(r['surfcurspeed'],params['surfcurspeed'],1)
1644 self.failUnlessEqual(r['surfcurdir'],params['surfcurdir'])
1645 self.failUnlessAlmostEqual(r['curspeed2'],params['curspeed2'],1)
1646 self.failUnlessEqual(r['curdir2'],params['curdir2'])
1647 self.failUnlessEqual(r['curlevel2'],params['curlevel2'])
1648 self.failUnlessAlmostEqual(r['curspeed3'],params['curspeed3'],1)
1649 self.failUnlessEqual(r['curdir3'],params['curdir3'])
1650 self.failUnlessEqual(r['curlevel3'],params['curlevel3'])
1651 self.failUnlessAlmostEqual(r['sigwaveheight'],params['sigwaveheight'],1)
1652 self.failUnlessEqual(r['waveperiod'],params['waveperiod'])
1653 self.failUnlessEqual(r['wavedir'],params['wavedir'])
1654 self.failUnlessAlmostEqual(r['swellheight'],params['swellheight'],1)
1655 self.failUnlessEqual(r['swellperiod'],params['swellperiod'])
1656 self.failUnlessEqual(r['swelldir'],params['swelldir'])
1657 self.failUnlessEqual(r['seastate'],params['seastate'])
1658 self.failUnlessAlmostEqual(r['watertemp'],params['watertemp'],1)
1659 self.failUnlessEqual(r['preciptype'],params['preciptype'])
1660 self.failUnlessAlmostEqual(r['salinity'],params['salinity'],1)
1661 self.failUnlessEqual(r['ice'],params['ice'])
1662 self.failUnlessEqual(r['Spare'],params['Spare'])
1663
1665 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
1666 help='decode a "imo_met_hydro" AIS message')
1667 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
1668 help='encode a "imo_met_hydro" AIS message')
1669 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
1670 ,help='Field parameter value [default: %default]')
1671 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
1672 ,help='Field parameter value [default: %default]')
1673 parser.add_option('--latitude-field', dest='latitudeField',default=Decimal('91'),metavar='decimal',type='string'
1674 ,help='Field parameter value [default: %default]')
1675 parser.add_option('--longitude-field', dest='longitudeField',default=Decimal('181'),metavar='decimal',type='string'
1676 ,help='Field parameter value [default: %default]')
1677 parser.add_option('--day-field', dest='dayField',metavar='uint',type='int'
1678 ,help='Field parameter value [default: %default]')
1679 parser.add_option('--hour-field', dest='hourField',default=31,metavar='uint',type='int'
1680 ,help='Field parameter value [default: %default]')
1681 parser.add_option('--min-field', dest='minField',default=63,metavar='uint',type='int'
1682 ,help='Field parameter value [default: %default]')
1683 parser.add_option('--avewind-field', dest='avewindField',default=127,metavar='uint',type='int'
1684 ,help='Field parameter value [default: %default]')
1685 parser.add_option('--windgust-field', dest='windgustField',default=127,metavar='uint',type='int'
1686 ,help='Field parameter value [default: %default]')
1687 parser.add_option('--winddir-field', dest='winddirField',default=511,metavar='uint',type='int'
1688 ,help='Field parameter value [default: %default]')
1689 parser.add_option('--windgustdir-field', dest='windgustdirField',default=511,metavar='uint',type='int'
1690 ,help='Field parameter value [default: %default]')
1691 parser.add_option('--airtemp-field', dest='airtempField',default=Decimal('102.3'),metavar='decimal',type='string'
1692 ,help='Field parameter value [default: %default]')
1693 parser.add_option('--relhumid-field', dest='relhumidField',default=127,metavar='uint',type='int'
1694 ,help='Field parameter value [default: %default]')
1695 parser.add_option('--dewpoint-field', dest='dewpointField',default=Decimal('51.1'),metavar='decimal',type='string'
1696 ,help='Field parameter value [default: %default]')
1697 parser.add_option('--airpressure-field', dest='airpressureField',default=Decimal('1311'),metavar='udecimal',type='string'
1698 ,help='Field parameter value [default: %default]')
1699 parser.add_option('--airpressuretrend-field', dest='airpressuretrendField',default=3,metavar='uint',type='int'
1700 ,help='Field parameter value [default: %default]')
1701 parser.add_option('--horizvis-field', dest='horizvisField',default=Decimal('25.5'),metavar='udecimal',type='string'
1702 ,help='Field parameter value [default: %default]')
1703 parser.add_option('--waterlevel-field', dest='waterlevelField',metavar='decimal',type='string'
1704 ,help='Field parameter value [default: %default]')
1705 parser.add_option('--waterleveltrend-field', dest='waterleveltrendField',default=3,metavar='uint',type='int'
1706 ,help='Field parameter value [default: %default]')
1707 parser.add_option('--surfcurspeed-field', dest='surfcurspeedField',default=Decimal('25.5'),metavar='udecimal',type='string'
1708 ,help='Field parameter value [default: %default]')
1709 parser.add_option('--surfcurdir-field', dest='surfcurdirField',default=511,metavar='uint',type='int'
1710 ,help='Field parameter value [default: %default]')
1711 parser.add_option('--curspeed2-field', dest='curspeed2Field',default=Decimal('25.5'),metavar='udecimal',type='string'
1712 ,help='Field parameter value [default: %default]')
1713 parser.add_option('--curdir2-field', dest='curdir2Field',default=511,metavar='uint',type='int'
1714 ,help='Field parameter value [default: %default]')
1715 parser.add_option('--curlevel2-field', dest='curlevel2Field',default=31,metavar='uint',type='int'
1716 ,help='Field parameter value [default: %default]')
1717 parser.add_option('--curspeed3-field', dest='curspeed3Field',default=Decimal('25.5'),metavar='udecimal',type='string'
1718 ,help='Field parameter value [default: %default]')
1719 parser.add_option('--curdir3-field', dest='curdir3Field',default=511,metavar='uint',type='int'
1720 ,help='Field parameter value [default: %default]')
1721 parser.add_option('--curlevel3-field', dest='curlevel3Field',default=31,metavar='uint',type='int'
1722 ,help='Field parameter value [default: %default]')
1723 parser.add_option('--sigwaveheight-field', dest='sigwaveheightField',default=Decimal('25.5'),metavar='udecimal',type='string'
1724 ,help='Field parameter value [default: %default]')
1725 parser.add_option('--waveperiod-field', dest='waveperiodField',default=63,metavar='uint',type='int'
1726 ,help='Field parameter value [default: %default]')
1727 parser.add_option('--wavedir-field', dest='wavedirField',default=511,metavar='uint',type='int'
1728 ,help='Field parameter value [default: %default]')
1729 parser.add_option('--swellheight-field', dest='swellheightField',default=Decimal('25.5'),metavar='udecimal',type='string'
1730 ,help='Field parameter value [default: %default]')
1731 parser.add_option('--swellperiod-field', dest='swellperiodField',default=63,metavar='uint',type='int'
1732 ,help='Field parameter value [default: %default]')
1733 parser.add_option('--swelldir-field', dest='swelldirField',default=511,metavar='uint',type='int'
1734 ,help='Field parameter value [default: %default]')
1735 parser.add_option('--seastate-field', dest='seastateField',default=15,metavar='uint',type='int'
1736 ,help='Field parameter value [default: %default]')
1737 parser.add_option('--watertemp-field', dest='watertempField',default=Decimal('92.3'),metavar='udecimal',type='string'
1738 ,help='Field parameter value [default: %default]')
1739 parser.add_option('--preciptype-field', dest='preciptypeField',default=7,metavar='uint',type='int'
1740 ,help='Field parameter value [default: %default]')
1741 parser.add_option('--salinity-field', dest='salinityField',default=Decimal('92.3'),metavar='decimal',type='string'
1742 ,help='Field parameter value [default: %default]')
1743 parser.add_option('--ice-field', dest='iceField',metavar='uint',type='int'
1744 ,help='Field parameter value [default: %default]')
1745
1746
1747 if __name__=='__main__':
1748
1749 from optparse import OptionParser
1750 parser = OptionParser(usage="%prog [options]",
1751 version="%prog "+__version__)
1752
1753 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
1754 help='run the documentation tests')
1755 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
1756 help='run the unit tests')
1757 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
1758 help='Make the test output verbose')
1759
1760
1761
1762 typeChoices = ('binary','nmeapayload','nmea')
1763 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
1764 ,default='nmeapayload'
1765 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
1766
1767
1768 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
1769 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
1770 ,default='std'
1771 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
1772
1773 parser.add_option('-o','--output',dest='outputFileName',default=None,
1774 help='Name of the python file to write [default: stdout]')
1775
1776 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
1777 choices=fieldList,
1778 help='Which fields to include in the output. Currently only for csv output [default: all]')
1779
1780 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
1781 help='Print the field name for csv')
1782
1783 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
1784 help='Print out an sql create command for the table.')
1785
1786 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
1787 help='Print a LaTeX table of the type')
1788
1789 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true',
1790 help='Print delimited table of the type (for Word table importing)')
1791 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t'
1792 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)')
1793
1794
1795 dbChoices = ('sqlite','postgres')
1796 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
1797 ,choices=dbChoices,type='choice'
1798 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
1799
1800 addMsgOptions(parser)
1801
1802 (options,args) = parser.parse_args()
1803 success=True
1804
1805 if options.doctest:
1806 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
1807 sys.argv= [sys.argv[0]]
1808 if options.verbose: sys.argv.append('-v')
1809 import doctest
1810 numfail,numtests=doctest.testmod()
1811 if numfail==0: print 'ok'
1812 else:
1813 print 'FAILED'
1814 success=False
1815
1816 if not success: sys.exit('Something Failed')
1817 del success
1818
1819 if options.unittest:
1820 sys.argv = [sys.argv[0]]
1821 if options.verbose: sys.argv.append('-v')
1822 unittest.main()
1823
1824 outfile = sys.stdout
1825 if None!=options.outputFileName:
1826 outfile = file(options.outputFileName,'w')
1827
1828
1829 if options.doEncode:
1830
1831 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
1832 if None==options.UserIDField: parser.error("missing value for UserIDField")
1833 if None==options.latitudeField: parser.error("missing value for latitudeField")
1834 if None==options.longitudeField: parser.error("missing value for longitudeField")
1835 if None==options.dayField: parser.error("missing value for dayField")
1836 if None==options.hourField: parser.error("missing value for hourField")
1837 if None==options.minField: parser.error("missing value for minField")
1838 if None==options.avewindField: parser.error("missing value for avewindField")
1839 if None==options.windgustField: parser.error("missing value for windgustField")
1840 if None==options.winddirField: parser.error("missing value for winddirField")
1841 if None==options.windgustdirField: parser.error("missing value for windgustdirField")
1842 if None==options.airtempField: parser.error("missing value for airtempField")
1843 if None==options.relhumidField: parser.error("missing value for relhumidField")
1844 if None==options.dewpointField: parser.error("missing value for dewpointField")
1845 if None==options.airpressureField: parser.error("missing value for airpressureField")
1846 if None==options.airpressuretrendField: parser.error("missing value for airpressuretrendField")
1847 if None==options.horizvisField: parser.error("missing value for horizvisField")
1848 if None==options.waterlevelField: parser.error("missing value for waterlevelField")
1849 if None==options.waterleveltrendField: parser.error("missing value for waterleveltrendField")
1850 if None==options.surfcurspeedField: parser.error("missing value for surfcurspeedField")
1851 if None==options.surfcurdirField: parser.error("missing value for surfcurdirField")
1852 if None==options.curspeed2Field: parser.error("missing value for curspeed2Field")
1853 if None==options.curdir2Field: parser.error("missing value for curdir2Field")
1854 if None==options.curlevel2Field: parser.error("missing value for curlevel2Field")
1855 if None==options.curspeed3Field: parser.error("missing value for curspeed3Field")
1856 if None==options.curdir3Field: parser.error("missing value for curdir3Field")
1857 if None==options.curlevel3Field: parser.error("missing value for curlevel3Field")
1858 if None==options.sigwaveheightField: parser.error("missing value for sigwaveheightField")
1859 if None==options.waveperiodField: parser.error("missing value for waveperiodField")
1860 if None==options.wavedirField: parser.error("missing value for wavedirField")
1861 if None==options.swellheightField: parser.error("missing value for swellheightField")
1862 if None==options.swellperiodField: parser.error("missing value for swellperiodField")
1863 if None==options.swelldirField: parser.error("missing value for swelldirField")
1864 if None==options.seastateField: parser.error("missing value for seastateField")
1865 if None==options.watertempField: parser.error("missing value for watertempField")
1866 if None==options.preciptypeField: parser.error("missing value for preciptypeField")
1867 if None==options.salinityField: parser.error("missing value for salinityField")
1868 if None==options.iceField: parser.error("missing value for iceField")
1869 msgDict={
1870 'MessageID': '8',
1871 'RepeatIndicator': options.RepeatIndicatorField,
1872 'UserID': options.UserIDField,
1873 'Spare': '0',
1874 'dac': '1',
1875 'fid': '11',
1876 'latitude': options.latitudeField,
1877 'longitude': options.longitudeField,
1878 'day': options.dayField,
1879 'hour': options.hourField,
1880 'min': options.minField,
1881 'avewind': options.avewindField,
1882 'windgust': options.windgustField,
1883 'winddir': options.winddirField,
1884 'windgustdir': options.windgustdirField,
1885 'airtemp': options.airtempField,
1886 'relhumid': options.relhumidField,
1887 'dewpoint': options.dewpointField,
1888 'airpressure': options.airpressureField,
1889 'airpressuretrend': options.airpressuretrendField,
1890 'horizvis': options.horizvisField,
1891 'waterlevel': options.waterlevelField,
1892 'waterleveltrend': options.waterleveltrendField,
1893 'surfcurspeed': options.surfcurspeedField,
1894 'surfcurdir': options.surfcurdirField,
1895 'curspeed2': options.curspeed2Field,
1896 'curdir2': options.curdir2Field,
1897 'curlevel2': options.curlevel2Field,
1898 'curspeed3': options.curspeed3Field,
1899 'curdir3': options.curdir3Field,
1900 'curlevel3': options.curlevel3Field,
1901 'sigwaveheight': options.sigwaveheightField,
1902 'waveperiod': options.waveperiodField,
1903 'wavedir': options.wavedirField,
1904 'swellheight': options.swellheightField,
1905 'swellperiod': options.swellperiodField,
1906 'swelldir': options.swelldirField,
1907 'seastate': options.seastateField,
1908 'watertemp': options.watertempField,
1909 'preciptype': options.preciptypeField,
1910 'salinity': options.salinityField,
1911 'ice': options.iceField,
1912 'Spare': '0',
1913 }
1914
1915 bits = encode(msgDict)
1916 if 'binary'==options.ioType: print str(bits)
1917 elif 'nmeapayload'==options.ioType:
1918
1919 print "bitLen",len(bits)
1920 bitLen=len(bits)
1921 if bitLen%6!=0:
1922 bits = bits + BitVector(size=(6 - (bitLen%6)))
1923 print "result:",binary.bitvectoais6(bits)[0]
1924
1925
1926
1927 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
1928 else: sys.exit('ERROR: unknown ioType. Help!')
1929
1930
1931 if options.sqlCreate:
1932 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
1933
1934 if options.latexDefinitionTable:
1935 latexDefinitionTable(outfile)
1936
1937
1938 if options.textDefinitionTable:
1939 textDefinitionTable(outfile,options.delimTextDefinitionTable)
1940
1941 if options.printCsvfieldList:
1942
1943 if None == options.fieldList: options.fieldList = fieldList
1944 import StringIO
1945 buf = StringIO.StringIO()
1946 for field in options.fieldList:
1947 buf.write(field+',')
1948 result = buf.getvalue()
1949 if result[-1] == ',': print result[:-1]
1950 else: print result
1951
1952 if options.doDecode:
1953 if len(args)==0: args = sys.stdin
1954 for msg in args:
1955 bv = None
1956
1957 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
1958
1959
1960 bv = binary.ais6tobitvec(msg.split(',')[5])
1961 else:
1962
1963 binaryMsg=True
1964 for c in msg:
1965 if c not in ('0','1'):
1966 binaryMsg=False
1967 break
1968 if binaryMsg:
1969 bv = BitVector(bitstring=msg)
1970 else:
1971 bv = binary.ais6tobitvec(msg)
1972
1973 printFields(decode(bv)
1974 ,out=outfile
1975 ,format=options.outputType
1976 ,fieldList=options.fieldList
1977 ,dbType=options.dbType
1978 )
1979