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