1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-02-16 $'.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 'dac',
51 'fid',
52 'efid',
53 'timetag_month',
54 'timetag_day',
55 'timetag_hour',
56 'timetag_min',
57 'timetag_sec',
58 'stationid',
59 'station_longitude',
60 'station_latitude',
61 'whale_longitude',
62 'whale_latitude',
63 'timetoexpire',
64 'radius',
65 'heading',
66 'numWhales',
67 )
68
69 fieldListPostgres = (
70 'dac',
71 'fid',
72 'efid',
73 'timetag_month',
74 'timetag_day',
75 'timetag_hour',
76 'timetag_min',
77 'timetag_sec',
78 'stationid',
79 'station_longitude',
80 'station_latitude',
81 'whale_longitude',
82 'whale_latitude',
83 'timetoexpire',
84 'radius',
85 'heading',
86 'numWhales',
87 )
88
89 toPgFields = {
90 }
91 '''
92 Go to the Postgis field names from the straight field name
93 '''
94
95 fromPgFields = {
96 }
97 '''
98 Go from the Postgis field names to the straight field name
99 '''
100
101 pgTypes = {
102 }
103 '''
104 Lookup table for each postgis field name to get its type.
105 '''
106
107 -def encode(params, validate=False):
108 '''Create a whalenotice binary message payload to pack into an AIS Msg whalenotice.
109
110 Fields in params:
111 - dac(uint): Designated Area Code (field automatically set to "366")
112 - fid(uint): Functional Identifier (field automatically set to "1")
113 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2")
114 - timetag_month(uint): Time whale was last recorded month 1..12
115 - timetag_day(uint): Time whale was last recorded day of the month 1..31
116 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23
117 - timetag_min(uint): Time whale was last recorded minutes
118 - timetag_sec(uint): Time whale was last recorded seconds
119 - stationid(aisstr6): Character identifier of the station. Usually a number.
120 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location
121 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location
122 - whale_longitude(decimal): Where was the whale East West location
123 - whale_latitude(decimal): Where was the whale North South location
124 - timetoexpire(uint): Seconds until this notice expires
125 - radius(uint): Distance of the required exclusion/slow zone
126 - heading(uint): Direction the whale is traveling
127 - numWhales(uint): Number of whales detected
128 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
129 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
130 @rtype: BitVector
131 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
132 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
133 '''
134
135 bvList = []
136 bvList.append(binary.setBitVectorSize(BitVector(intVal=366),16))
137 bvList.append(binary.setBitVectorSize(BitVector(intVal=1),4))
138 bvList.append(binary.setBitVectorSize(BitVector(intVal=2),12))
139 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_month']),4))
140 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_day']),5))
141 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_hour']),5))
142 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_min']),6))
143 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetag_sec']),6))
144 if 'stationid' in params:
145 bvList.append(aisstring.encode(params['stationid'],42))
146 else:
147 bvList.append(aisstring.encode('@@@@@@@',42))
148 if 'station_longitude' in params:
149 bvList.append(binary.bvFromSignedInt(int(Decimal(params['station_longitude'])*Decimal('600000')),28))
150 else:
151 bvList.append(binary.bvFromSignedInt(108600000,28))
152 if 'station_latitude' in params:
153 bvList.append(binary.bvFromSignedInt(int(Decimal(params['station_latitude'])*Decimal('600000')),27))
154 else:
155 bvList.append(binary.bvFromSignedInt(54600000,27))
156 if 'whale_longitude' in params:
157 bvList.append(binary.bvFromSignedInt(int(Decimal(params['whale_longitude'])*Decimal('600000')),28))
158 else:
159 bvList.append(binary.bvFromSignedInt(108600000,28))
160 if 'whale_latitude' in params:
161 bvList.append(binary.bvFromSignedInt(int(Decimal(params['whale_latitude'])*Decimal('600000')),27))
162 else:
163 bvList.append(binary.bvFromSignedInt(54600000,27))
164 if 'timetoexpire' in params:
165 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timetoexpire']),16))
166 else:
167 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),16))
168 if 'radius' in params:
169 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['radius']),16))
170 else:
171 bvList.append(binary.setBitVectorSize(BitVector(intVal=65534),16))
172 if 'heading' in params:
173 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['heading']),9))
174 else:
175 bvList.append(binary.setBitVectorSize(BitVector(intVal=511),9))
176 if 'numWhales' in params:
177 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['numWhales']),8))
178 else:
179 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8))
180
181 return binary.joinBV(bvList)
182
183 -def decode(bv, validate=False):
184 '''Unpack a whalenotice message
185
186 Fields in params:
187 - dac(uint): Designated Area Code (field automatically set to "366")
188 - fid(uint): Functional Identifier (field automatically set to "1")
189 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2")
190 - timetag_month(uint): Time whale was last recorded month 1..12
191 - timetag_day(uint): Time whale was last recorded day of the month 1..31
192 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23
193 - timetag_min(uint): Time whale was last recorded minutes
194 - timetag_sec(uint): Time whale was last recorded seconds
195 - stationid(aisstr6): Character identifier of the station. Usually a number.
196 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location
197 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location
198 - whale_longitude(decimal): Where was the whale East West location
199 - whale_latitude(decimal): Where was the whale North South location
200 - timetoexpire(uint): Seconds until this notice expires
201 - radius(uint): Distance of the required exclusion/slow zone
202 - heading(uint): Direction the whale is traveling
203 - numWhales(uint): Number of whales detected
204 @type bv: BitVector
205 @param bv: Bits defining a message
206 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
207 @rtype: dict
208 @return: params
209 '''
210
211
212
213
214 r = {}
215 r['dac']=366
216 r['fid']=1
217 r['efid']=2
218 r['timetag_month']=int(bv[32:36])
219 r['timetag_day']=int(bv[36:41])
220 r['timetag_hour']=int(bv[41:46])
221 r['timetag_min']=int(bv[46:52])
222 r['timetag_sec']=int(bv[52:58])
223 r['stationid']=aisstring.decode(bv[58:100])
224 r['station_longitude']=Decimal(binary.signedIntFromBV(bv[100:128]))/Decimal('600000')
225 r['station_latitude']=Decimal(binary.signedIntFromBV(bv[128:155]))/Decimal('600000')
226 r['whale_longitude']=Decimal(binary.signedIntFromBV(bv[155:183]))/Decimal('600000')
227 r['whale_latitude']=Decimal(binary.signedIntFromBV(bv[183:210]))/Decimal('600000')
228 r['timetoexpire']=int(bv[210:226])
229 r['radius']=int(bv[226:242])
230 r['heading']=int(bv[242:251])
231 r['numWhales']=int(bv[251:259])
232 return r
233
235 return 366
236
238 return 1
239
241 return 2
242
245
248
251
254
257
260
263
266
269
272
274 return int(bv[210:226])
275
277 return int(bv[226:242])
278
280 return int(bv[242:251])
281
283 return int(bv[251:259])
284
285
287 out.write("<h3>whalenotice<h3>\n")
288 out.write("<table border=\"1\">\n")
289 out.write("<tr bgcolor=\"orange\">\n")
290 out.write("<th align=\"left\">Field Name</th>\n")
291 out.write("<th align=\"left\">Type</th>\n")
292 out.write("<th align=\"left\">Value</th>\n")
293 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
294 out.write("<th align=\"left\">Units</th>\n")
295 out.write("\n")
296 out.write("<tr>\n")
297 out.write("<td>dac</td>\n")
298 out.write("<td>uint</td>\n")
299 if 'dac' in params:
300 out.write(" <td>"+str(params['dac'])+"</td>\n")
301 out.write(" <td>"+str(params['dac'])+"</td>\n")
302 out.write("</tr>\n")
303 out.write("\n")
304 out.write("<tr>\n")
305 out.write("<td>fid</td>\n")
306 out.write("<td>uint</td>\n")
307 if 'fid' in params:
308 out.write(" <td>"+str(params['fid'])+"</td>\n")
309 out.write(" <td>"+str(params['fid'])+"</td>\n")
310 out.write("</tr>\n")
311 out.write("\n")
312 out.write("<tr>\n")
313 out.write("<td>efid</td>\n")
314 out.write("<td>uint</td>\n")
315 if 'efid' in params:
316 out.write(" <td>"+str(params['efid'])+"</td>\n")
317 out.write(" <td>"+str(params['efid'])+"</td>\n")
318 out.write("</tr>\n")
319 out.write("\n")
320 out.write("<tr>\n")
321 out.write("<td>timetag_month</td>\n")
322 out.write("<td>uint</td>\n")
323 if 'timetag_month' in params:
324 out.write(" <td>"+str(params['timetag_month'])+"</td>\n")
325 out.write(" <td>"+str(params['timetag_month'])+"</td>\n")
326 out.write("</tr>\n")
327 out.write("\n")
328 out.write("<tr>\n")
329 out.write("<td>timetag_day</td>\n")
330 out.write("<td>uint</td>\n")
331 if 'timetag_day' in params:
332 out.write(" <td>"+str(params['timetag_day'])+"</td>\n")
333 out.write(" <td>"+str(params['timetag_day'])+"</td>\n")
334 out.write("</tr>\n")
335 out.write("\n")
336 out.write("<tr>\n")
337 out.write("<td>timetag_hour</td>\n")
338 out.write("<td>uint</td>\n")
339 if 'timetag_hour' in params:
340 out.write(" <td>"+str(params['timetag_hour'])+"</td>\n")
341 out.write(" <td>"+str(params['timetag_hour'])+"</td>\n")
342 out.write("</tr>\n")
343 out.write("\n")
344 out.write("<tr>\n")
345 out.write("<td>timetag_min</td>\n")
346 out.write("<td>uint</td>\n")
347 if 'timetag_min' in params:
348 out.write(" <td>"+str(params['timetag_min'])+"</td>\n")
349 out.write(" <td>"+str(params['timetag_min'])+"</td>\n")
350 out.write("</tr>\n")
351 out.write("\n")
352 out.write("<tr>\n")
353 out.write("<td>timetag_sec</td>\n")
354 out.write("<td>uint</td>\n")
355 if 'timetag_sec' in params:
356 out.write(" <td>"+str(params['timetag_sec'])+"</td>\n")
357 out.write(" <td>"+str(params['timetag_sec'])+"</td>\n")
358 out.write("</tr>\n")
359 out.write("\n")
360 out.write("<tr>\n")
361 out.write("<td>stationid</td>\n")
362 out.write("<td>aisstr6</td>\n")
363 if 'stationid' in params:
364 out.write(" <td>"+str(params['stationid'])+"</td>\n")
365 out.write(" <td>"+str(params['stationid'])+"</td>\n")
366 out.write("</tr>\n")
367 out.write("\n")
368 out.write("<tr>\n")
369 out.write("<td>station_longitude</td>\n")
370 out.write("<td>decimal</td>\n")
371 if 'station_longitude' in params:
372 out.write(" <td>"+str(params['station_longitude'])+"</td>\n")
373 out.write(" <td>"+str(params['station_longitude'])+"</td>\n")
374 out.write("<td>degrees</td>\n")
375 out.write("</tr>\n")
376 out.write("\n")
377 out.write("<tr>\n")
378 out.write("<td>station_latitude</td>\n")
379 out.write("<td>decimal</td>\n")
380 if 'station_latitude' in params:
381 out.write(" <td>"+str(params['station_latitude'])+"</td>\n")
382 out.write(" <td>"+str(params['station_latitude'])+"</td>\n")
383 out.write("<td>degrees</td>\n")
384 out.write("</tr>\n")
385 out.write("\n")
386 out.write("<tr>\n")
387 out.write("<td>whale_longitude</td>\n")
388 out.write("<td>decimal</td>\n")
389 if 'whale_longitude' in params:
390 out.write(" <td>"+str(params['whale_longitude'])+"</td>\n")
391 out.write(" <td>"+str(params['whale_longitude'])+"</td>\n")
392 out.write("<td>degrees</td>\n")
393 out.write("</tr>\n")
394 out.write("\n")
395 out.write("<tr>\n")
396 out.write("<td>whale_latitude</td>\n")
397 out.write("<td>decimal</td>\n")
398 if 'whale_latitude' in params:
399 out.write(" <td>"+str(params['whale_latitude'])+"</td>\n")
400 out.write(" <td>"+str(params['whale_latitude'])+"</td>\n")
401 out.write("<td>degrees</td>\n")
402 out.write("</tr>\n")
403 out.write("\n")
404 out.write("<tr>\n")
405 out.write("<td>timetoexpire</td>\n")
406 out.write("<td>uint</td>\n")
407 if 'timetoexpire' in params:
408 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n")
409 out.write(" <td>"+str(params['timetoexpire'])+"</td>\n")
410 out.write("<td>seconds</td>\n")
411 out.write("</tr>\n")
412 out.write("\n")
413 out.write("<tr>\n")
414 out.write("<td>radius</td>\n")
415 out.write("<td>uint</td>\n")
416 if 'radius' in params:
417 out.write(" <td>"+str(params['radius'])+"</td>\n")
418 out.write(" <td>"+str(params['radius'])+"</td>\n")
419 out.write("<td>m</td>\n")
420 out.write("</tr>\n")
421 out.write("\n")
422 out.write("<tr>\n")
423 out.write("<td>heading</td>\n")
424 out.write("<td>uint</td>\n")
425 if 'heading' in params:
426 out.write(" <td>"+str(params['heading'])+"</td>\n")
427 out.write(" <td>"+str(params['heading'])+"</td>\n")
428 out.write("<td>degrees true north</td>\n")
429 out.write("</tr>\n")
430 out.write("\n")
431 out.write("<tr>\n")
432 out.write("<td>numWhales</td>\n")
433 out.write("<td>uint</td>\n")
434 if 'numWhales' in params:
435 out.write(" <td>"+str(params['numWhales'])+"</td>\n")
436 out.write(" <td>"+str(params['numWhales'])+"</td>\n")
437 out.write("</tr>\n")
438 out.write("</table>\n")
439
440
442 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
443 out.write("\ <Placemark>\n")
444 out.write("\t <name>"+str(params['stationsid'])+"</name>\n")
445 out.write("\t\t<description>\n")
446 import StringIO
447 buf = StringIO.StringIO()
448 printHtml(params,buf)
449 import cgi
450 out.write(cgi.escape(buf.getvalue()))
451 out.write("\t\t</description>\n")
452 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
453 out.write("\t\t<Point>\n")
454 out.write("\t\t\t<coordinates>")
455 out.write(str(params['station_longitude']))
456 out.write(',')
457 out.write(str(params['station_latitude']))
458 out.write(",0</coordinates>\n")
459 out.write("\t\t</Point>\n")
460 out.write("\t</Placemark>\n")
461
462 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
463 '''Print a numWhales message to stdout.
464
465 Fields in params:
466 - dac(uint): Designated Area Code (field automatically set to "366")
467 - fid(uint): Functional Identifier (field automatically set to "1")
468 - efid(uint): extended functional identifier (dac+fid+id defines which message) (field automatically set to "2")
469 - timetag_month(uint): Time whale was last recorded month 1..12
470 - timetag_day(uint): Time whale was last recorded day of the month 1..31
471 - timetag_hour(uint): Time whale was last recorded UTC hours 0..23
472 - timetag_min(uint): Time whale was last recorded minutes
473 - timetag_sec(uint): Time whale was last recorded seconds
474 - stationid(aisstr6): Character identifier of the station. Usually a number.
475 - station_longitude(decimal): Location of the sensor taking the water level measurement or position of prediction East West location
476 - station_latitude(decimal): Location of the sensor taking the water level measurement or position of prediction North South location
477 - whale_longitude(decimal): Where was the whale East West location
478 - whale_latitude(decimal): Where was the whale North South location
479 - timetoexpire(uint): Seconds until this notice expires
480 - radius(uint): Distance of the required exclusion/slow zone
481 - heading(uint): Direction the whale is traveling
482 - numWhales(uint): Number of whales detected
483 @param params: Dictionary of field names/values.
484 @param out: File like object to write to
485 @rtype: stdout
486 @return: text to out
487 '''
488
489 if 'std'==format:
490 out.write("numWhales:\n")
491 if 'dac' in params: out.write(" dac: "+str(params['dac'])+"\n")
492 if 'fid' in params: out.write(" fid: "+str(params['fid'])+"\n")
493 if 'efid' in params: out.write(" efid: "+str(params['efid'])+"\n")
494 if 'timetag_month' in params: out.write(" timetag_month: "+str(params['timetag_month'])+"\n")
495 if 'timetag_day' in params: out.write(" timetag_day: "+str(params['timetag_day'])+"\n")
496 if 'timetag_hour' in params: out.write(" timetag_hour: "+str(params['timetag_hour'])+"\n")
497 if 'timetag_min' in params: out.write(" timetag_min: "+str(params['timetag_min'])+"\n")
498 if 'timetag_sec' in params: out.write(" timetag_sec: "+str(params['timetag_sec'])+"\n")
499 if 'stationid' in params: out.write(" stationid: "+str(params['stationid'])+"\n")
500 if 'station_longitude' in params: out.write(" station_longitude: "+str(params['station_longitude'])+"\n")
501 if 'station_latitude' in params: out.write(" station_latitude: "+str(params['station_latitude'])+"\n")
502 if 'whale_longitude' in params: out.write(" whale_longitude: "+str(params['whale_longitude'])+"\n")
503 if 'whale_latitude' in params: out.write(" whale_latitude: "+str(params['whale_latitude'])+"\n")
504 if 'timetoexpire' in params: out.write(" timetoexpire: "+str(params['timetoexpire'])+"\n")
505 if 'radius' in params: out.write(" radius: "+str(params['radius'])+"\n")
506 if 'heading' in params: out.write(" heading: "+str(params['heading'])+"\n")
507 if 'numWhales' in params: out.write(" numWhales: "+str(params['numWhales'])+"\n")
508 elif 'csv'==format:
509 if None == options.fieldList:
510 options.fieldList = fieldList
511 needComma = False;
512 for field in fieldList:
513 if needComma: out.write(',')
514 needComma = True
515 if field in params:
516 out.write(str(params[field]))
517
518 out.write("\n")
519 elif 'html'==format:
520 printHtml(params,out)
521 elif 'sql'==format:
522 sqlInsertStr(params,out,dbType=dbType)
523 elif 'kml'==format:
524 printKml(params,out)
525 elif 'kml-full'==format:
526 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
527 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
528 out.write("<Document>\n")
529 out.write(" <name>whalenotice</name>\n")
530 printKml(params,out)
531 out.write("</Document>\n")
532 out.write("</kml>\n")
533 else:
534 print "ERROR: unknown format:",format
535 assert False
536
537 return
538
539
540
541
542
543 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
544 ,addCoastGuardFields=True
545 ,dbType='postgres'
546 ):
547 '''
548 Return the SQL CREATE command for this message type
549 @param outfile: file like object to print to.
550 @param fields: which fields to put in the create. Defaults to all.
551 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
552 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
553 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
554 @type addCoastGuardFields: bool
555 @return: sql create string
556 @rtype: str
557
558 @see: sqlCreate
559 '''
560 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
561
562 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
563 '''
564 Return the sqlhelp object to create the table.
565
566 @param fields: which fields to put in the create. Defaults to all.
567 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
568 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
569 @type addCoastGuardFields: bool
570 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
571 @return: An object that can be used to generate a return
572 @rtype: sqlhelp.create
573 '''
574 if None == fields: fields = fieldList
575 import sqlhelp
576 c = sqlhelp.create('whalenotice',dbType=dbType)
577 c.addPrimaryKey()
578 if 'dac' in fields: c.addInt ('dac')
579 if 'fid' in fields: c.addInt ('fid')
580 if 'efid' in fields: c.addInt ('efid')
581 if 'timetag_month' in fields: c.addInt ('timetag_month')
582 if 'timetag_day' in fields: c.addInt ('timetag_day')
583 if 'timetag_hour' in fields: c.addInt ('timetag_hour')
584 if 'timetag_min' in fields: c.addInt ('timetag_min')
585 if 'timetag_sec' in fields: c.addInt ('timetag_sec')
586 if 'stationid' in fields: c.addVarChar('stationid',7)
587 if 'station_longitude' in fields: c.addDecimal('station_longitude',8,5)
588 if 'station_latitude' in fields: c.addDecimal('station_latitude',8,5)
589 if 'whale_longitude' in fields: c.addDecimal('whale_longitude',8,5)
590 if 'whale_latitude' in fields: c.addDecimal('whale_latitude',8,5)
591 if 'timetoexpire' in fields: c.addInt ('timetoexpire')
592 if 'radius' in fields: c.addInt ('radius')
593 if 'heading' in fields: c.addInt ('heading')
594 if 'numWhales' in fields: c.addInt ('numWhales')
595
596 if addCoastGuardFields:
597
598
599
600
601
602 c.addVarChar('cg_r',15)
603 c.addInt('cg_sec')
604
605 c.addTimestamp('cg_timestamp')
606
607 return c
608
609 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
610 '''
611 Return the SQL INSERT command for this message type
612 @param params: dictionary of values keyed by field name
613 @param outfile: file like object to print to.
614 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
615 @return: sql create string
616 @rtype: str
617
618 @see: sqlCreate
619 '''
620 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
621
622
623 -def sqlInsert(params,extraParams=None,dbType='postgres'):
624 '''
625 Give the SQL INSERT statement
626 @param params: dict keyed by field name of values
627 @param extraParams: any extra fields that you have created beyond the normal ais message fields
628 @rtype: sqlhelp.insert
629 @return: insert class instance
630 @todo: allow optional type checking of params?
631 @warning: this will take invalid keys happily and do what???
632 '''
633 import sqlhelp
634 i = sqlhelp.insert('whalenotice',dbType=dbType)
635
636 if dbType=='postgres':
637 finished = []
638 for key in params:
639 if key in finished:
640
641 continue
642
643 if key not in toPgFields and key not in fromPgFields:
644 if type(params[key])==Decimal: i.add(key,float(params[key]))
645 else: i.add(key,params[key])
646 else:
647 if key in fromPgFields:
648 val = params[key]
649
650 i.addPostGIS(key,val)
651 finished.append(key)
652 else:
653
654 pgName = toPgFields[key]
655
656 valStr=pgTypes[pgName]+'('
657 vals = []
658 for nonPgKey in fromPgFields[pgName]:
659 vals.append(str(params[nonPgKey]))
660 finished.append(nonPgKey)
661 valStr+=' '.join(vals)+')'
662 i.addPostGIS(pgName,valStr)
663 else:
664 for key in params:
665 if type(params[key])==Decimal: i.add(key,float(params[key]))
666 else: i.add(key,params[key])
667
668 if None != extraParams:
669 for key in extraParams:
670 i.add(key,extraParams[key])
671
672 return i
673
674
675
676
677
678 import unittest
680 '''Return a params file base on the testvalue tags.
681 @rtype: dict
682 @return: params based on testvalue tags
683 '''
684 params = {}
685 params['dac'] = 366
686 params['fid'] = 1
687 params['efid'] = 2
688 params['timetag_month'] = 2
689 params['timetag_day'] = 28
690 params['timetag_hour'] = 23
691 params['timetag_min'] = 45
692 params['timetag_sec'] = 58
693 params['stationid'] = 'A234567'
694 params['station_longitude'] = Decimal('-122.16328055555556')
695 params['station_latitude'] = Decimal('37.424458333333334')
696 params['whale_longitude'] = Decimal('-122.16328055555556')
697 params['whale_latitude'] = Decimal('37.424458333333334')
698 params['timetoexpire'] = 1
699 params['radius'] = 5000
700 params['heading'] = 35
701 params['numWhales'] = 2
702
703 return params
704
706 '''Use testvalue tag text from each type to build test case the whalenotice message'''
708
709 params = testParams()
710 bits = encode(params)
711 r = decode(bits)
712
713
714 self.failUnlessEqual(r['dac'],params['dac'])
715 self.failUnlessEqual(r['fid'],params['fid'])
716 self.failUnlessEqual(r['efid'],params['efid'])
717 self.failUnlessEqual(r['timetag_month'],params['timetag_month'])
718 self.failUnlessEqual(r['timetag_day'],params['timetag_day'])
719 self.failUnlessEqual(r['timetag_hour'],params['timetag_hour'])
720 self.failUnlessEqual(r['timetag_min'],params['timetag_min'])
721 self.failUnlessEqual(r['timetag_sec'],params['timetag_sec'])
722 self.failUnlessEqual(r['stationid'],params['stationid'])
723 self.failUnlessAlmostEqual(r['station_longitude'],params['station_longitude'],5)
724 self.failUnlessAlmostEqual(r['station_latitude'],params['station_latitude'],5)
725 self.failUnlessAlmostEqual(r['whale_longitude'],params['whale_longitude'],5)
726 self.failUnlessAlmostEqual(r['whale_latitude'],params['whale_latitude'],5)
727 self.failUnlessEqual(r['timetoexpire'],params['timetoexpire'])
728 self.failUnlessEqual(r['radius'],params['radius'])
729 self.failUnlessEqual(r['heading'],params['heading'])
730 self.failUnlessEqual(r['numWhales'],params['numWhales'])
731
733 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
734 help='decode a "whalenotice" AIS message')
735 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
736 help='encode a "whalenotice" AIS message')
737 parser.add_option('--timetag_month-field', dest='timetag_monthField',metavar='uint',type='int'
738 ,help='Field parameter value [default: %default]')
739 parser.add_option('--timetag_day-field', dest='timetag_dayField',metavar='uint',type='int'
740 ,help='Field parameter value [default: %default]')
741 parser.add_option('--timetag_hour-field', dest='timetag_hourField',metavar='uint',type='int'
742 ,help='Field parameter value [default: %default]')
743 parser.add_option('--timetag_min-field', dest='timetag_minField',metavar='uint',type='int'
744 ,help='Field parameter value [default: %default]')
745 parser.add_option('--timetag_sec-field', dest='timetag_secField',metavar='uint',type='int'
746 ,help='Field parameter value [default: %default]')
747 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
748 ,help='Field parameter value [default: %default]')
749 parser.add_option('--station_longitude-field', dest='station_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
750 ,help='Field parameter value [default: %default]')
751 parser.add_option('--station_latitude-field', dest='station_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
752 ,help='Field parameter value [default: %default]')
753 parser.add_option('--whale_longitude-field', dest='whale_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
754 ,help='Field parameter value [default: %default]')
755 parser.add_option('--whale_latitude-field', dest='whale_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
756 ,help='Field parameter value [default: %default]')
757 parser.add_option('--timetoexpire-field', dest='timetoexpireField',default=0,metavar='uint',type='int'
758 ,help='Field parameter value [default: %default]')
759 parser.add_option('--radius-field', dest='radiusField',default=65534,metavar='uint',type='int'
760 ,help='Field parameter value [default: %default]')
761 parser.add_option('--heading-field', dest='headingField',default=511,metavar='uint',type='int'
762 ,help='Field parameter value [default: %default]')
763 parser.add_option('--numWhales-field', dest='numWhalesField',default=0,metavar='uint',type='int'
764 ,help='Field parameter value [default: %default]')
765
766
767 if __name__=='__main__':
768
769 from optparse import OptionParser
770 parser = OptionParser(usage="%prog [options]",
771 version="%prog "+__version__)
772
773 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
774 help='run the documentation tests')
775 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
776 help='run the unit tests')
777 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
778 help='Make the test output verbose')
779
780
781
782 typeChoices = ('binary','nmeapayload','nmea')
783 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
784 ,default='nmeapayload'
785 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
786
787
788 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
789 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
790 ,default='std'
791 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
792
793 parser.add_option('-o','--output',dest='outputFileName',default=None,
794 help='Name of the python file to write [default: stdout]')
795
796 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
797 choices=fieldList,
798 help='Which fields to include in the output. Currently only for csv output [default: all]')
799
800 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
801 help='Print the field name for csv')
802
803 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
804 help='Print out an sql create command for the table.')
805
806 dbChoices = ('sqlite','postgres')
807 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
808 ,choices=dbChoices,type='choice'
809 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
810
811 addMsgOptions(parser)
812
813 (options,args) = parser.parse_args()
814 success=True
815
816 if options.doctest:
817 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
818 sys.argv= [sys.argv[0]]
819 if options.verbose: sys.argv.append('-v')
820 import doctest
821 numfail,numtests=doctest.testmod()
822 if numfail==0: print 'ok'
823 else:
824 print 'FAILED'
825 success=False
826
827 if not success: sys.exit('Something Failed')
828 del success
829
830 if options.unittest:
831 sys.argv = [sys.argv[0]]
832 if options.verbose: sys.argv.append('-v')
833 unittest.main()
834
835 outfile = sys.stdout
836 if None!=options.outputFileName:
837 outfile = file(options.outputFileName,'w')
838
839
840 if options.doEncode:
841
842 if None==options.timetag_monthField: parser.error("missing value for timetag_monthField")
843 if None==options.timetag_dayField: parser.error("missing value for timetag_dayField")
844 if None==options.timetag_hourField: parser.error("missing value for timetag_hourField")
845 if None==options.timetag_minField: parser.error("missing value for timetag_minField")
846 if None==options.timetag_secField: parser.error("missing value for timetag_secField")
847 if None==options.stationidField: parser.error("missing value for stationidField")
848 if None==options.station_longitudeField: parser.error("missing value for station_longitudeField")
849 if None==options.station_latitudeField: parser.error("missing value for station_latitudeField")
850 if None==options.whale_longitudeField: parser.error("missing value for whale_longitudeField")
851 if None==options.whale_latitudeField: parser.error("missing value for whale_latitudeField")
852 if None==options.timetoexpireField: parser.error("missing value for timetoexpireField")
853 if None==options.radiusField: parser.error("missing value for radiusField")
854 if None==options.headingField: parser.error("missing value for headingField")
855 if None==options.numWhalesField: parser.error("missing value for numWhalesField")
856 msgDict={
857 'dac': '366',
858 'fid': '1',
859 'efid': '2',
860 'timetag_month': options.timetag_monthField,
861 'timetag_day': options.timetag_dayField,
862 'timetag_hour': options.timetag_hourField,
863 'timetag_min': options.timetag_minField,
864 'timetag_sec': options.timetag_secField,
865 'stationid': options.stationidField,
866 'station_longitude': options.station_longitudeField,
867 'station_latitude': options.station_latitudeField,
868 'whale_longitude': options.whale_longitudeField,
869 'whale_latitude': options.whale_latitudeField,
870 'timetoexpire': options.timetoexpireField,
871 'radius': options.radiusField,
872 'heading': options.headingField,
873 'numWhales': options.numWhalesField,
874 }
875
876 bits = encode(msgDict)
877 if 'binary'==options.ioType: print str(bits)
878 elif 'nmeapayload'==options.ioType:
879
880 print "bitLen",len(bits)
881 bitLen=len(bits)
882 if bitLen%6!=0:
883 bits = bits + BitVector(size=(6 - (bitLen%6)))
884 print "result:",binary.bitvectoais6(bits)[0]
885
886
887
888 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
889 else: sys.exit('ERROR: unknown ioType. Help!')
890
891
892 if options.sqlCreate:
893 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
894
895 if options.printCsvfieldList:
896
897 if None == options.fieldList: options.fieldList = fieldList
898 import StringIO
899 buf = StringIO.StringIO()
900 for field in options.fieldList:
901 buf.write(field+',')
902 result = buf.getvalue()
903 if result[-1] == ',': print result[:-1]
904 else: print result
905
906 if options.doDecode:
907 for msg in args:
908 bv = None
909
910 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
911
912
913 bv = binary.ais6tobitvec(msg.split(',')[5])
914 else:
915
916 binaryMsg=True
917 for c in msg:
918 if c not in ('0','1'):
919 binaryMsg=False
920 break
921 if binaryMsg:
922 bv = BitVector(bitstring=msg)
923 else:
924 bv = binary.ais6tobitvec(msg)
925
926 printFields(decode(bv)
927 ,out=outfile
928 ,format=options.outputType
929 ,fieldList=options.fieldList
930 ,dbType=options.dbType
931 )
932