1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-03-31 $'.split()[1]
5 __author__ = 'xmlbinmsg'
6
7 __doc__='''
8
9 Autogenerated python functions to serialize/deserialize binary messages.
10
11 Generated by: ./aisxmlbinmsg2py.py
12
13 Need to then wrap these functions with the outer AIS packet and then
14 convert the whole binary blob to a NMEA string. Those functions are
15 not currently provided in this file.
16
17 serialize: python to ais binary
18 deserialize: ais binary to python
19
20 The generated code uses translators.py, binary.py, and aisstring.py
21 which should be packaged with the resulting files.
22
23
24 @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3
25 @requires: U{BitVector<http://cheeseshop.python.org/pypi/BitVector>}
26
27 @author: '''+__author__+'''
28 @version: ''' + __version__ +'''
29 @var __date__: Date of last svn commit
30 @undocumented: __version__ __author__ __doc__ parser
31 @status: under development
32 @license: Generated code has no license
33 @todo: FIX: put in a description of the message here with fields and types.
34 '''
35
36 import sys
37 from decimal import Decimal
38 from BitVector import BitVector
39
40 import binary, aisstring
41
42
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 'efid',
57 'month',
58 'day',
59 'hour',
60 'min',
61 'sec',
62 'stationid',
63 'longitude',
64 'latitude',
65 'waterlevel',
66 'datum',
67 'sigma',
68 'o',
69 'levelinferred',
70 'flat_tolerance_exceeded',
71 'rate_tolerance_exceeded',
72 'temp_tolerance_exceeded',
73 'expected_height_exceeded',
74 'link_down',
75 'timeLastMeasured',
76 )
77
78 fieldListPostgres = (
79 'MessageID',
80 'RepeatIndicator',
81 'UserID',
82 'Spare',
83 'dac',
84 'fid',
85 'efid',
86 'month',
87 'day',
88 'hour',
89 'min',
90 'sec',
91 'stationid',
92 'stationloc',
93 'waterlevel',
94 'datum',
95 'sigma',
96 'o',
97 'levelinferred',
98 'flat_tolerance_exceeded',
99 'rate_tolerance_exceeded',
100 'temp_tolerance_exceeded',
101 'expected_height_exceeded',
102 'link_down',
103 'timeLastMeasured',
104 )
105
106 toPgFields = {
107 'longitude':'stationloc',
108 'latitude':'stationloc',
109 }
110 '''
111 Go to the Postgis field names from the straight field name
112 '''
113
114 fromPgFields = {
115 'stationloc':('longitude','latitude',),
116 }
117 '''
118 Go from the Postgis field names to the straight field name
119 '''
120
121 pgTypes = {
122 'stationloc':'POINT',
123 }
124 '''
125 Lookup table for each postgis field name to get its type.
126 '''
127
128 -def encode(params, validate=False):
129 '''Create a waterlevel binary message payload to pack into an AIS Msg waterlevel.
130
131 Fields in params:
132 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8")
133 - RepeatIndicator(uint): Indicated how many times a message has been repeated
134 - UserID(uint): Unique ship identification number (MMSI)
135 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
136 - dac(uint): Designated Area Code (field automatically set to "366")
137 - fid(uint): Functional Identifier (field automatically set to "1")
138 - efid(uint): extended functional identifier (field automatically set to "1")
139 - month(uint): Time the measurement represents month 1..12
140 - day(uint): Time the measurement represents day of the month 1..31
141 - hour(uint): Time the measurement represents UTC hours 0..23
142 - min(uint): Time the measurement represents minutes
143 - sec(uint): Time the measurement represents seconds
144 - stationid(aisstr6): Character identifier of the station. Usually a number.
145 - longitude(decimal): Location of the sensor taking the water level measurement or position of prediction. East West location
146 - latitude(decimal): Location of the sensor taking the water level measurement or position of prediction. North South location
147 - waterlevel(int): Water level in centimeters
148 - datum(uint): What reference datum applies to the value
149 - sigma(float): Standard deviation of 1 second samples used to compute the water level height
150 - o(uint): Count of number of samples that fall outside a 3-sigma band about the mean
151 - levelinferred(bool): indicates that the water level value has been inferred
152 - flat_tolerance_exceeded(bool): flat tolerance limit was exceeded. Need better descr
153 - rate_tolerance_exceeded(bool): rate of change tolerance limit was exceeded
154 - temp_tolerance_exceeded(bool): temperature difference tolerance limit was exceeded
155 - expected_height_exceeded(bool): either the maximum or minimum expected water level height limit was exceeded
156 - link_down(bool): Unable to communicate with the tide system. All data invalid
157 - timeLastMeasured(udecimal): Time relative since the timetag that the station actually measured a value.
158 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
159 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
160 @rtype: BitVector
161 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
162 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
163 '''
164
165 bvList = []
166 bvList.append(binary.setBitVectorSize(BitVector(intVal=8),6))
167 if 'RepeatIndicator' in params:
168 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2))
169 else:
170 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
171 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30))
172 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
173 bvList.append(binary.setBitVectorSize(BitVector(intVal=366),10))
174 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),6))
175 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),12))
176 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['month']),4))
177 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['day']),5))
178 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['hour']),5))
179 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['min']),6))
180 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['sec']),6))
181 if 'stationid' in params:
182 bvList.append(aisstring.encode(params['stationid'],42))
183 else:
184 bvList.append(aisstring.encode('@@@@@@@',42))
185 if 'longitude' in params:
186 bvList.append(binary.bvFromSignedInt(int(Decimal(params['longitude'])*Decimal('600000')),28))
187 else:
188 bvList.append(binary.bvFromSignedInt(108600000,28))
189 if 'latitude' in params:
190 bvList.append(binary.bvFromSignedInt(int(Decimal(params['latitude'])*Decimal('600000')),27))
191 else:
192 bvList.append(binary.bvFromSignedInt(54600000,27))
193 if 'waterlevel' in params:
194 bvList.append(binary.bvFromSignedInt(params['waterlevel'],16))
195 else:
196 bvList.append(binary.bvFromSignedInt(-32768,16))
197 if 'datum' in params:
198 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['datum']),5))
199 else:
200 bvList.append(binary.setBitVectorSize(BitVector(intVal=31),5))
201 bvList.append(binary.float2bitvec(params['sigma']))
202 if 'o' in params:
203 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['o']),8))
204 else:
205 bvList.append(binary.setBitVectorSize(BitVector(intVal=255),8))
206 if params["levelinferred"]: bvList.append(TrueBV)
207 else: bvList.append(FalseBV)
208 if params["flat_tolerance_exceeded"]: bvList.append(TrueBV)
209 else: bvList.append(FalseBV)
210 if params["rate_tolerance_exceeded"]: bvList.append(TrueBV)
211 else: bvList.append(FalseBV)
212 if params["temp_tolerance_exceeded"]: bvList.append(TrueBV)
213 else: bvList.append(FalseBV)
214 if params["expected_height_exceeded"]: bvList.append(TrueBV)
215 else: bvList.append(FalseBV)
216 if params["link_down"]: bvList.append(TrueBV)
217 else: bvList.append(FalseBV)
218 if 'timeLastMeasured' in params:
219 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['timeLastMeasured'])*Decimal('10')))),12))
220 else:
221 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(4096)),12))
222
223 return binary.joinBV(bvList)
224
225 -def decode(bv, validate=False):
226 '''Unpack a waterlevel message
227
228 Fields in params:
229 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8")
230 - RepeatIndicator(uint): Indicated how many times a message has been repeated
231 - UserID(uint): Unique ship identification number (MMSI)
232 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
233 - dac(uint): Designated Area Code (field automatically set to "366")
234 - fid(uint): Functional Identifier (field automatically set to "1")
235 - efid(uint): extended functional identifier (field automatically set to "1")
236 - month(uint): Time the measurement represents month 1..12
237 - day(uint): Time the measurement represents day of the month 1..31
238 - hour(uint): Time the measurement represents UTC hours 0..23
239 - min(uint): Time the measurement represents minutes
240 - sec(uint): Time the measurement represents seconds
241 - stationid(aisstr6): Character identifier of the station. Usually a number.
242 - longitude(decimal): Location of the sensor taking the water level measurement or position of prediction. East West location
243 - latitude(decimal): Location of the sensor taking the water level measurement or position of prediction. North South location
244 - waterlevel(int): Water level in centimeters
245 - datum(uint): What reference datum applies to the value
246 - sigma(float): Standard deviation of 1 second samples used to compute the water level height
247 - o(uint): Count of number of samples that fall outside a 3-sigma band about the mean
248 - levelinferred(bool): indicates that the water level value has been inferred
249 - flat_tolerance_exceeded(bool): flat tolerance limit was exceeded. Need better descr
250 - rate_tolerance_exceeded(bool): rate of change tolerance limit was exceeded
251 - temp_tolerance_exceeded(bool): temperature difference tolerance limit was exceeded
252 - expected_height_exceeded(bool): either the maximum or minimum expected water level height limit was exceeded
253 - link_down(bool): Unable to communicate with the tide system. All data invalid
254 - timeLastMeasured(udecimal): Time relative since the timetag that the station actually measured a value.
255 @type bv: BitVector
256 @param bv: Bits defining a message
257 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
258 @rtype: dict
259 @return: params
260 '''
261
262
263
264
265 r = {}
266 r['MessageID']=8
267 r['RepeatIndicator']=int(bv[6:8])
268 r['UserID']=int(bv[8:38])
269 r['Spare']=0
270 r['dac']=366
271 r['fid']=1
272 r['efid']=1
273 r['month']=int(bv[68:72])
274 r['day']=int(bv[72:77])
275 r['hour']=int(bv[77:82])
276 r['min']=int(bv[82:88])
277 r['sec']=int(bv[88:94])
278 r['stationid']=aisstring.decode(bv[94:136])
279 r['longitude']=Decimal(binary.signedIntFromBV(bv[136:164]))/Decimal('600000')
280 r['latitude']=Decimal(binary.signedIntFromBV(bv[164:191]))/Decimal('600000')
281 r['waterlevel']=binary.signedIntFromBV(bv[191:207])
282 r['datum']=int(bv[207:212])
283 r['sigma']=binary.bitvec2float(bv[212:244])
284 r['o']=int(bv[244:252])
285 r['levelinferred']=bool(int(bv[252:253]))
286 r['flat_tolerance_exceeded']=bool(int(bv[253:254]))
287 r['rate_tolerance_exceeded']=bool(int(bv[254:255]))
288 r['temp_tolerance_exceeded']=bool(int(bv[255:256]))
289 r['expected_height_exceeded']=bool(int(bv[256:257]))
290 r['link_down']=bool(int(bv[257:258]))
291 r['timeLastMeasured']=Decimal(int(bv[258:270]))/Decimal('10')
292 return r
293
296
299
302
305
308
311
314
316 return int(bv[68:72])
317
319 return int(bv[72:77])
320
322 return int(bv[77:82])
323
325 return int(bv[82:88])
326
328 return int(bv[88:94])
329
332
335
338
341
343 return int(bv[207:212])
344
347
349 return int(bv[244:252])
350
352 return bool(int(bv[252:253]))
353
355 return bool(int(bv[253:254]))
356
358 return bool(int(bv[254:255]))
359
361 return bool(int(bv[255:256]))
362
364 return bool(int(bv[256:257]))
365
367 return bool(int(bv[257:258]))
368
370 return Decimal(int(bv[258:270]))/Decimal('10')
371
372
374 out.write("<h3>waterlevel<h3>\n")
375 out.write("<table border=\"1\">\n")
376 out.write("<tr bgcolor=\"orange\">\n")
377 out.write("<th align=\"left\">Field Name</th>\n")
378 out.write("<th align=\"left\">Type</th>\n")
379 out.write("<th align=\"left\">Value</th>\n")
380 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
381 out.write("<th align=\"left\">Units</th>\n")
382 out.write("\n")
383 out.write("<tr>\n")
384 out.write("<td>MessageID</td>\n")
385 out.write("<td>uint</td>\n")
386 if 'MessageID' in params:
387 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
388 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
389 out.write("</tr>\n")
390 out.write("\n")
391 out.write("<tr>\n")
392 out.write("<td>RepeatIndicator</td>\n")
393 out.write("<td>uint</td>\n")
394 if 'RepeatIndicator' in params:
395 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n")
396 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut:
397 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>")
398 else:
399 out.write("<td><i>Missing LUT entry</i></td>")
400 out.write("</tr>\n")
401 out.write("\n")
402 out.write("<tr>\n")
403 out.write("<td>UserID</td>\n")
404 out.write("<td>uint</td>\n")
405 if 'UserID' in params:
406 out.write(" <td>"+str(params['UserID'])+"</td>\n")
407 out.write(" <td>"+str(params['UserID'])+"</td>\n")
408 out.write("</tr>\n")
409 out.write("\n")
410 out.write("<tr>\n")
411 out.write("<td>Spare</td>\n")
412 out.write("<td>uint</td>\n")
413 if 'Spare' in params:
414 out.write(" <td>"+str(params['Spare'])+"</td>\n")
415 out.write(" <td>"+str(params['Spare'])+"</td>\n")
416 out.write("</tr>\n")
417 out.write("\n")
418 out.write("<tr>\n")
419 out.write("<td>dac</td>\n")
420 out.write("<td>uint</td>\n")
421 if 'dac' in params:
422 out.write(" <td>"+str(params['dac'])+"</td>\n")
423 out.write(" <td>"+str(params['dac'])+"</td>\n")
424 out.write("</tr>\n")
425 out.write("\n")
426 out.write("<tr>\n")
427 out.write("<td>fid</td>\n")
428 out.write("<td>uint</td>\n")
429 if 'fid' in params:
430 out.write(" <td>"+str(params['fid'])+"</td>\n")
431 out.write(" <td>"+str(params['fid'])+"</td>\n")
432 out.write("</tr>\n")
433 out.write("\n")
434 out.write("<tr>\n")
435 out.write("<td>efid</td>\n")
436 out.write("<td>uint</td>\n")
437 if 'efid' in params:
438 out.write(" <td>"+str(params['efid'])+"</td>\n")
439 out.write(" <td>"+str(params['efid'])+"</td>\n")
440 out.write("</tr>\n")
441 out.write("\n")
442 out.write("<tr>\n")
443 out.write("<td>month</td>\n")
444 out.write("<td>uint</td>\n")
445 if 'month' in params:
446 out.write(" <td>"+str(params['month'])+"</td>\n")
447 out.write(" <td>"+str(params['month'])+"</td>\n")
448 out.write("</tr>\n")
449 out.write("\n")
450 out.write("<tr>\n")
451 out.write("<td>day</td>\n")
452 out.write("<td>uint</td>\n")
453 if 'day' in params:
454 out.write(" <td>"+str(params['day'])+"</td>\n")
455 out.write(" <td>"+str(params['day'])+"</td>\n")
456 out.write("</tr>\n")
457 out.write("\n")
458 out.write("<tr>\n")
459 out.write("<td>hour</td>\n")
460 out.write("<td>uint</td>\n")
461 if 'hour' in params:
462 out.write(" <td>"+str(params['hour'])+"</td>\n")
463 out.write(" <td>"+str(params['hour'])+"</td>\n")
464 out.write("</tr>\n")
465 out.write("\n")
466 out.write("<tr>\n")
467 out.write("<td>min</td>\n")
468 out.write("<td>uint</td>\n")
469 if 'min' in params:
470 out.write(" <td>"+str(params['min'])+"</td>\n")
471 out.write(" <td>"+str(params['min'])+"</td>\n")
472 out.write("</tr>\n")
473 out.write("\n")
474 out.write("<tr>\n")
475 out.write("<td>sec</td>\n")
476 out.write("<td>uint</td>\n")
477 if 'sec' in params:
478 out.write(" <td>"+str(params['sec'])+"</td>\n")
479 out.write(" <td>"+str(params['sec'])+"</td>\n")
480 out.write("</tr>\n")
481 out.write("\n")
482 out.write("<tr>\n")
483 out.write("<td>stationid</td>\n")
484 out.write("<td>aisstr6</td>\n")
485 if 'stationid' in params:
486 out.write(" <td>"+str(params['stationid'])+"</td>\n")
487 out.write(" <td>"+str(params['stationid'])+"</td>\n")
488 out.write("</tr>\n")
489 out.write("\n")
490 out.write("<tr>\n")
491 out.write("<td>longitude</td>\n")
492 out.write("<td>decimal</td>\n")
493 if 'longitude' in params:
494 out.write(" <td>"+str(params['longitude'])+"</td>\n")
495 out.write(" <td>"+str(params['longitude'])+"</td>\n")
496 out.write("<td>degrees</td>\n")
497 out.write("</tr>\n")
498 out.write("\n")
499 out.write("<tr>\n")
500 out.write("<td>latitude</td>\n")
501 out.write("<td>decimal</td>\n")
502 if 'latitude' in params:
503 out.write(" <td>"+str(params['latitude'])+"</td>\n")
504 out.write(" <td>"+str(params['latitude'])+"</td>\n")
505 out.write("<td>degrees</td>\n")
506 out.write("</tr>\n")
507 out.write("\n")
508 out.write("<tr>\n")
509 out.write("<td>waterlevel</td>\n")
510 out.write("<td>int</td>\n")
511 if 'waterlevel' in params:
512 out.write(" <td>"+str(params['waterlevel'])+"</td>\n")
513 out.write(" <td>"+str(params['waterlevel'])+"</td>\n")
514 out.write("<td>cm</td>\n")
515 out.write("</tr>\n")
516 out.write("\n")
517 out.write("<tr>\n")
518 out.write("<td>datum</td>\n")
519 out.write("<td>uint</td>\n")
520 if 'datum' in params:
521 out.write(" <td>"+str(params['datum'])+"</td>\n")
522 if str(params['datum']) in datumDecodeLut:
523 out.write("<td>"+datumDecodeLut[str(params['datum'])]+"</td>")
524 else:
525 out.write("<td><i>Missing LUT entry</i></td>")
526 out.write("</tr>\n")
527 out.write("\n")
528 out.write("<tr>\n")
529 out.write("<td>sigma</td>\n")
530 out.write("<td>float</td>\n")
531 if 'sigma' in params:
532 out.write(" <td>"+str(params['sigma'])+"</td>\n")
533 out.write(" <td>"+str(params['sigma'])+"</td>\n")
534 out.write("<td>m</td>\n")
535 out.write("</tr>\n")
536 out.write("\n")
537 out.write("<tr>\n")
538 out.write("<td>o</td>\n")
539 out.write("<td>uint</td>\n")
540 if 'o' in params:
541 out.write(" <td>"+str(params['o'])+"</td>\n")
542 out.write(" <td>"+str(params['o'])+"</td>\n")
543 out.write("</tr>\n")
544 out.write("\n")
545 out.write("<tr>\n")
546 out.write("<td>levelinferred</td>\n")
547 out.write("<td>bool</td>\n")
548 if 'levelinferred' in params:
549 out.write(" <td>"+str(params['levelinferred'])+"</td>\n")
550 out.write(" <td>"+str(params['levelinferred'])+"</td>\n")
551 out.write("</tr>\n")
552 out.write("\n")
553 out.write("<tr>\n")
554 out.write("<td>flat_tolerance_exceeded</td>\n")
555 out.write("<td>bool</td>\n")
556 if 'flat_tolerance_exceeded' in params:
557 out.write(" <td>"+str(params['flat_tolerance_exceeded'])+"</td>\n")
558 out.write(" <td>"+str(params['flat_tolerance_exceeded'])+"</td>\n")
559 out.write("</tr>\n")
560 out.write("\n")
561 out.write("<tr>\n")
562 out.write("<td>rate_tolerance_exceeded</td>\n")
563 out.write("<td>bool</td>\n")
564 if 'rate_tolerance_exceeded' in params:
565 out.write(" <td>"+str(params['rate_tolerance_exceeded'])+"</td>\n")
566 out.write(" <td>"+str(params['rate_tolerance_exceeded'])+"</td>\n")
567 out.write("</tr>\n")
568 out.write("\n")
569 out.write("<tr>\n")
570 out.write("<td>temp_tolerance_exceeded</td>\n")
571 out.write("<td>bool</td>\n")
572 if 'temp_tolerance_exceeded' in params:
573 out.write(" <td>"+str(params['temp_tolerance_exceeded'])+"</td>\n")
574 out.write(" <td>"+str(params['temp_tolerance_exceeded'])+"</td>\n")
575 out.write("</tr>\n")
576 out.write("\n")
577 out.write("<tr>\n")
578 out.write("<td>expected_height_exceeded</td>\n")
579 out.write("<td>bool</td>\n")
580 if 'expected_height_exceeded' in params:
581 out.write(" <td>"+str(params['expected_height_exceeded'])+"</td>\n")
582 out.write(" <td>"+str(params['expected_height_exceeded'])+"</td>\n")
583 out.write("</tr>\n")
584 out.write("\n")
585 out.write("<tr>\n")
586 out.write("<td>link_down</td>\n")
587 out.write("<td>bool</td>\n")
588 if 'link_down' in params:
589 out.write(" <td>"+str(params['link_down'])+"</td>\n")
590 out.write(" <td>"+str(params['link_down'])+"</td>\n")
591 out.write("</tr>\n")
592 out.write("\n")
593 out.write("<tr>\n")
594 out.write("<td>timeLastMeasured</td>\n")
595 out.write("<td>udecimal</td>\n")
596 if 'timeLastMeasured' in params:
597 out.write(" <td>"+str(params['timeLastMeasured'])+"</td>\n")
598 out.write(" <td>"+str(params['timeLastMeasured'])+"</td>\n")
599 out.write("<td>hours</td>\n")
600 out.write("</tr>\n")
601 out.write("</table>\n")
602
603
605 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
606 out.write("\ <Placemark>\n")
607 out.write("\t <name>"+str(params['stationid'])+"</name>\n")
608 out.write("\t\t<description>\n")
609 import StringIO
610 buf = StringIO.StringIO()
611 printHtml(params,buf)
612 import cgi
613 out.write(cgi.escape(buf.getvalue()))
614 out.write("\t\t</description>\n")
615 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
616 out.write("\t\t<Point>\n")
617 out.write("\t\t\t<coordinates>")
618 out.write(str(params['longitude']))
619 out.write(',')
620 out.write(str(params['latitude']))
621 out.write(",0</coordinates>\n")
622 out.write("\t\t</Point>\n")
623 out.write("\t</Placemark>\n")
624
625 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
626 '''Print a waterlevel message to stdout.
627
628 Fields in params:
629 - MessageID(uint): AIS message number. Must be 8 (field automatically set to "8")
630 - RepeatIndicator(uint): Indicated how many times a message has been repeated
631 - UserID(uint): Unique ship identification number (MMSI)
632 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
633 - dac(uint): Designated Area Code (field automatically set to "366")
634 - fid(uint): Functional Identifier (field automatically set to "1")
635 - efid(uint): extended functional identifier (field automatically set to "1")
636 - month(uint): Time the measurement represents month 1..12
637 - day(uint): Time the measurement represents day of the month 1..31
638 - hour(uint): Time the measurement represents UTC hours 0..23
639 - min(uint): Time the measurement represents minutes
640 - sec(uint): Time the measurement represents seconds
641 - stationid(aisstr6): Character identifier of the station. Usually a number.
642 - longitude(decimal): Location of the sensor taking the water level measurement or position of prediction. East West location
643 - latitude(decimal): Location of the sensor taking the water level measurement or position of prediction. North South location
644 - waterlevel(int): Water level in centimeters
645 - datum(uint): What reference datum applies to the value
646 - sigma(float): Standard deviation of 1 second samples used to compute the water level height
647 - o(uint): Count of number of samples that fall outside a 3-sigma band about the mean
648 - levelinferred(bool): indicates that the water level value has been inferred
649 - flat_tolerance_exceeded(bool): flat tolerance limit was exceeded. Need better descr
650 - rate_tolerance_exceeded(bool): rate of change tolerance limit was exceeded
651 - temp_tolerance_exceeded(bool): temperature difference tolerance limit was exceeded
652 - expected_height_exceeded(bool): either the maximum or minimum expected water level height limit was exceeded
653 - link_down(bool): Unable to communicate with the tide system. All data invalid
654 - timeLastMeasured(udecimal): Time relative since the timetag that the station actually measured a value.
655 @param params: Dictionary of field names/values.
656 @param out: File like object to write to
657 @rtype: stdout
658 @return: text to out
659 '''
660
661 if 'std'==format:
662 out.write("waterlevel:\n")
663 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n")
664 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n")
665 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n")
666 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
667 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n")
668 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n")
669 if 'efid' in params: out.write(" efid: "+str(params['efid'])+"\n")
670 if 'month' in params: out.write(" month: "+str(params['month'])+"\n")
671 if 'day' in params: out.write(" day: "+str(params['day'])+"\n")
672 if 'hour' in params: out.write(" hour: "+str(params['hour'])+"\n")
673 if 'min' in params: out.write(" min: "+str(params['min'])+"\n")
674 if 'sec' in params: out.write(" sec: "+str(params['sec'])+"\n")
675 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n")
676 if 'longitude' in params: out.write(" longitude: "+str(params['longitude'])+"\n")
677 if 'latitude' in params: out.write(" latitude: "+str(params['latitude'])+"\n")
678 if 'waterlevel' in params: out.write(" waterlevel: "+str(params['waterlevel'])+"\n")
679 if 'datum' in params: out.write(" datum: "+str(params['datum'])+"\n")
680 if 'sigma' in params: out.write(" sigma: "+str(params['sigma'])+"\n")
681 if 'o' in params: out.write(" o: "+str(params['o'])+"\n")
682 if 'levelinferred' in params: out.write(" levelinferred: "+str(params['levelinferred'])+"\n")
683 if 'flat_tolerance_exceeded' in params: out.write(" flat_tolerance_exceeded: "+str(params['flat_tolerance_exceeded'])+"\n")
684 if 'rate_tolerance_exceeded' in params: out.write(" rate_tolerance_exceeded: "+str(params['rate_tolerance_exceeded'])+"\n")
685 if 'temp_tolerance_exceeded' in params: out.write(" temp_tolerance_exceeded: "+str(params['temp_tolerance_exceeded'])+"\n")
686 if 'expected_height_exceeded' in params: out.write(" expected_height_exceeded: "+str(params['expected_height_exceeded'])+"\n")
687 if 'link_down' in params: out.write(" link_down: "+str(params['link_down'])+"\n")
688 if 'timeLastMeasured' in params: out.write(" timeLastMeasured: "+str(params['timeLastMeasured'])+"\n")
689 elif 'csv'==format:
690 if None == options.fieldList:
691 options.fieldList = fieldList
692 needComma = False;
693 for field in fieldList:
694 if needComma: out.write(',')
695 needComma = True
696 if field in params:
697 out.write(str(params[field]))
698
699 out.write("\n")
700 elif 'html'==format:
701 printHtml(params,out)
702 elif 'sql'==format:
703 sqlInsertStr(params,out,dbType=dbType)
704 elif 'kml'==format:
705 printKml(params,out)
706 elif 'kml-full'==format:
707 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
708 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
709 out.write("<Document>\n")
710 out.write(" <name>waterlevel</name>\n")
711 printKml(params,out)
712 out.write("</Document>\n")
713 out.write("</kml>\n")
714 else:
715 print "ERROR: unknown format:",format
716 assert False
717
718 return
719
720 RepeatIndicatorEncodeLut = {
721 'default':'0',
722 'do not repeat any more':'3',
723 }
724
725 RepeatIndicatorDecodeLut = {
726 '0':'default',
727 '3':'do not repeat any more',
728 }
729
730 datumEncodeLut = {
731 'MLLW':'0',
732 'IGLD-85':'1',
733 'WaterDepth':'2',
734 'STND':'3',
735 'MHW':'4',
736 'MLS':'5',
737 'NGVD':'6',
738 'NAVD':'7',
739 'WGS-84':'8',
740 'LAT':'9',
741 }
742
743 datumDecodeLut = {
744 '0':'MLLW',
745 '1':'IGLD-85',
746 '2':'WaterDepth',
747 '3':'STND',
748 '4':'MHW',
749 '5':'MLS',
750 '6':'NGVD',
751 '7':'NAVD',
752 '8':'WGS-84',
753 '9':'LAT',
754 }
755
756
757
758
759
760 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
761 ,addCoastGuardFields=True
762 ,dbType='postgres'
763 ):
764 '''
765 Return the SQL CREATE command for this message type
766 @param outfile: file like object to print to.
767 @param fields: which fields to put in the create. Defaults to all.
768 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
769 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
770 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
771 @type addCoastGuardFields: bool
772 @return: sql create string
773 @rtype: str
774
775 @see: sqlCreate
776 '''
777
778 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
779
780 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
781 '''
782 Return the sqlhelp object to create the table.
783
784 @param fields: which fields to put in the create. Defaults to all.
785 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
786 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
787 @type addCoastGuardFields: bool
788 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
789 @return: An object that can be used to generate a return
790 @rtype: sqlhelp.create
791 '''
792 if None == fields: fields = fieldList
793 import sqlhelp
794 c = sqlhelp.create('waterlevel',dbType=dbType)
795 c.addPrimaryKey()
796 if 'MessageID' in fields: c.addInt ('MessageID')
797 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator')
798 if 'UserID' in fields: c.addInt ('UserID')
799 if 'Spare' in fields: c.addInt ('Spare')
800 if 'dac' in fields: c.addInt ('dac')
801 if 'fid' in fields: c.addInt ('fid')
802 if 'efid' in fields: c.addInt ('efid')
803 if 'month' in fields: c.addInt ('month')
804 if 'day' in fields: c.addInt ('day')
805 if 'hour' in fields: c.addInt ('hour')
806 if 'min' in fields: c.addInt ('min')
807 if 'sec' in fields: c.addInt ('sec')
808 if 'stationid' in fields: c.addVarChar('stationid',7)
809 if dbType != 'postgres':
810 if 'longitude' in fields: c.addDecimal('longitude',8,5)
811 if dbType != 'postgres':
812 if 'latitude' in fields: c.addDecimal('latitude',8,5)
813 if 'waterlevel' in fields: c.addInt ('waterlevel')
814 if 'datum' in fields: c.addInt ('datum')
815 if 'sigma' in fields: c.addReal('sigma')
816 if 'o' in fields: c.addInt ('o')
817 if 'levelinferred' in fields: c.addBool('levelinferred')
818 if 'flat_tolerance_exceeded' in fields: c.addBool('flat_tolerance_exceeded')
819 if 'rate_tolerance_exceeded' in fields: c.addBool('rate_tolerance_exceeded')
820 if 'temp_tolerance_exceeded' in fields: c.addBool('temp_tolerance_exceeded')
821 if 'expected_height_exceeded' in fields: c.addBool('expected_height_exceeded')
822 if 'link_down' in fields: c.addBool('link_down')
823 if 'timeLastMeasured' in fields: c.addDecimal('timeLastMeasured',4,1)
824
825 if addCoastGuardFields:
826
827
828
829
830
831 c.addVarChar('cg_r',15)
832 c.addInt('cg_sec')
833
834 c.addTimestamp('cg_timestamp')
835
836 if dbType == 'postgres':
837 c.addPostGIS('stationloc','POINT',2);
838
839 return c
840
841 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
842 '''
843 Return the SQL INSERT command for this message type
844 @param params: dictionary of values keyed by field name
845 @param outfile: file like object to print to.
846 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
847 @return: sql create string
848 @rtype: str
849
850 @see: sqlCreate
851 '''
852 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
853
854
855 -def sqlInsert(params,extraParams=None,dbType='postgres'):
856 '''
857 Give the SQL INSERT statement
858 @param params: dict keyed by field name of values
859 @param extraParams: any extra fields that you have created beyond the normal ais message fields
860 @rtype: sqlhelp.insert
861 @return: insert class instance
862 @todo: allow optional type checking of params?
863 @warning: this will take invalid keys happily and do what???
864 '''
865 import sqlhelp
866 i = sqlhelp.insert('waterlevel',dbType=dbType)
867
868 if dbType=='postgres':
869 finished = []
870 for key in params:
871 if key in finished:
872 continue
873
874 if key not in toPgFields and key not in fromPgFields:
875 if type(params[key])==Decimal: i.add(key,float(params[key]))
876 else: i.add(key,params[key])
877 else:
878 if key in fromPgFields:
879 val = params[key]
880
881 i.addPostGIS(key,val)
882 finished.append(key)
883 else:
884
885 pgName = toPgFields[key]
886
887 valStr=pgTypes[pgName]+'('
888 vals = []
889 for nonPgKey in fromPgFields[pgName]:
890 vals.append(str(params[nonPgKey]))
891 finished.append(nonPgKey)
892 valStr+=' '.join(vals)+')'
893 i.addPostGIS(pgName,valStr)
894 else:
895 for key in params:
896 if type(params[key])==Decimal: i.add(key,float(params[key]))
897 else: i.add(key,params[key])
898
899 if None != extraParams:
900 for key in extraParams:
901 i.add(key,extraParams[key])
902
903 return i
904
905
906
907
908
911 '''
912 Return the LaTeX definition table for this message type
913 @param outfile: file like object to print to.
914 @type outfile: file obj
915 @return: LaTeX table string via the outfile
916 @rtype: str
917
918 '''
919 o = outfile
920
921 o.write('''
922 \\begin{table}%[htb]
923 \\centering
924 \\begin{tabular}{|l|c|l|}
925 \\hline
926 Parameter & Number of bits & Description
927 \\\\ \\hline\\hline
928 MessageID & 6 & AIS message number. Must be 8 \\\\ \hline
929 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline
930 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline
931 Spare & 2 & Reserved for definition by a regional authority. \\\\ \hline
932 dac & 10 & Designated Area Code \\\\ \hline
933 fid & 6 & Functional Identifier \\\\ \hline
934 efid & 12 & extended functional identifier \\\\ \hline
935 month & 4 & Time the measurement represents month 1..12 \\\\ \hline
936 day & 5 & Time the measurement represents day of the month 1..31 \\\\ \hline
937 hour & 5 & Time the measurement represents UTC hours 0..23 \\\\ \hline
938 min & 6 & Time the measurement represents minutes \\\\ \hline
939 sec & 6 & Time the measurement represents seconds \\\\ \hline
940 stationid & 42 & Character identifier of the station. Usually a number. \\\\ \hline
941 longitude & 28 & Location of the sensor taking the water level measurement or position of prediction. East West location \\\\ \hline
942 latitude & 27 & Location of the sensor taking the water level measurement or position of prediction. North South location \\\\ \hline
943 waterlevel & 16 & Water level in centimeters \\\\ \hline
944 datum & 5 & What reference datum applies to the value \\\\ \hline
945 sigma & 32 & Standard deviation of 1 second samples used to compute the water level height \\\\ \hline
946 o & 8 & Count of number of samples that fall outside a 3-sigma band about the mean \\\\ \hline
947 levelinferred & 1 & indicates that the water level value has been inferred \\\\ \hline
948 flat\_tolerance\_exceeded & 1 & flat tolerance limit was exceeded. Need better descr \\\\ \hline
949 rate\_tolerance\_exceeded & 1 & rate of change tolerance limit was exceeded \\\\ \hline
950 temp\_tolerance\_exceeded & 1 & temperature difference tolerance limit was exceeded \\\\ \hline
951 expected\_height\_exceeded & 1 & either the maximum or minimum expected water level height limit was exceeded \\\\ \hline
952 link\_down & 1 & Unable to communicate with the tide system. All data invalid \\\\ \hline
953 timeLastMeasured & 12 & Time relative since the timetag that the station actually measured a value.\\\\ \\hline \\hline
954 Total bits & 270 & Appears to take 2 slots with 154 pad bits to fill the last slot \\\\ \\hline
955 \\end{tabular}
956 \\caption{AIS message number 8: Water level report. In this case from the NOAA Co-Ops 6 minute raw data. This is }
957 \\label{tab:waterlevel}
958 \\end{table}
959 ''')
960
961
962
963
964
965 import unittest
967 '''Return a params file base on the testvalue tags.
968 @rtype: dict
969 @return: params based on testvalue tags
970 '''
971 params = {}
972 params['MessageID'] = 8
973 params['RepeatIndicator'] = 1
974 params['UserID'] = 1193046
975 params['Spare'] = 0
976 params['dac'] = 366
977 params['fid'] = 1
978 params['efid'] = 1
979 params['month'] = 2
980 params['day'] = 28
981 params['hour'] = 23
982 params['min'] = 45
983 params['sec'] = 58
984 params['stationid'] = 'A234567'
985 params['longitude'] = Decimal('-122.16328055555556')
986 params['latitude'] = Decimal('37.424458333333334')
987 params['waterlevel'] = -97
988 params['datum'] = 0
989 params['sigma'] = -1.234
990 params['o'] = 240
991 params['levelinferred'] = False
992 params['flat_tolerance_exceeded'] = True
993 params['rate_tolerance_exceeded'] = False
994 params['temp_tolerance_exceeded'] = False
995 params['expected_height_exceeded'] = True
996 params['link_down'] = False
997 params['timeLastMeasured'] = Decimal('0')
998
999 return params
1000
1002 '''Use testvalue tag text from each type to build test case the waterlevel message'''
1004
1005 params = testParams()
1006 bits = encode(params)
1007 r = decode(bits)
1008
1009
1010 self.failUnlessEqual(r['MessageID'],params['MessageID'])
1011 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
1012 self.failUnlessEqual(r['UserID'],params['UserID'])
1013 self.failUnlessEqual(r['Spare'],params['Spare'])
1014 self.failUnlessEqual(r['dac'],params['dac'])
1015 self.failUnlessEqual(r['fid'],params['fid'])
1016 self.failUnlessEqual(r['efid'],params['efid'])
1017 self.failUnlessEqual(r['month'],params['month'])
1018 self.failUnlessEqual(r['day'],params['day'])
1019 self.failUnlessEqual(r['hour'],params['hour'])
1020 self.failUnlessEqual(r['min'],params['min'])
1021 self.failUnlessEqual(r['sec'],params['sec'])
1022 self.failUnlessEqual(r['stationid'],params['stationid'])
1023 self.failUnlessAlmostEqual(r['longitude'],params['longitude'],5)
1024 self.failUnlessAlmostEqual(r['latitude'],params['latitude'],5)
1025 self.failUnlessEqual(r['waterlevel'],params['waterlevel'])
1026 self.failUnlessEqual(r['datum'],params['datum'])
1027 self.failUnlessAlmostEqual(r['sigma'],params['sigma'],3)
1028 self.failUnlessEqual(r['o'],params['o'])
1029 self.failUnlessEqual(r['levelinferred'],params['levelinferred'])
1030 self.failUnlessEqual(r['flat_tolerance_exceeded'],params['flat_tolerance_exceeded'])
1031 self.failUnlessEqual(r['rate_tolerance_exceeded'],params['rate_tolerance_exceeded'])
1032 self.failUnlessEqual(r['temp_tolerance_exceeded'],params['temp_tolerance_exceeded'])
1033 self.failUnlessEqual(r['expected_height_exceeded'],params['expected_height_exceeded'])
1034 self.failUnlessEqual(r['link_down'],params['link_down'])
1035 self.failUnlessAlmostEqual(r['timeLastMeasured'],params['timeLastMeasured'],1)
1036
1038 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
1039 help='decode a "waterlevel" AIS message')
1040 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
1041 help='encode a "waterlevel" AIS message')
1042 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
1043 ,help='Field parameter value [default: %default]')
1044 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
1045 ,help='Field parameter value [default: %default]')
1046 parser.add_option('--month-field', dest='monthField',metavar='uint',type='int'
1047 ,help='Field parameter value [default: %default]')
1048 parser.add_option('--day-field', dest='dayField',metavar='uint',type='int'
1049 ,help='Field parameter value [default: %default]')
1050 parser.add_option('--hour-field', dest='hourField',metavar='uint',type='int'
1051 ,help='Field parameter value [default: %default]')
1052 parser.add_option('--min-field', dest='minField',metavar='uint',type='int'
1053 ,help='Field parameter value [default: %default]')
1054 parser.add_option('--sec-field', dest='secField',metavar='uint',type='int'
1055 ,help='Field parameter value [default: %default]')
1056 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
1057 ,help='Field parameter value [default: %default]')
1058 parser.add_option('--longitude-field', dest='longitudeField',default=Decimal('181'),metavar='decimal',type='string'
1059 ,help='Field parameter value [default: %default]')
1060 parser.add_option('--latitude-field', dest='latitudeField',default=Decimal('91'),metavar='decimal',type='string'
1061 ,help='Field parameter value [default: %default]')
1062 parser.add_option('--waterlevel-field', dest='waterlevelField',default=-32768,metavar='int',type='int'
1063 ,help='Field parameter value [default: %default]')
1064 parser.add_option('--datum-field', dest='datumField',default=31,metavar='uint',type='int'
1065 ,help='Field parameter value [default: %default]')
1066 parser.add_option('--sigma-field', dest='sigmaField',metavar='float',type='float'
1067 ,help='Field parameter value [default: %default]')
1068 parser.add_option('--o-field', dest='oField',default=255,metavar='uint',type='int'
1069 ,help='Field parameter value [default: %default]')
1070 parser.add_option('--levelinferred-field', dest='levelinferredField',metavar='bool',type='int'
1071 ,help='Field parameter value [default: %default]')
1072 parser.add_option('--flat_tolerance_exceeded-field', dest='flat_tolerance_exceededField',metavar='bool',type='int'
1073 ,help='Field parameter value [default: %default]')
1074 parser.add_option('--rate_tolerance_exceeded-field', dest='rate_tolerance_exceededField',metavar='bool',type='int'
1075 ,help='Field parameter value [default: %default]')
1076 parser.add_option('--temp_tolerance_exceeded-field', dest='temp_tolerance_exceededField',metavar='bool',type='int'
1077 ,help='Field parameter value [default: %default]')
1078 parser.add_option('--expected_height_exceeded-field', dest='expected_height_exceededField',metavar='bool',type='int'
1079 ,help='Field parameter value [default: %default]')
1080 parser.add_option('--link_down-field', dest='link_downField',metavar='bool',type='int'
1081 ,help='Field parameter value [default: %default]')
1082 parser.add_option('--timeLastMeasured-field', dest='timeLastMeasuredField',default=Decimal('409.6'),metavar='udecimal',type='string'
1083 ,help='Field parameter value [default: %default]')
1084
1085
1086 if __name__=='__main__':
1087
1088 from optparse import OptionParser
1089 parser = OptionParser(usage="%prog [options]",
1090 version="%prog "+__version__)
1091
1092 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
1093 help='run the documentation tests')
1094 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
1095 help='run the unit tests')
1096 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
1097 help='Make the test output verbose')
1098
1099
1100
1101 typeChoices = ('binary','nmeapayload','nmea')
1102 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
1103 ,default='nmeapayload'
1104 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
1105
1106
1107 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
1108 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
1109 ,default='std'
1110 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
1111
1112 parser.add_option('-o','--output',dest='outputFileName',default=None,
1113 help='Name of the python file to write [default: stdout]')
1114
1115 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
1116 choices=fieldList,
1117 help='Which fields to include in the output. Currently only for csv output [default: all]')
1118
1119 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
1120 help='Print the field name for csv')
1121
1122 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
1123 help='Print out an sql create command for the table.')
1124
1125 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
1126 help='Print a LaTeX table of the type')
1127
1128 dbChoices = ('sqlite','postgres')
1129 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
1130 ,choices=dbChoices,type='choice'
1131 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
1132
1133 addMsgOptions(parser)
1134
1135 (options,args) = parser.parse_args()
1136 success=True
1137
1138 if options.doctest:
1139 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
1140 sys.argv= [sys.argv[0]]
1141 if options.verbose: sys.argv.append('-v')
1142 import doctest
1143 numfail,numtests=doctest.testmod()
1144 if numfail==0: print 'ok'
1145 else:
1146 print 'FAILED'
1147 success=False
1148
1149 if not success: sys.exit('Something Failed')
1150 del success
1151
1152 if options.unittest:
1153 sys.argv = [sys.argv[0]]
1154 if options.verbose: sys.argv.append('-v')
1155 unittest.main()
1156
1157 outfile = sys.stdout
1158 if None!=options.outputFileName:
1159 outfile = file(options.outputFileName,'w')
1160
1161
1162 if options.doEncode:
1163
1164 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
1165 if None==options.UserIDField: parser.error("missing value for UserIDField")
1166 if None==options.monthField: parser.error("missing value for monthField")
1167 if None==options.dayField: parser.error("missing value for dayField")
1168 if None==options.hourField: parser.error("missing value for hourField")
1169 if None==options.minField: parser.error("missing value for minField")
1170 if None==options.secField: parser.error("missing value for secField")
1171 if None==options.stationidField: parser.error("missing value for stationidField")
1172 if None==options.longitudeField: parser.error("missing value for longitudeField")
1173 if None==options.latitudeField: parser.error("missing value for latitudeField")
1174 if None==options.waterlevelField: parser.error("missing value for waterlevelField")
1175 if None==options.datumField: parser.error("missing value for datumField")
1176 if None==options.sigmaField: parser.error("missing value for sigmaField")
1177 if None==options.oField: parser.error("missing value for oField")
1178 if None==options.levelinferredField: parser.error("missing value for levelinferredField")
1179 if None==options.flat_tolerance_exceededField: parser.error("missing value for flat_tolerance_exceededField")
1180 if None==options.rate_tolerance_exceededField: parser.error("missing value for rate_tolerance_exceededField")
1181 if None==options.temp_tolerance_exceededField: parser.error("missing value for temp_tolerance_exceededField")
1182 if None==options.expected_height_exceededField: parser.error("missing value for expected_height_exceededField")
1183 if None==options.link_downField: parser.error("missing value for link_downField")
1184 if None==options.timeLastMeasuredField: parser.error("missing value for timeLastMeasuredField")
1185 msgDict={
1186 'MessageID': '8',
1187 'RepeatIndicator': options.RepeatIndicatorField,
1188 'UserID': options.UserIDField,
1189 'Spare': '0',
1190 'dac': '366',
1191 'fid': '1',
1192 'efid': '1',
1193 'month': options.monthField,
1194 'day': options.dayField,
1195 'hour': options.hourField,
1196 'min': options.minField,
1197 'sec': options.secField,
1198 'stationid': options.stationidField,
1199 'longitude': options.longitudeField,
1200 'latitude': options.latitudeField,
1201 'waterlevel': options.waterlevelField,
1202 'datum': options.datumField,
1203 'sigma': options.sigmaField,
1204 'o': options.oField,
1205 'levelinferred': options.levelinferredField,
1206 'flat_tolerance_exceeded': options.flat_tolerance_exceededField,
1207 'rate_tolerance_exceeded': options.rate_tolerance_exceededField,
1208 'temp_tolerance_exceeded': options.temp_tolerance_exceededField,
1209 'expected_height_exceeded': options.expected_height_exceededField,
1210 'link_down': options.link_downField,
1211 'timeLastMeasured': options.timeLastMeasuredField,
1212 }
1213
1214 bits = encode(msgDict)
1215 if 'binary'==options.ioType: print str(bits)
1216 elif 'nmeapayload'==options.ioType:
1217
1218 print "bitLen",len(bits)
1219 bitLen=len(bits)
1220 if bitLen%6!=0:
1221 bits = bits + BitVector(size=(6 - (bitLen%6)))
1222 print "result:",binary.bitvectoais6(bits)[0]
1223
1224
1225
1226 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
1227 else: sys.exit('ERROR: unknown ioType. Help!')
1228
1229
1230 if options.sqlCreate:
1231 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
1232
1233 if options.latexDefinitionTable:
1234 latexDefinitionTable(outfile)
1235
1236 if options.printCsvfieldList:
1237
1238 if None == options.fieldList: options.fieldList = fieldList
1239 import StringIO
1240 buf = StringIO.StringIO()
1241 for field in options.fieldList:
1242 buf.write(field+',')
1243 result = buf.getvalue()
1244 if result[-1] == ',': print result[:-1]
1245 else: print result
1246
1247 if options.doDecode:
1248 for msg in args:
1249 bv = None
1250
1251 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
1252
1253
1254 bv = binary.ais6tobitvec(msg.split(',')[5])
1255 else:
1256
1257 binaryMsg=True
1258 for c in msg:
1259 if c not in ('0','1'):
1260 binaryMsg=False
1261 break
1262 if binaryMsg:
1263 bv = BitVector(bitstring=msg)
1264 else:
1265 bv = binary.ais6tobitvec(msg)
1266
1267 printFields(decode(bv)
1268 ,out=outfile
1269 ,format=options.outputType
1270 ,fieldList=options.fieldList
1271 ,dbType=options.dbType
1272 )
1273