1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-01-18 $'.split()[1]
5 __author__ = 'xmlbinmsg'
6
7 __doc__='''
8
9 Autogenerated python functions to serialize/deserialize binary messages.
10
11 Generated by: ./aisxmlbinmsg2py.py
12
13 Need to then wrap these functions with the outer AIS packet and then
14 convert the whole binary blob to a NMEA string. Those functions are
15 not currently provided in this file.
16
17 serialize: python to ais binary
18 deserialize: ais binary to python
19
20 The generated code uses translators.py, binary.py, and aisstring.py
21 which should be packaged with the resulting files.
22
23
24 @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3
25 @requires: U{BitVector<http://cheeseshop.python.org/pypi/BitVector>}
26
27 @author: '''+__author__+'''
28 @version: ''' + __version__ +'''
29 @var __date__: Date of last svn commit
30 @undocumented: __version__ __author__ __doc__ parser
31 @status: under development
32 @license: Generated code has no license
33 '''
34
35 import sys
36 from decimal import Decimal
37 from BitVector import BitVector
38
39 import binary, aisstring
40
41
42 TrueBV = BitVector(bitstring="1")
43 "Why always rebuild the True bit? This should speed things up a bunch"
44 FalseBV = BitVector(bitstring="0")
45 "Why always rebuild the False bit? This should speed things up a bunch"
46
47
48 fieldList = [
49 'time_month',
50 'time_day',
51 'time_hour',
52 'time_min',
53 'stationid',
54 'pos_longitude',
55 'pos_latitude',
56 'speed',
57 'gust',
58 'direction',
59 'atmpressure',
60 'airtemp',
61 'dewpoint',
62 'visibility',
63 'watertemp',
64 'reserved',
65 ]
66
67 -def encode(params, validate=False):
68 '''Create a sls_weatherreport binary message payload to pack into an AIS Msg sls_weatherreport.
69
70 Fields in params:
71 - time_month(uint): Time tag of measurement month 1..12
72 - time_day(uint): Time tag of measurement day of the month 1..31
73 - time_hour(uint): Time tag of measurement UTC hours 0..23
74 - time_min(uint): Time tag of measurement minutes
75 - stationid(aisstr6): Character identifier of the station
76 - pos_longitude(decimal): Location of measurement East West location
77 - pos_latitude(decimal): Location of measurement North South location
78 - speed(udecimal): Average wind speed
79 - gust(udecimal): Wind gust
80 - direction(uint): Wind direction
81 - atmpressure(udecimal): Atmospheric pressure
82 - airtemp(decimal): Air temperature
83 - dewpoint(decimal): Dew Point
84 - visibility(udecimal): Visibility
85 - watertemp(decimal): Water Temperature
86 - reserved(uint): Reserved bits for future use (field automatically set to "0")
87 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
88 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
89 @rtype: BitVector
90 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
91 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
92 '''
93
94 bvList = []
95 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_month']),4))
96 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_day']),5))
97 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_hour']),5))
98 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_min']),6))
99 if 'stationid' in params:
100 bvList.append(aisstring.encode(params['stationid'],42))
101 else:
102 bvList.append(aisstring.encode('@@@@@@@',42))
103 if 'pos_longitude' in params:
104 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_longitude'])*Decimal('60000')),25))
105 else:
106 bvList.append(binary.bvFromSignedInt(10860000,25))
107 if 'pos_latitude' in params:
108 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_latitude'])*Decimal('60000')),24))
109 else:
110 bvList.append(binary.bvFromSignedInt(5460000,24))
111 if 'speed' in params:
112 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['speed'])*Decimal('10')))),10))
113 else:
114 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(1023)),10))
115 if 'gust' in params:
116 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['gust'])*Decimal('10')))),10))
117 else:
118 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(1023)),10))
119 if 'direction' in params:
120 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['direction']),9))
121 else:
122 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9))
123 if 'atmpressure' in params:
124 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['atmpressure'])*Decimal('10')))),14))
125 else:
126 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(163830)),14))
127 if 'airtemp' in params:
128 bvList.append(binary.bvFromSignedInt(int(Decimal(params['airtemp'])*Decimal('10')),10))
129 else:
130 bvList.append(binary.bvFromSignedInt(-512,10))
131 if 'dewpoint' in params:
132 bvList.append(binary.bvFromSignedInt(int(Decimal(params['dewpoint'])*Decimal('10')),10))
133 else:
134 bvList.append(binary.bvFromSignedInt(-512,10))
135 if 'visibility' in params:
136 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['visibility'])*Decimal('10')))),8))
137 else:
138 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(255)),8))
139 if 'watertemp' in params:
140 bvList.append(binary.bvFromSignedInt(int(Decimal(params['watertemp'])*Decimal('10')),10))
141 else:
142 bvList.append(binary.bvFromSignedInt(-512,10))
143 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
144
145 return binary.joinBV(bvList)
146
147 -def decode(bv, validate=False):
148 '''Unpack a sls_weatherreport message
149
150 Fields in params:
151 - time_month(uint): Time tag of measurement month 1..12
152 - time_day(uint): Time tag of measurement day of the month 1..31
153 - time_hour(uint): Time tag of measurement UTC hours 0..23
154 - time_min(uint): Time tag of measurement minutes
155 - stationid(aisstr6): Character identifier of the station
156 - pos_longitude(decimal): Location of measurement East West location
157 - pos_latitude(decimal): Location of measurement North South location
158 - speed(udecimal): Average wind speed
159 - gust(udecimal): Wind gust
160 - direction(uint): Wind direction
161 - atmpressure(udecimal): Atmospheric pressure
162 - airtemp(decimal): Air temperature
163 - dewpoint(decimal): Dew Point
164 - visibility(udecimal): Visibility
165 - watertemp(decimal): Water Temperature
166 - reserved(uint): Reserved bits for future use (field automatically set to "0")
167 @type bv: BitVector
168 @param bv: Bits defining a message
169 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
170 @rtype: dict
171 @return: params
172 '''
173
174
175
176
177 r = {}
178 r['time_month']=int(bv[0:4])
179 r['time_day']=int(bv[4:9])
180 r['time_hour']=int(bv[9:14])
181 r['time_min']=int(bv[14:20])
182 r['stationid']=aisstring.decode(bv[20:62])
183 r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
184 r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
185 r['speed']=Decimal(int(bv[111:121]))/Decimal('10')
186 r['gust']=Decimal(int(bv[121:131]))/Decimal('10')
187 r['direction']=int(bv[131:140])
188 r['atmpressure']=Decimal(int(bv[140:154]))/Decimal('10')
189 r['airtemp']=Decimal(binary.signedIntFromBV(bv[154:164]))/Decimal('10')
190 r['dewpoint']=Decimal(binary.signedIntFromBV(bv[164:174]))/Decimal('10')
191 r['visibility']=Decimal(int(bv[174:182]))/Decimal('10')
192 r['watertemp']=Decimal(binary.signedIntFromBV(bv[182:192]))/Decimal('10')
193 r['reserved']=0
194 return r
195
198
201
204
206 return int(bv[14:20])
207
210
213
216
218 return Decimal(int(bv[111:121]))/Decimal('10')
219
221 return Decimal(int(bv[121:131]))/Decimal('10')
222
224 return int(bv[131:140])
225
227 return Decimal(int(bv[140:154]))/Decimal('10')
228
231
234
236 return Decimal(int(bv[174:182]))/Decimal('10')
237
240
242 return 0
243
244
246 out.write("<h3>sls_weatherreport<h3>\n")
247 out.write("<table border=\"1\">\n")
248 out.write("<tr bgcolor=\"orange\">\n")
249 out.write("<th align=\"left\">Field Name</th>\n")
250 out.write("<th align=\"left\">Type</th>\n")
251 out.write("<th align=\"left\">Value</th>\n")
252 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
253 out.write("<th align=\"left\">Units</th>\n")
254 out.write("\n")
255 out.write("<tr>\n")
256 out.write("<td>time_month</td>\n")
257 out.write("<td>uint</td>\n")
258 if 'time_month' in params:
259 out.write(" <td>"+str(params['time_month'])+"</td>\n")
260 out.write(" <td>"+str(params['time_month'])+"</td>\n")
261 out.write("</tr>\n")
262 out.write("\n")
263 out.write("<tr>\n")
264 out.write("<td>time_day</td>\n")
265 out.write("<td>uint</td>\n")
266 if 'time_day' in params:
267 out.write(" <td>"+str(params['time_day'])+"</td>\n")
268 out.write(" <td>"+str(params['time_day'])+"</td>\n")
269 out.write("</tr>\n")
270 out.write("\n")
271 out.write("<tr>\n")
272 out.write("<td>time_hour</td>\n")
273 out.write("<td>uint</td>\n")
274 if 'time_hour' in params:
275 out.write(" <td>"+str(params['time_hour'])+"</td>\n")
276 out.write(" <td>"+str(params['time_hour'])+"</td>\n")
277 out.write("</tr>\n")
278 out.write("\n")
279 out.write("<tr>\n")
280 out.write("<td>time_min</td>\n")
281 out.write("<td>uint</td>\n")
282 if 'time_min' in params:
283 out.write(" <td>"+str(params['time_min'])+"</td>\n")
284 out.write(" <td>"+str(params['time_min'])+"</td>\n")
285 out.write("</tr>\n")
286 out.write("\n")
287 out.write("<tr>\n")
288 out.write("<td>stationid</td>\n")
289 out.write("<td>aisstr6</td>\n")
290 if 'stationid' in params:
291 out.write(" <td>"+str(params['stationid'])+"</td>\n")
292 out.write(" <td>"+str(params['stationid'])+"</td>\n")
293 out.write("</tr>\n")
294 out.write("\n")
295 out.write("<tr>\n")
296 out.write("<td>pos_longitude</td>\n")
297 out.write("<td>decimal</td>\n")
298 if 'pos_longitude' in params:
299 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n")
300 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n")
301 out.write("<td>degrees</td>\n")
302 out.write("</tr>\n")
303 out.write("\n")
304 out.write("<tr>\n")
305 out.write("<td>pos_latitude</td>\n")
306 out.write("<td>decimal</td>\n")
307 if 'pos_latitude' in params:
308 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n")
309 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n")
310 out.write("<td>degrees</td>\n")
311 out.write("</tr>\n")
312 out.write("\n")
313 out.write("<tr>\n")
314 out.write("<td>speed</td>\n")
315 out.write("<td>udecimal</td>\n")
316 if 'speed' in params:
317 out.write(" <td>"+str(params['speed'])+"</td>\n")
318 if str(params['speed']) in speedDecodeLut:
319 out.write("<td>"+speedDecodeLut[str(params['speed'])]+"</td>")
320 else:
321 out.write("<td><i>Missing LUT entry</i></td>")
322 out.write("<td>kts</td>\n")
323 out.write("</tr>\n")
324 out.write("\n")
325 out.write("<tr>\n")
326 out.write("<td>gust</td>\n")
327 out.write("<td>udecimal</td>\n")
328 if 'gust' in params:
329 out.write(" <td>"+str(params['gust'])+"</td>\n")
330 if str(params['gust']) in gustDecodeLut:
331 out.write("<td>"+gustDecodeLut[str(params['gust'])]+"</td>")
332 else:
333 out.write("<td><i>Missing LUT entry</i></td>")
334 out.write("<td>kts</td>\n")
335 out.write("</tr>\n")
336 out.write("\n")
337 out.write("<tr>\n")
338 out.write("<td>direction</td>\n")
339 out.write("<td>uint</td>\n")
340 if 'direction' in params:
341 out.write(" <td>"+str(params['direction'])+"</td>\n")
342 out.write(" <td>"+str(params['direction'])+"</td>\n")
343 out.write("<td>degrees</td>\n")
344 out.write("</tr>\n")
345 out.write("\n")
346 out.write("<tr>\n")
347 out.write("<td>atmpressure</td>\n")
348 out.write("<td>udecimal</td>\n")
349 if 'atmpressure' in params:
350 out.write(" <td>"+str(params['atmpressure'])+"</td>\n")
351 out.write(" <td>"+str(params['atmpressure'])+"</td>\n")
352 out.write("<td>millibars</td>\n")
353 out.write("</tr>\n")
354 out.write("\n")
355 out.write("<tr>\n")
356 out.write("<td>airtemp</td>\n")
357 out.write("<td>decimal</td>\n")
358 if 'airtemp' in params:
359 out.write(" <td>"+str(params['airtemp'])+"</td>\n")
360 if str(params['airtemp']) in airtempDecodeLut:
361 out.write("<td>"+airtempDecodeLut[str(params['airtemp'])]+"</td>")
362 else:
363 out.write("<td><i>Missing LUT entry</i></td>")
364 out.write("<td>Celsius</td>\n")
365 out.write("</tr>\n")
366 out.write("\n")
367 out.write("<tr>\n")
368 out.write("<td>dewpoint</td>\n")
369 out.write("<td>decimal</td>\n")
370 if 'dewpoint' in params:
371 out.write(" <td>"+str(params['dewpoint'])+"</td>\n")
372 if str(params['dewpoint']) in dewpointDecodeLut:
373 out.write("<td>"+dewpointDecodeLut[str(params['dewpoint'])]+"</td>")
374 else:
375 out.write("<td><i>Missing LUT entry</i></td>")
376 out.write("<td>Celsius</td>\n")
377 out.write("</tr>\n")
378 out.write("\n")
379 out.write("<tr>\n")
380 out.write("<td>visibility</td>\n")
381 out.write("<td>udecimal</td>\n")
382 if 'visibility' in params:
383 out.write(" <td>"+str(params['visibility'])+"</td>\n")
384 if str(params['visibility']) in visibilityDecodeLut:
385 out.write("<td>"+visibilityDecodeLut[str(params['visibility'])]+"</td>")
386 else:
387 out.write("<td><i>Missing LUT entry</i></td>")
388 out.write("<td>km</td>\n")
389 out.write("</tr>\n")
390 out.write("\n")
391 out.write("<tr>\n")
392 out.write("<td>watertemp</td>\n")
393 out.write("<td>decimal</td>\n")
394 if 'watertemp' in params:
395 out.write(" <td>"+str(params['watertemp'])+"</td>\n")
396 if str(params['watertemp']) in watertempDecodeLut:
397 out.write("<td>"+watertempDecodeLut[str(params['watertemp'])]+"</td>")
398 else:
399 out.write("<td><i>Missing LUT entry</i></td>")
400 out.write("<td>Celsius</td>\n")
401 out.write("</tr>\n")
402 out.write("\n")
403 out.write("<tr>\n")
404 out.write("<td>reserved</td>\n")
405 out.write("<td>uint</td>\n")
406 if 'reserved' in params:
407 out.write(" <td>"+str(params['reserved'])+"</td>\n")
408 out.write(" <td>"+str(params['reserved'])+"</td>\n")
409 out.write("</tr>\n")
410 out.write("</table>\n")
411
412
414 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
415 out.write("\ <Placemark>\n")
416 out.write("\t <name>"+str(params['stationid'])+"</name>\n")
417 out.write("\t\t<description>\n")
418 import StringIO
419 buf = StringIO.StringIO()
420 printHtml(params,buf)
421 import cgi
422 out.write(cgi.escape(buf.getvalue()))
423 out.write("\t\t</description>\n")
424 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
425 out.write("\t\t<Point>\n")
426 out.write("\t\t\t<coordinates>")
427 out.write(str(params['pos_longitude']))
428 out.write(',')
429 out.write(str(params['pos_latitude']))
430 out.write(",0</coordinates>\n")
431 out.write("\t\t</Point>\n")
432 out.write("\t</Placemark>\n")
433
434 -def printFields(params, out=sys.stdout, format='std', fieldList=None):
435 '''Print a reserved message to stdout.
436
437 Fields in params:
438 - time_month(uint): Time tag of measurement month 1..12
439 - time_day(uint): Time tag of measurement day of the month 1..31
440 - time_hour(uint): Time tag of measurement UTC hours 0..23
441 - time_min(uint): Time tag of measurement minutes
442 - stationid(aisstr6): Character identifier of the station
443 - pos_longitude(decimal): Location of measurement East West location
444 - pos_latitude(decimal): Location of measurement North South location
445 - speed(udecimal): Average wind speed
446 - gust(udecimal): Wind gust
447 - direction(uint): Wind direction
448 - atmpressure(udecimal): Atmospheric pressure
449 - airtemp(decimal): Air temperature
450 - dewpoint(decimal): Dew Point
451 - visibility(udecimal): Visibility
452 - watertemp(decimal): Water Temperature
453 - reserved(uint): Reserved bits for future use (field automatically set to "0")
454 @param params: Dictionary of field names/values.
455 @param out: File like object to write to
456 @rtype: stdout
457 @return: text to out
458 '''
459
460 if 'std'==format:
461 out.write("reserved:\n")
462 if 'time_month' in params: out.write(" time_month: "+str(params['time_month'])+"\n")
463 if 'time_day' in params: out.write(" time_day: "+str(params['time_day'])+"\n")
464 if 'time_hour' in params: out.write(" time_hour: "+str(params['time_hour'])+"\n")
465 if 'time_min' in params: out.write(" time_min: "+str(params['time_min'])+"\n")
466 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n")
467 if 'pos_longitude' in params: out.write(" pos_longitude: "+str(params['pos_longitude'])+"\n")
468 if 'pos_latitude' in params: out.write(" pos_latitude: "+str(params['pos_latitude'])+"\n")
469 if 'speed' in params: out.write(" speed: "+str(params['speed'])+"\n")
470 if 'gust' in params: out.write(" gust: "+str(params['gust'])+"\n")
471 if 'direction' in params: out.write(" direction: "+str(params['direction'])+"\n")
472 if 'atmpressure' in params: out.write(" atmpressure: "+str(params['atmpressure'])+"\n")
473 if 'airtemp' in params: out.write(" airtemp: "+str(params['airtemp'])+"\n")
474 if 'dewpoint' in params: out.write(" dewpoint: "+str(params['dewpoint'])+"\n")
475 if 'visibility' in params: out.write(" visibility: "+str(params['visibility'])+"\n")
476 if 'watertemp' in params: out.write(" watertemp: "+str(params['watertemp'])+"\n")
477 if 'reserved' in params: out.write(" reserved: "+str(params['reserved'])+"\n")
478 elif 'csv'==format:
479 if None == options.fieldList:
480 options.fieldList = fieldList
481 needComma = False;
482 for field in fieldList:
483 if needComma: out.write(',')
484 needComma = True
485 if field in params:
486 out.write(str(params[field]))
487
488 out.write("\n")
489 elif 'html'==format:
490 printHtml(params,out)
491 elif 'kml'==format:
492 printKml(params,out)
493 elif 'kml-full'==format:
494 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
495 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
496 out.write("<Document>\n")
497 out.write(" <name>Position</name>\n")
498 printKml(params,out)
499 out.write("</Document>\n")
500 out.write("</kml>\n")
501 else:
502 print "ERROR: unknown format:",format
503 assert False
504
505 return
506
507 speedEncodeLut = {
508 '102.2 kts or greater':'102.2',
509 }
510
511 speedDecodeLut = {
512 '102.2':'102.2 kts or greater',
513 }
514
515 gustEncodeLut = {
516 '102.2 kts or greater':'102.2',
517 }
518
519 gustDecodeLut = {
520 '102.2':'102.2 kts or greater',
521 }
522
523 airtempEncodeLut = {
524 '-51.1 degrees C or lower':'-51.1',
525 '51.1 degrees C or greater':'51.1',
526 }
527
528 airtempDecodeLut = {
529 '-51.1':'-51.1 degrees C or lower',
530 '51.1':'51.1 degrees C or greater',
531 }
532
533 dewpointEncodeLut = {
534 '-51.1 degrees C or lower':'-51.1',
535 '51.1 degrees C or greater':'51.1',
536 }
537
538 dewpointDecodeLut = {
539 '-51.1':'-51.1 degrees C or lower',
540 '51.1':'51.1 degrees C or greater',
541 }
542
543 visibilityEncodeLut = {
544 '25.4 km or greater':'25.4',
545 }
546
547 visibilityDecodeLut = {
548 '25.4':'25.4 km or greater',
549 }
550
551 watertempEncodeLut = {
552 '-51.1 degrees C or lower':'-51.1',
553 '51.1 degrees C or greater':'51.1',
554 }
555
556 watertempDecodeLut = {
557 '-51.1':'-51.1 degrees C or lower',
558 '51.1':'51.1 degrees C or greater',
559 }
560
561
562
563
564
565
566 import unittest
568 '''Return a params file base on the testvalue tags.
569 @rtype: dict
570 @return: params based on testvalue tags
571 '''
572 params = {}
573 params['time_month'] = 2
574 params['time_day'] = 28
575 params['time_hour'] = 23
576 params['time_min'] = 45
577 params['stationid'] = 'A345678'
578 params['pos_longitude'] = Decimal('-122.16328')
579 params['pos_latitude'] = Decimal('37.42446')
580 params['speed'] = Decimal('0.7')
581 params['gust'] = Decimal('0.7')
582 params['direction'] = 41
583 params['atmpressure'] = Decimal('0.7')
584 params['airtemp'] = Decimal('-8')
585 params['dewpoint'] = Decimal('-7')
586 params['visibility'] = Decimal('12.3')
587 params['watertemp'] = Decimal('-0.2')
588 params['reserved'] = 0
589
590 return params
591
593 '''Use testvalue tag text from each type to build test case the sls_weatherreport message'''
595
596 params = testParams()
597 bits = encode(params)
598 r = decode(bits)
599
600
601 self.failUnlessEqual(r['time_month'],params['time_month'])
602 self.failUnlessEqual(r['time_day'],params['time_day'])
603 self.failUnlessEqual(r['time_hour'],params['time_hour'])
604 self.failUnlessEqual(r['time_min'],params['time_min'])
605 self.failUnlessEqual(r['stationid'],params['stationid'])
606 self.failUnlessAlmostEqual(r['pos_longitude'],params['pos_longitude'],4)
607 self.failUnlessAlmostEqual(r['pos_latitude'],params['pos_latitude'],4)
608 self.failUnlessAlmostEqual(r['speed'],params['speed'],3)
609 self.failUnlessAlmostEqual(r['gust'],params['gust'],3)
610 self.failUnlessEqual(r['direction'],params['direction'])
611 self.failUnlessAlmostEqual(r['atmpressure'],params['atmpressure'],3)
612 self.failUnlessAlmostEqual(r['airtemp'],params['airtemp'],3)
613 self.failUnlessAlmostEqual(r['dewpoint'],params['dewpoint'],3)
614 self.failUnlessAlmostEqual(r['visibility'],params['visibility'],3)
615 self.failUnlessAlmostEqual(r['watertemp'],params['watertemp'],3)
616 self.failUnlessEqual(r['reserved'],params['reserved'])
617
619 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
620 help='decode a "sls_weatherreport" AIS message')
621 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
622 help='encode a "sls_weatherreport" AIS message')
623 parser.add_option('--time_month-field', dest='time_monthField',metavar='uint',type='int'
624 ,help='Field parameter value [default: %default]')
625 parser.add_option('--time_day-field', dest='time_dayField',metavar='uint',type='int'
626 ,help='Field parameter value [default: %default]')
627 parser.add_option('--time_hour-field', dest='time_hourField',metavar='uint',type='int'
628 ,help='Field parameter value [default: %default]')
629 parser.add_option('--time_min-field', dest='time_minField',metavar='uint',type='int'
630 ,help='Field parameter value [default: %default]')
631 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
632 ,help='Field parameter value [default: %default]')
633 parser.add_option('--pos_longitude-field', dest='pos_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
634 ,help='Field parameter value [default: %default]')
635 parser.add_option('--pos_latitude-field', dest='pos_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
636 ,help='Field parameter value [default: %default]')
637 parser.add_option('--speed-field', dest='speedField',default=Decimal('102.3'),metavar='udecimal',type='string'
638 ,help='Field parameter value [default: %default]')
639 parser.add_option('--gust-field', dest='gustField',default=Decimal('102.3'),metavar='udecimal',type='string'
640 ,help='Field parameter value [default: %default]')
641 parser.add_option('--direction-field', dest='directionField',default=511,metavar='uint',type='int'
642 ,help='Field parameter value [default: %default]')
643 parser.add_option('--atmpressure-field', dest='atmpressureField',default=Decimal('16383'),metavar='udecimal',type='string'
644 ,help='Field parameter value [default: %default]')
645 parser.add_option('--airtemp-field', dest='airtempField',default=Decimal('-51.2'),metavar='decimal',type='string'
646 ,help='Field parameter value [default: %default]')
647 parser.add_option('--dewpoint-field', dest='dewpointField',default=Decimal('-51.2'),metavar='decimal',type='string'
648 ,help='Field parameter value [default: %default]')
649 parser.add_option('--visibility-field', dest='visibilityField',default=Decimal('25.5'),metavar='udecimal',type='string'
650 ,help='Field parameter value [default: %default]')
651 parser.add_option('--watertemp-field', dest='watertempField',default=Decimal('-51.2'),metavar='decimal',type='string'
652 ,help='Field parameter value [default: %default]')
653
654
655 if __name__=='__main__':
656
657 from optparse import OptionParser
658 parser = OptionParser(usage="%prog [options]",
659 version="%prog "+__version__)
660
661 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
662 help='run the documentation tests')
663 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
664 help='run the unit tests')
665 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
666 help='Make the test output verbose')
667
668
669
670 typeChoices = ('binary','nmeapayload','nmea')
671 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
672 ,default='nmeapayload'
673 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]')
674
675
676 outputChoices = ('std','html','csv' , 'kml','kml-full')
677 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
678 ,default='std'
679 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
680
681 parser.add_option('-o','--output',dest='outputFileName',default=None,
682 help='Name of the python file to write [default: stdout]')
683
684 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
685 choices=fieldList,
686 help='Which fields to include in the output. Currently only for csv output [default: all]')
687
688 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
689 help='Print the field name for csv')
690
691 addMsgOptions(parser)
692
693 (options,args) = parser.parse_args()
694 success=True
695
696 if options.doctest:
697 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
698 sys.argv= [sys.argv[0]]
699 if options.verbose: sys.argv.append('-v')
700 import doctest
701 numfail,numtests=doctest.testmod()
702 if numfail==0: print 'ok'
703 else:
704 print 'FAILED'
705 success=False
706
707 if not success: sys.exit('Something Failed')
708 del success
709
710 if options.unittest:
711 sys.argv = [sys.argv[0]]
712 if options.verbose: sys.argv.append('-v')
713 unittest.main()
714
715 outfile = sys.stdout
716 if None!=options.outputFileName:
717 outfile = file(options.outputFileName,'w')
718
719
720 if options.doEncode:
721
722 if None==options.time_monthField: parser.error("missing value for time_monthField")
723 if None==options.time_dayField: parser.error("missing value for time_dayField")
724 if None==options.time_hourField: parser.error("missing value for time_hourField")
725 if None==options.time_minField: parser.error("missing value for time_minField")
726 if None==options.stationidField: parser.error("missing value for stationidField")
727 if None==options.pos_longitudeField: parser.error("missing value for pos_longitudeField")
728 if None==options.pos_latitudeField: parser.error("missing value for pos_latitudeField")
729 if None==options.speedField: parser.error("missing value for speedField")
730 if None==options.gustField: parser.error("missing value for gustField")
731 if None==options.directionField: parser.error("missing value for directionField")
732 if None==options.atmpressureField: parser.error("missing value for atmpressureField")
733 if None==options.airtempField: parser.error("missing value for airtempField")
734 if None==options.dewpointField: parser.error("missing value for dewpointField")
735 if None==options.visibilityField: parser.error("missing value for visibilityField")
736 if None==options.watertempField: parser.error("missing value for watertempField")
737 msgDict={
738 'time_month': options.time_monthField,
739 'time_day': options.time_dayField,
740 'time_hour': options.time_hourField,
741 'time_min': options.time_minField,
742 'stationid': options.stationidField,
743 'pos_longitude': options.pos_longitudeField,
744 'pos_latitude': options.pos_latitudeField,
745 'speed': options.speedField,
746 'gust': options.gustField,
747 'direction': options.directionField,
748 'atmpressure': options.atmpressureField,
749 'airtemp': options.airtempField,
750 'dewpoint': options.dewpointField,
751 'visibility': options.visibilityField,
752 'watertemp': options.watertempField,
753 'reserved': '0',
754 }
755
756 bits = encode(msgDict)
757 if 'binary'==options.ioType: print str(bits)
758 elif 'nmeapayload'==options.ioType:
759
760 print "bitLen",len(bits)
761 bitLen=len(bits)
762 if bitLen%6!=0:
763 bits = bits + BitVector(size=(6 - (bitLen%6)))
764 print "result:",binary.bitvectoais6(bits)[0]
765
766
767
768 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
769 else: sys.exit('ERROR: unknown ioType. Help!')
770
771 if options.printCsvfieldList:
772
773 if None == options.fieldList: options.fieldList = fieldList
774 import StringIO
775 buf = StringIO.StringIO()
776 for field in options.fieldList:
777 buf.write(field+',')
778 result = buf.getvalue()
779 if result[-1] == ',': print result[:-1]
780 else: print result
781
782 if options.doDecode:
783 for msg in args:
784 bv = None
785 if 'binary' == options.ioType: bv = BitVector(bitstring=msg)
786 elif 'nmeapayload'== options.ioType: bv = binary.ais6tobitvec(msg)
787 elif 'nmea' == options.ioType: bv = binary.ais6tobitvec(msg.split(',')[5])
788 else: sys.exit('ERROR: unknown ioType. Help!')
789
790 printFields(decode(bv),out=outfile,format=options.outputType,fieldList=options.fieldList)
791