1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-01-23 $'.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 'sql'==format:
492 sqlInsertStr(params,out)
493 elif 'kml'==format:
494 printKml(params,out)
495 elif 'kml-full'==format:
496 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
497 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
498 out.write("<Document>\n")
499 out.write(" <name>sls_weatherreport</name>\n")
500 printKml(params,out)
501 out.write("</Document>\n")
502 out.write("</kml>\n")
503 else:
504 print "ERROR: unknown format:",format
505 assert False
506
507 return
508
509 speedEncodeLut = {
510 '102.2 kts or greater':'102.2',
511 }
512
513 speedDecodeLut = {
514 '102.2':'102.2 kts or greater',
515 }
516
517 gustEncodeLut = {
518 '102.2 kts or greater':'102.2',
519 }
520
521 gustDecodeLut = {
522 '102.2':'102.2 kts or greater',
523 }
524
525 airtempEncodeLut = {
526 '-51.1 degrees C or lower':'-51.1',
527 '51.1 degrees C or greater':'51.1',
528 }
529
530 airtempDecodeLut = {
531 '-51.1':'-51.1 degrees C or lower',
532 '51.1':'51.1 degrees C or greater',
533 }
534
535 dewpointEncodeLut = {
536 '-51.1 degrees C or lower':'-51.1',
537 '51.1 degrees C or greater':'51.1',
538 }
539
540 dewpointDecodeLut = {
541 '-51.1':'-51.1 degrees C or lower',
542 '51.1':'51.1 degrees C or greater',
543 }
544
545 visibilityEncodeLut = {
546 '25.4 km or greater':'25.4',
547 }
548
549 visibilityDecodeLut = {
550 '25.4':'25.4 km or greater',
551 }
552
553 watertempEncodeLut = {
554 '-51.1 degrees C or lower':'-51.1',
555 '51.1 degrees C or greater':'51.1',
556 }
557
558 watertempDecodeLut = {
559 '-51.1':'-51.1 degrees C or lower',
560 '51.1':'51.1 degrees C or greater',
561 }
562
563
564
565
566
567 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None):
568 '''
569 Return the SQL CREATE command for this message type
570 @param outfile: file like object to print to.
571 @param fields: which fields to put in the create. Defaults to all.
572 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
573 @return: sql create string
574 @rtype: str
575
576 @see: sqlCreate
577 '''
578 outfile.write(str(sqlCreate(fields,extraFields)))
579
580 -def sqlCreate(fields=None, extraFields=None):
581 '''
582 Return the sqlhelp object to create the table.
583
584 @param fields: which fields to put in the create. Defaults to all.
585 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
586 @return: An object that can be used to generate a return
587 @rtype: sqlhelp.create
588 '''
589 if None == fields: fields = fieldList
590 import sqlhelp
591 c = sqlhelp.create('sls_weatherreport')
592 if 'time_month' in fields: c.addInt ('time_month')
593 if 'time_day' in fields: c.addInt ('time_day')
594 if 'time_hour' in fields: c.addInt ('time_hour')
595 if 'time_min' in fields: c.addInt ('time_min')
596 if 'stationid' in fields: c.addVarChar(stationid,7)
597 if 'pos_longitude' in fields: c.addDecimal('pos_longitude',7,4)
598 if 'pos_latitude' in fields: c.addDecimal('pos_latitude',7,4)
599 if 'speed' in fields: c.addDecimal('speed',4,1)
600 if 'gust' in fields: c.addDecimal('gust',4,1)
601 if 'direction' in fields: c.addInt ('direction')
602 if 'atmpressure' in fields: c.addDecimal('atmpressure',5,1)
603 if 'airtemp' in fields: c.addDecimal('airtemp',4,1)
604 if 'dewpoint' in fields: c.addDecimal('dewpoint',4,1)
605 if 'visibility' in fields: c.addDecimal('visibility',3,1)
606 if 'watertemp' in fields: c.addDecimal('watertemp',4,1)
607 if 'reserved' in fields: c.addInt ('reserved')
608
609 return c
610
611 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None):
612 '''
613 Return the SQL CREATE command for this message type
614 @param params: dictionary of values keyed by field name
615 @param outfile: file like object to print to.
616 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
617 @return: sql create string
618 @rtype: str
619
620 @see: sqlCreate
621 '''
622 outfile.write(str(sqlInsert(params,extraParams)))
623
624
626 '''
627 Give the SQL insert statement
628 @param params: dict keyed by field name of values
629 @param extraParams: any extra fields that you have created beyond the normal ais message fields
630 @rtype: sqlhelp.insert
631 @return: insert class instance
632 @todo: allow optional type checking of params?
633 @warning: this will take invalid keys happily and do what???
634 '''
635 import sqlhelp
636 i = sqlhelp.insert('sls_weatherreport')
637 for key in params: i.add(key,params[key])
638 if None != extraParams:
639 for key in extraParams:
640 i.add(key,extraParams[key])
641
642 return i
643
644
645
646
647
648 import unittest
650 '''Return a params file base on the testvalue tags.
651 @rtype: dict
652 @return: params based on testvalue tags
653 '''
654 params = {}
655 params['time_month'] = 2
656 params['time_day'] = 28
657 params['time_hour'] = 23
658 params['time_min'] = 45
659 params['stationid'] = 'A345678'
660 params['pos_longitude'] = Decimal('-122.16328')
661 params['pos_latitude'] = Decimal('37.42446')
662 params['speed'] = Decimal('0.7')
663 params['gust'] = Decimal('0.7')
664 params['direction'] = 41
665 params['atmpressure'] = Decimal('0.7')
666 params['airtemp'] = Decimal('-8')
667 params['dewpoint'] = Decimal('-7')
668 params['visibility'] = Decimal('12.3')
669 params['watertemp'] = Decimal('-0.2')
670 params['reserved'] = 0
671
672 return params
673
675 '''Use testvalue tag text from each type to build test case the sls_weatherreport message'''
677
678 params = testParams()
679 bits = encode(params)
680 r = decode(bits)
681
682
683 self.failUnlessEqual(r['time_month'],params['time_month'])
684 self.failUnlessEqual(r['time_day'],params['time_day'])
685 self.failUnlessEqual(r['time_hour'],params['time_hour'])
686 self.failUnlessEqual(r['time_min'],params['time_min'])
687 self.failUnlessEqual(r['stationid'],params['stationid'])
688 self.failUnlessAlmostEqual(r['pos_longitude'],params['pos_longitude'],4)
689 self.failUnlessAlmostEqual(r['pos_latitude'],params['pos_latitude'],4)
690 self.failUnlessAlmostEqual(r['speed'],params['speed'],1)
691 self.failUnlessAlmostEqual(r['gust'],params['gust'],1)
692 self.failUnlessEqual(r['direction'],params['direction'])
693 self.failUnlessAlmostEqual(r['atmpressure'],params['atmpressure'],1)
694 self.failUnlessAlmostEqual(r['airtemp'],params['airtemp'],1)
695 self.failUnlessAlmostEqual(r['dewpoint'],params['dewpoint'],1)
696 self.failUnlessAlmostEqual(r['visibility'],params['visibility'],1)
697 self.failUnlessAlmostEqual(r['watertemp'],params['watertemp'],1)
698 self.failUnlessEqual(r['reserved'],params['reserved'])
699
701 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
702 help='decode a "sls_weatherreport" AIS message')
703 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
704 help='encode a "sls_weatherreport" AIS message')
705 parser.add_option('--time_month-field', dest='time_monthField',metavar='uint',type='int'
706 ,help='Field parameter value [default: %default]')
707 parser.add_option('--time_day-field', dest='time_dayField',metavar='uint',type='int'
708 ,help='Field parameter value [default: %default]')
709 parser.add_option('--time_hour-field', dest='time_hourField',metavar='uint',type='int'
710 ,help='Field parameter value [default: %default]')
711 parser.add_option('--time_min-field', dest='time_minField',metavar='uint',type='int'
712 ,help='Field parameter value [default: %default]')
713 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
714 ,help='Field parameter value [default: %default]')
715 parser.add_option('--pos_longitude-field', dest='pos_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
716 ,help='Field parameter value [default: %default]')
717 parser.add_option('--pos_latitude-field', dest='pos_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
718 ,help='Field parameter value [default: %default]')
719 parser.add_option('--speed-field', dest='speedField',default=Decimal('102.3'),metavar='udecimal',type='string'
720 ,help='Field parameter value [default: %default]')
721 parser.add_option('--gust-field', dest='gustField',default=Decimal('102.3'),metavar='udecimal',type='string'
722 ,help='Field parameter value [default: %default]')
723 parser.add_option('--direction-field', dest='directionField',default=511,metavar='uint',type='int'
724 ,help='Field parameter value [default: %default]')
725 parser.add_option('--atmpressure-field', dest='atmpressureField',default=Decimal('16383'),metavar='udecimal',type='string'
726 ,help='Field parameter value [default: %default]')
727 parser.add_option('--airtemp-field', dest='airtempField',default=Decimal('-51.2'),metavar='decimal',type='string'
728 ,help='Field parameter value [default: %default]')
729 parser.add_option('--dewpoint-field', dest='dewpointField',default=Decimal('-51.2'),metavar='decimal',type='string'
730 ,help='Field parameter value [default: %default]')
731 parser.add_option('--visibility-field', dest='visibilityField',default=Decimal('25.5'),metavar='udecimal',type='string'
732 ,help='Field parameter value [default: %default]')
733 parser.add_option('--watertemp-field', dest='watertempField',default=Decimal('-51.2'),metavar='decimal',type='string'
734 ,help='Field parameter value [default: %default]')
735
736
737 if __name__=='__main__':
738
739 from optparse import OptionParser
740 parser = OptionParser(usage="%prog [options]",
741 version="%prog "+__version__)
742
743 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
744 help='run the documentation tests')
745 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
746 help='run the unit tests')
747 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
748 help='Make the test output verbose')
749
750
751
752 typeChoices = ('binary','nmeapayload','nmea')
753 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
754 ,default='nmeapayload'
755 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]')
756
757
758 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
759 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
760 ,default='std'
761 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
762
763 parser.add_option('-o','--output',dest='outputFileName',default=None,
764 help='Name of the python file to write [default: stdout]')
765
766 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
767 choices=fieldList,
768 help='Which fields to include in the output. Currently only for csv output [default: all]')
769
770 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
771 help='Print the field name for csv')
772
773 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
774 help='Print out an sql create command for the table.')
775
776 addMsgOptions(parser)
777
778 (options,args) = parser.parse_args()
779 success=True
780
781 if options.doctest:
782 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
783 sys.argv= [sys.argv[0]]
784 if options.verbose: sys.argv.append('-v')
785 import doctest
786 numfail,numtests=doctest.testmod()
787 if numfail==0: print 'ok'
788 else:
789 print 'FAILED'
790 success=False
791
792 if not success: sys.exit('Something Failed')
793 del success
794
795 if options.unittest:
796 sys.argv = [sys.argv[0]]
797 if options.verbose: sys.argv.append('-v')
798 unittest.main()
799
800 outfile = sys.stdout
801 if None!=options.outputFileName:
802 outfile = file(options.outputFileName,'w')
803
804
805 if options.doEncode:
806
807 if None==options.time_monthField: parser.error("missing value for time_monthField")
808 if None==options.time_dayField: parser.error("missing value for time_dayField")
809 if None==options.time_hourField: parser.error("missing value for time_hourField")
810 if None==options.time_minField: parser.error("missing value for time_minField")
811 if None==options.stationidField: parser.error("missing value for stationidField")
812 if None==options.pos_longitudeField: parser.error("missing value for pos_longitudeField")
813 if None==options.pos_latitudeField: parser.error("missing value for pos_latitudeField")
814 if None==options.speedField: parser.error("missing value for speedField")
815 if None==options.gustField: parser.error("missing value for gustField")
816 if None==options.directionField: parser.error("missing value for directionField")
817 if None==options.atmpressureField: parser.error("missing value for atmpressureField")
818 if None==options.airtempField: parser.error("missing value for airtempField")
819 if None==options.dewpointField: parser.error("missing value for dewpointField")
820 if None==options.visibilityField: parser.error("missing value for visibilityField")
821 if None==options.watertempField: parser.error("missing value for watertempField")
822 msgDict={
823 'time_month': options.time_monthField,
824 'time_day': options.time_dayField,
825 'time_hour': options.time_hourField,
826 'time_min': options.time_minField,
827 'stationid': options.stationidField,
828 'pos_longitude': options.pos_longitudeField,
829 'pos_latitude': options.pos_latitudeField,
830 'speed': options.speedField,
831 'gust': options.gustField,
832 'direction': options.directionField,
833 'atmpressure': options.atmpressureField,
834 'airtemp': options.airtempField,
835 'dewpoint': options.dewpointField,
836 'visibility': options.visibilityField,
837 'watertemp': options.watertempField,
838 'reserved': '0',
839 }
840
841 bits = encode(msgDict)
842 if 'binary'==options.ioType: print str(bits)
843 elif 'nmeapayload'==options.ioType:
844
845 print "bitLen",len(bits)
846 bitLen=len(bits)
847 if bitLen%6!=0:
848 bits = bits + BitVector(size=(6 - (bitLen%6)))
849 print "result:",binary.bitvectoais6(bits)[0]
850
851
852
853 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
854 else: sys.exit('ERROR: unknown ioType. Help!')
855
856
857 if options.sqlCreate:
858 sqlCreateStr(outfile,options.fieldList)
859
860 if options.printCsvfieldList:
861
862 if None == options.fieldList: options.fieldList = fieldList
863 import StringIO
864 buf = StringIO.StringIO()
865 for field in options.fieldList:
866 buf.write(field+',')
867 result = buf.getvalue()
868 if result[-1] == ',': print result[:-1]
869 else: print result
870
871 if options.doDecode:
872 for msg in args:
873 bv = None
874 if 'binary' == options.ioType: bv = BitVector(bitstring=msg)
875 elif 'nmeapayload'== options.ioType: bv = binary.ais6tobitvec(msg)
876 elif 'nmea' == options.ioType: bv = binary.ais6tobitvec(msg.split(',')[5])
877 else: sys.exit('ERROR: unknown ioType. Help!')
878
879 printFields(decode(bv),out=outfile,format=options.outputType,fieldList=options.fieldList)
880