1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2008-01-11 $'.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 'time_month',
51 'time_day',
52 'time_hour',
53 'time_min',
54 'stationid',
55 'pos_longitude',
56 'pos_latitude',
57 'flow',
58 'reserved',
59 )
60
61 fieldListPostgres = (
62 'time_month',
63 'time_day',
64 'time_hour',
65 'time_min',
66 'stationid',
67 'pos',
68 'flow',
69 'reserved',
70 )
71
72 toPgFields = {
73 'pos_longitude':'pos',
74 'pos_latitude':'pos',
75 }
76 '''
77 Go to the Postgis field names from the straight field name
78 '''
79
80 fromPgFields = {
81 'pos':('pos_longitude','pos_latitude',),
82 }
83 '''
84 Go from the Postgis field names to the straight field name
85 '''
86
87 pgTypes = {
88 'pos':'POINT',
89 }
90 '''
91 Lookup table for each postgis field name to get its type.
92 '''
93
94 -def encode(params, validate=False):
95 '''Create a sls_wind binary message payload to pack into an AIS Msg sls_wind.
96
97 Fields in params:
98 - time_month(uint): Time tag of measurement month 1..12
99 - time_day(uint): Time tag of measurement day of the month 1..31
100 - time_hour(uint): Time tag of measurement UTC hours 0..23
101 - time_min(uint): Time tag of measurement minutes
102 - stationid(aisstr6): Character identifier of the station
103 - pos_longitude(decimal): Location of measurement East West location
104 - pos_latitude(decimal): Location of measurement North South location
105 - flow(uint): Water flow
106 - reserved(uint): Reserved bits for future use (field automatically set to "0")
107 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
108 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
109 @rtype: BitVector
110 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
111 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
112 '''
113
114 bvList = []
115 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_month']),4))
116 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_day']),5))
117 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_hour']),5))
118 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_min']),6))
119 if 'stationid' in params:
120 bvList.append(aisstring.encode(params['stationid'],42))
121 else:
122 bvList.append(aisstring.encode('@@@@@@@',42))
123 if 'pos_longitude' in params:
124 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_longitude'])*Decimal('60000')),25))
125 else:
126 bvList.append(binary.bvFromSignedInt(10860000,25))
127 if 'pos_latitude' in params:
128 bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_latitude'])*Decimal('60000')),24))
129 else:
130 bvList.append(binary.bvFromSignedInt(5460000,24))
131 if 'flow' in params:
132 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['flow']),10))
133 else:
134 bvList.append(binary.setBitVectorSize(BitVector(intVal=16383),10))
135 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),19))
136
137 return binary.joinBV(bvList)
138
139 -def decode(bv, validate=False):
140 '''Unpack a sls_wind message
141
142 Fields in params:
143 - time_month(uint): Time tag of measurement month 1..12
144 - time_day(uint): Time tag of measurement day of the month 1..31
145 - time_hour(uint): Time tag of measurement UTC hours 0..23
146 - time_min(uint): Time tag of measurement minutes
147 - stationid(aisstr6): Character identifier of the station
148 - pos_longitude(decimal): Location of measurement East West location
149 - pos_latitude(decimal): Location of measurement North South location
150 - flow(uint): Water flow
151 - reserved(uint): Reserved bits for future use (field automatically set to "0")
152 @type bv: BitVector
153 @param bv: Bits defining a message
154 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
155 @rtype: dict
156 @return: params
157 '''
158
159
160
161
162 r = {}
163 r['time_month']=int(bv[0:4])
164 r['time_day']=int(bv[4:9])
165 r['time_hour']=int(bv[9:14])
166 r['time_min']=int(bv[14:20])
167 r['stationid']=aisstring.decode(bv[20:62])
168 r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
169 r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
170 r['flow']=int(bv[111:121])
171 r['reserved']=0
172 return r
173
176
179
182
184 return int(bv[14:20])
185
188
191
194
196 return int(bv[111:121])
197
200
201
203 out.write("<h3>sls_wind</h3>\n")
204 out.write("<table border=\"1\">\n")
205 out.write("<tr bgcolor=\"orange\">\n")
206 out.write("<th align=\"left\">Field Name</th>\n")
207 out.write("<th align=\"left\">Type</th>\n")
208 out.write("<th align=\"left\">Value</th>\n")
209 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
210 out.write("<th align=\"left\">Units</th>\n")
211 out.write("\n")
212 out.write("<tr>\n")
213 out.write("<td>time_month</td>\n")
214 out.write("<td>uint</td>\n")
215 if 'time_month' in params:
216 out.write(" <td>"+str(params['time_month'])+"</td>\n")
217 out.write(" <td>"+str(params['time_month'])+"</td>\n")
218 out.write("</tr>\n")
219 out.write("\n")
220 out.write("<tr>\n")
221 out.write("<td>time_day</td>\n")
222 out.write("<td>uint</td>\n")
223 if 'time_day' in params:
224 out.write(" <td>"+str(params['time_day'])+"</td>\n")
225 out.write(" <td>"+str(params['time_day'])+"</td>\n")
226 out.write("</tr>\n")
227 out.write("\n")
228 out.write("<tr>\n")
229 out.write("<td>time_hour</td>\n")
230 out.write("<td>uint</td>\n")
231 if 'time_hour' in params:
232 out.write(" <td>"+str(params['time_hour'])+"</td>\n")
233 out.write(" <td>"+str(params['time_hour'])+"</td>\n")
234 out.write("</tr>\n")
235 out.write("\n")
236 out.write("<tr>\n")
237 out.write("<td>time_min</td>\n")
238 out.write("<td>uint</td>\n")
239 if 'time_min' in params:
240 out.write(" <td>"+str(params['time_min'])+"</td>\n")
241 out.write(" <td>"+str(params['time_min'])+"</td>\n")
242 out.write("</tr>\n")
243 out.write("\n")
244 out.write("<tr>\n")
245 out.write("<td>stationid</td>\n")
246 out.write("<td>aisstr6</td>\n")
247 if 'stationid' in params:
248 out.write(" <td>"+str(params['stationid'])+"</td>\n")
249 out.write(" <td>"+str(params['stationid'])+"</td>\n")
250 out.write("</tr>\n")
251 out.write("\n")
252 out.write("<tr>\n")
253 out.write("<td>pos_longitude</td>\n")
254 out.write("<td>decimal</td>\n")
255 if 'pos_longitude' in params:
256 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n")
257 out.write(" <td>"+str(params['pos_longitude'])+"</td>\n")
258 out.write("<td>degrees</td>\n")
259 out.write("</tr>\n")
260 out.write("\n")
261 out.write("<tr>\n")
262 out.write("<td>pos_latitude</td>\n")
263 out.write("<td>decimal</td>\n")
264 if 'pos_latitude' in params:
265 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n")
266 out.write(" <td>"+str(params['pos_latitude'])+"</td>\n")
267 out.write("<td>degrees</td>\n")
268 out.write("</tr>\n")
269 out.write("\n")
270 out.write("<tr>\n")
271 out.write("<td>flow</td>\n")
272 out.write("<td>uint</td>\n")
273 if 'flow' in params:
274 out.write(" <td>"+str(params['flow'])+"</td>\n")
275 out.write(" <td>"+str(params['flow'])+"</td>\n")
276 out.write("<td>m^3/s</td>\n")
277 out.write("</tr>\n")
278 out.write("\n")
279 out.write("<tr>\n")
280 out.write("<td>reserved</td>\n")
281 out.write("<td>uint</td>\n")
282 if 'reserved' in params:
283 out.write(" <td>"+str(params['reserved'])+"</td>\n")
284 out.write(" <td>"+str(params['reserved'])+"</td>\n")
285 out.write("</tr>\n")
286 out.write("</table>\n")
287
288
290 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
291 out.write("\ <Placemark>\n")
292 out.write("\t <name>"+str(params['stationid'])+"</name>\n")
293 out.write("\t\t<description>\n")
294 import StringIO
295 buf = StringIO.StringIO()
296 printHtml(params,buf)
297 import cgi
298 out.write(cgi.escape(buf.getvalue()))
299 out.write("\t\t</description>\n")
300 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
301 out.write("\t\t<Point>\n")
302 out.write("\t\t\t<coordinates>")
303 out.write(str(params['pos_longitude']))
304 out.write(',')
305 out.write(str(params['pos_latitude']))
306 out.write(",0</coordinates>\n")
307 out.write("\t\t</Point>\n")
308 out.write("\t</Placemark>\n")
309
310 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
311 '''Print a sls_wind message to stdout.
312
313 Fields in params:
314 - time_month(uint): Time tag of measurement month 1..12
315 - time_day(uint): Time tag of measurement day of the month 1..31
316 - time_hour(uint): Time tag of measurement UTC hours 0..23
317 - time_min(uint): Time tag of measurement minutes
318 - stationid(aisstr6): Character identifier of the station
319 - pos_longitude(decimal): Location of measurement East West location
320 - pos_latitude(decimal): Location of measurement North South location
321 - flow(uint): Water flow
322 - reserved(uint): Reserved bits for future use (field automatically set to "0")
323 @param params: Dictionary of field names/values.
324 @param out: File like object to write to
325 @rtype: stdout
326 @return: text to out
327 '''
328
329 if 'std'==format:
330 out.write("sls_wind:\n")
331 if 'time_month' in params: out.write(" time_month: "+str(params['time_month'])+"\n")
332 if 'time_day' in params: out.write(" time_day: "+str(params['time_day'])+"\n")
333 if 'time_hour' in params: out.write(" time_hour: "+str(params['time_hour'])+"\n")
334 if 'time_min' in params: out.write(" time_min: "+str(params['time_min'])+"\n")
335 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n")
336 if 'pos_longitude' in params: out.write(" pos_longitude: "+str(params['pos_longitude'])+"\n")
337 if 'pos_latitude' in params: out.write(" pos_latitude: "+str(params['pos_latitude'])+"\n")
338 if 'flow' in params: out.write(" flow: "+str(params['flow'])+"\n")
339 if 'reserved' in params: out.write(" reserved: "+str(params['reserved'])+"\n")
340 elif 'csv'==format:
341 if None == options.fieldList:
342 options.fieldList = fieldList
343 needComma = False;
344 for field in fieldList:
345 if needComma: out.write(',')
346 needComma = True
347 if field in params:
348 out.write(str(params[field]))
349
350 out.write("\n")
351 elif 'html'==format:
352 printHtml(params,out)
353 elif 'sql'==format:
354 sqlInsertStr(params,out,dbType=dbType)
355 elif 'kml'==format:
356 printKml(params,out)
357 elif 'kml-full'==format:
358 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
359 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
360 out.write("<Document>\n")
361 out.write(" <name>sls_wind</name>\n")
362 printKml(params,out)
363 out.write("</Document>\n")
364 out.write("</kml>\n")
365 else:
366 print "ERROR: unknown format:",format
367 assert False
368
369 return
370
371
372
373
374
375 dbTableName='sls_wind'
376 'Database table name'
377
378 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
379 ,addCoastGuardFields=True
380 ,dbType='postgres'
381 ):
382 '''
383 Return the SQL CREATE command for this message type
384 @param outfile: file like object to print to.
385 @param fields: which fields to put in the create. Defaults to all.
386 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
387 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
388 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
389 @type addCoastGuardFields: bool
390 @return: sql create string
391 @rtype: str
392
393 @see: sqlCreate
394 '''
395
396 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
397
398 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
399 '''
400 Return the sqlhelp object to create the table.
401
402 @param fields: which fields to put in the create. Defaults to all.
403 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
404 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
405 @type addCoastGuardFields: bool
406 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
407 @return: An object that can be used to generate a return
408 @rtype: sqlhelp.create
409 '''
410 if None == fields: fields = fieldList
411 import sqlhelp
412 c = sqlhelp.create('sls_wind',dbType=dbType)
413 c.addPrimaryKey()
414 if 'time_month' in fields: c.addInt ('time_month')
415 if 'time_day' in fields: c.addInt ('time_day')
416 if 'time_hour' in fields: c.addInt ('time_hour')
417 if 'time_min' in fields: c.addInt ('time_min')
418 if 'stationid' in fields: c.addVarChar('stationid',7)
419 if dbType != 'postgres':
420 if 'pos_longitude' in fields: c.addDecimal('pos_longitude',7,4)
421 if dbType != 'postgres':
422 if 'pos_latitude' in fields: c.addDecimal('pos_latitude',7,4)
423 if 'flow' in fields: c.addInt ('flow')
424 if 'reserved' in fields: c.addInt ('reserved')
425
426 if addCoastGuardFields:
427
428
429
430
431
432 c.addVarChar('cg_r',15)
433 c.addInt('cg_sec')
434
435 c.addTimestamp('cg_timestamp')
436
437 if dbType == 'postgres':
438
439
440 c.addPostGIS('pos','POINT',2,SRID=4326);
441
442 return c
443
444 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
445 '''
446 Return the SQL INSERT command for this message type
447 @param params: dictionary of values keyed by field name
448 @param outfile: file like object to print to.
449 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
450 @return: sql create string
451 @rtype: str
452
453 @see: sqlCreate
454 '''
455 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
456
457
458 -def sqlInsert(params,extraParams=None,dbType='postgres'):
459 '''
460 Give the SQL INSERT statement
461 @param params: dict keyed by field name of values
462 @param extraParams: any extra fields that you have created beyond the normal ais message fields
463 @rtype: sqlhelp.insert
464 @return: insert class instance
465 @todo: allow optional type checking of params?
466 @warning: this will take invalid keys happily and do what???
467 '''
468 import sqlhelp
469 i = sqlhelp.insert('sls_wind',dbType=dbType)
470
471 if dbType=='postgres':
472 finished = []
473 for key in params:
474 if key in finished:
475 continue
476
477 if key not in toPgFields and key not in fromPgFields:
478 if type(params[key])==Decimal: i.add(key,float(params[key]))
479 else: i.add(key,params[key])
480 else:
481 if key in fromPgFields:
482 val = params[key]
483
484 i.addPostGIS(key,val)
485 finished.append(key)
486 else:
487
488 pgName = toPgFields[key]
489
490 valStr=pgTypes[pgName]+'('
491 vals = []
492 for nonPgKey in fromPgFields[pgName]:
493 vals.append(str(params[nonPgKey]))
494 finished.append(nonPgKey)
495 valStr+=' '.join(vals)+')'
496 i.addPostGIS(pgName,valStr)
497 else:
498 for key in params:
499 if type(params[key])==Decimal: i.add(key,float(params[key]))
500 else: i.add(key,params[key])
501
502 if None != extraParams:
503 for key in extraParams:
504 i.add(key,extraParams[key])
505
506 return i
507
508
509
510
511
514 '''
515 Return the LaTeX definition table for this message type
516 @param outfile: file like object to print to.
517 @type outfile: file obj
518 @return: LaTeX table string via the outfile
519 @rtype: str
520
521 '''
522 o = outfile
523
524 o.write('''
525 \\begin{table}%[htb]
526 \\centering
527 \\begin{tabular}{|l|c|l|}
528 \\hline
529 Parameter & Number of bits & Description
530 \\\\ \\hline\\hline
531 time\_month & 4 & Time tag of measurement month 1..12 \\\\ \hline
532 time\_day & 5 & Time tag of measurement day of the month 1..31 \\\\ \hline
533 time\_hour & 5 & Time tag of measurement UTC hours 0..23 \\\\ \hline
534 time\_min & 6 & Time tag of measurement minutes \\\\ \hline
535 stationid & 42 & Character identifier of the station \\\\ \hline
536 pos\_longitude & 25 & Location of measurement East West location \\\\ \hline
537 pos\_latitude & 24 & Location of measurement North South location \\\\ \hline
538 flow & 10 & Water flow \\\\ \hline
539 reserved & 19 & Reserved bits for future use\\\\ \\hline \\hline
540 Total bits & 140 & Appears to take 1 slot with 28 pad bits to fill the last slot \\\\ \\hline
541 \\end{tabular}
542 \\caption{AIS message number 8: St Lawrance Seaway wind information}
543 \\label{tab:sls_wind}
544 \\end{table}
545 ''')
546
547
548
549
550
551 -def textDefinitionTable(outfile=sys.stdout
552 ,delim='\t'
553 ):
554 '''
555 Return the text definition table for this message type
556 @param outfile: file like object to print to.
557 @type outfile: file obj
558 @return: text table string via the outfile
559 @rtype: str
560
561 '''
562 o = outfile
563 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description
564 time_month'''+delim+'''4'''+delim+'''Time tag of measurement month 1..12
565 time_day'''+delim+'''5'''+delim+'''Time tag of measurement day of the month 1..31
566 time_hour'''+delim+'''5'''+delim+'''Time tag of measurement UTC hours 0..23
567 time_min'''+delim+'''6'''+delim+'''Time tag of measurement minutes
568 stationid'''+delim+'''42'''+delim+'''Character identifier of the station
569 pos_longitude'''+delim+'''25'''+delim+'''Location of measurement East West location
570 pos_latitude'''+delim+'''24'''+delim+'''Location of measurement North South location
571 flow'''+delim+'''10'''+delim+'''Water flow
572 reserved'''+delim+'''19'''+delim+'''Reserved bits for future use
573 Total bits'''+delim+'''140'''+delim+'''Appears to take 1 slot with 28 pad bits to fill the last slot''')
574
575
576
577
578
579 import unittest
581 '''Return a params file base on the testvalue tags.
582 @rtype: dict
583 @return: params based on testvalue tags
584 '''
585 params = {}
586 params['time_month'] = 2
587 params['time_day'] = 28
588 params['time_hour'] = 23
589 params['time_min'] = 45
590 params['stationid'] = 'A345678'
591 params['pos_longitude'] = Decimal('-122.16328')
592 params['pos_latitude'] = Decimal('37.42446')
593 params['flow'] = 43
594 params['reserved'] = 0
595
596 return params
597
599 '''Use testvalue tag text from each type to build test case the sls_wind message'''
601
602 params = testParams()
603 bits = encode(params)
604 r = decode(bits)
605
606
607 self.failUnlessEqual(r['time_month'],params['time_month'])
608 self.failUnlessEqual(r['time_day'],params['time_day'])
609 self.failUnlessEqual(r['time_hour'],params['time_hour'])
610 self.failUnlessEqual(r['time_min'],params['time_min'])
611 self.failUnlessEqual(r['stationid'],params['stationid'])
612 self.failUnlessAlmostEqual(r['pos_longitude'],params['pos_longitude'],4)
613 self.failUnlessAlmostEqual(r['pos_latitude'],params['pos_latitude'],4)
614 self.failUnlessEqual(r['flow'],params['flow'])
615 self.failUnlessEqual(r['reserved'],params['reserved'])
616
618 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
619 help='decode a "sls_wind" AIS message')
620 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
621 help='encode a "sls_wind" AIS message')
622 parser.add_option('--time_month-field', dest='time_monthField',metavar='uint',type='int'
623 ,help='Field parameter value [default: %default]')
624 parser.add_option('--time_day-field', dest='time_dayField',metavar='uint',type='int'
625 ,help='Field parameter value [default: %default]')
626 parser.add_option('--time_hour-field', dest='time_hourField',metavar='uint',type='int'
627 ,help='Field parameter value [default: %default]')
628 parser.add_option('--time_min-field', dest='time_minField',metavar='uint',type='int'
629 ,help='Field parameter value [default: %default]')
630 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
631 ,help='Field parameter value [default: %default]')
632 parser.add_option('--pos_longitude-field', dest='pos_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
633 ,help='Field parameter value [default: %default]')
634 parser.add_option('--pos_latitude-field', dest='pos_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
635 ,help='Field parameter value [default: %default]')
636 parser.add_option('--flow-field', dest='flowField',default=16383,metavar='uint',type='int'
637 ,help='Field parameter value [default: %default]')
638
639
640 if __name__=='__main__':
641
642 from optparse import OptionParser
643 parser = OptionParser(usage="%prog [options]",
644 version="%prog "+__version__)
645
646 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
647 help='run the documentation tests')
648 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
649 help='run the unit tests')
650 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
651 help='Make the test output verbose')
652
653
654
655 typeChoices = ('binary','nmeapayload','nmea')
656 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
657 ,default='nmeapayload'
658 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
659
660
661 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
662 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
663 ,default='std'
664 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
665
666 parser.add_option('-o','--output',dest='outputFileName',default=None,
667 help='Name of the python file to write [default: stdout]')
668
669 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
670 choices=fieldList,
671 help='Which fields to include in the output. Currently only for csv output [default: all]')
672
673 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
674 help='Print the field name for csv')
675
676 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
677 help='Print out an sql create command for the table.')
678
679 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
680 help='Print a LaTeX table of the type')
681
682 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true',
683 help='Print delimited table of the type (for Word table importing)')
684 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t'
685 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)')
686
687
688 dbChoices = ('sqlite','postgres')
689 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
690 ,choices=dbChoices,type='choice'
691 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
692
693 addMsgOptions(parser)
694
695 (options,args) = parser.parse_args()
696 success=True
697
698 if options.doctest:
699 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
700 sys.argv= [sys.argv[0]]
701 if options.verbose: sys.argv.append('-v')
702 import doctest
703 numfail,numtests=doctest.testmod()
704 if numfail==0: print 'ok'
705 else:
706 print 'FAILED'
707 success=False
708
709 if not success: sys.exit('Something Failed')
710 del success
711
712 if options.unittest:
713 sys.argv = [sys.argv[0]]
714 if options.verbose: sys.argv.append('-v')
715 unittest.main()
716
717 outfile = sys.stdout
718 if None!=options.outputFileName:
719 outfile = file(options.outputFileName,'w')
720
721
722 if options.doEncode:
723
724 if None==options.time_monthField: parser.error("missing value for time_monthField")
725 if None==options.time_dayField: parser.error("missing value for time_dayField")
726 if None==options.time_hourField: parser.error("missing value for time_hourField")
727 if None==options.time_minField: parser.error("missing value for time_minField")
728 if None==options.stationidField: parser.error("missing value for stationidField")
729 if None==options.pos_longitudeField: parser.error("missing value for pos_longitudeField")
730 if None==options.pos_latitudeField: parser.error("missing value for pos_latitudeField")
731 if None==options.flowField: parser.error("missing value for flowField")
732 msgDict={
733 'time_month': options.time_monthField,
734 'time_day': options.time_dayField,
735 'time_hour': options.time_hourField,
736 'time_min': options.time_minField,
737 'stationid': options.stationidField,
738 'pos_longitude': options.pos_longitudeField,
739 'pos_latitude': options.pos_latitudeField,
740 'flow': options.flowField,
741 'reserved': '0',
742 }
743
744 bits = encode(msgDict)
745 if 'binary'==options.ioType: print str(bits)
746 elif 'nmeapayload'==options.ioType:
747
748 print "bitLen",len(bits)
749 bitLen=len(bits)
750 if bitLen%6!=0:
751 bits = bits + BitVector(size=(6 - (bitLen%6)))
752 print "result:",binary.bitvectoais6(bits)[0]
753
754
755
756 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
757 else: sys.exit('ERROR: unknown ioType. Help!')
758
759
760 if options.sqlCreate:
761 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
762
763 if options.latexDefinitionTable:
764 latexDefinitionTable(outfile)
765
766
767 if options.textDefinitionTable:
768 textDefinitionTable(outfile,options.delimTextDefinitionTable)
769
770 if options.printCsvfieldList:
771
772 if None == options.fieldList: options.fieldList = fieldList
773 import StringIO
774 buf = StringIO.StringIO()
775 for field in options.fieldList:
776 buf.write(field+',')
777 result = buf.getvalue()
778 if result[-1] == ',': print result[:-1]
779 else: print result
780
781 if options.doDecode:
782 if len(args)==0: args = sys.stdin
783 for msg in args:
784 bv = None
785
786 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
787
788
789 bv = binary.ais6tobitvec(msg.split(',')[5])
790 else:
791
792 binaryMsg=True
793 for c in msg:
794 if c not in ('0','1'):
795 binaryMsg=False
796 break
797 if binaryMsg:
798 bv = BitVector(bitstring=msg)
799 else:
800 bv = binary.ais6tobitvec(msg)
801
802 printFields(decode(bv)
803 ,out=outfile
804 ,format=options.outputType
805 ,fieldList=options.fieldList
806 ,dbType=options.dbType
807 )
808