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 '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 whalenotice 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("whalenotice:\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 continue
641
642 if key not in toPgFields and key not in fromPgFields:
643 if type(params[key])==Decimal: i.add(key,float(params[key]))
644 else: i.add(key,params[key])
645 else:
646 if key in fromPgFields:
647 val = params[key]
648
649 i.addPostGIS(key,val)
650 finished.append(key)
651 else:
652
653 pgName = toPgFields[key]
654
655 valStr=pgTypes[pgName]+'('
656 vals = []
657 for nonPgKey in fromPgFields[pgName]:
658 vals.append(str(params[nonPgKey]))
659 finished.append(nonPgKey)
660 valStr+=' '.join(vals)+')'
661 i.addPostGIS(pgName,valStr)
662 else:
663 for key in params:
664 if type(params[key])==Decimal: i.add(key,float(params[key]))
665 else: i.add(key,params[key])
666
667 if None != extraParams:
668 for key in extraParams:
669 i.add(key,extraParams[key])
670
671 return i
672
673
674
675
676
677 import unittest
679 '''Return a params file base on the testvalue tags.
680 @rtype: dict
681 @return: params based on testvalue tags
682 '''
683 params = {}
684 params['dac'] = 366
685 params['fid'] = 1
686 params['efid'] = 2
687 params['timetag_month'] = 2
688 params['timetag_day'] = 28
689 params['timetag_hour'] = 23
690 params['timetag_min'] = 45
691 params['timetag_sec'] = 58
692 params['stationid'] = 'A234567'
693 params['station_longitude'] = Decimal('-122.16328055555556')
694 params['station_latitude'] = Decimal('37.424458333333334')
695 params['whale_longitude'] = Decimal('-122.16328055555556')
696 params['whale_latitude'] = Decimal('37.424458333333334')
697 params['timetoexpire'] = 1
698 params['radius'] = 5000
699 params['heading'] = 35
700 params['numWhales'] = 2
701
702 return params
703
705 '''Use testvalue tag text from each type to build test case the whalenotice message'''
707
708 params = testParams()
709 bits = encode(params)
710 r = decode(bits)
711
712
713 self.failUnlessEqual(r['dac'],params['dac'])
714 self.failUnlessEqual(r['fid'],params['fid'])
715 self.failUnlessEqual(r['efid'],params['efid'])
716 self.failUnlessEqual(r['timetag_month'],params['timetag_month'])
717 self.failUnlessEqual(r['timetag_day'],params['timetag_day'])
718 self.failUnlessEqual(r['timetag_hour'],params['timetag_hour'])
719 self.failUnlessEqual(r['timetag_min'],params['timetag_min'])
720 self.failUnlessEqual(r['timetag_sec'],params['timetag_sec'])
721 self.failUnlessEqual(r['stationid'],params['stationid'])
722 self.failUnlessAlmostEqual(r['station_longitude'],params['station_longitude'],5)
723 self.failUnlessAlmostEqual(r['station_latitude'],params['station_latitude'],5)
724 self.failUnlessAlmostEqual(r['whale_longitude'],params['whale_longitude'],5)
725 self.failUnlessAlmostEqual(r['whale_latitude'],params['whale_latitude'],5)
726 self.failUnlessEqual(r['timetoexpire'],params['timetoexpire'])
727 self.failUnlessEqual(r['radius'],params['radius'])
728 self.failUnlessEqual(r['heading'],params['heading'])
729 self.failUnlessEqual(r['numWhales'],params['numWhales'])
730
732 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
733 help='decode a "whalenotice" AIS message')
734 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
735 help='encode a "whalenotice" AIS message')
736 parser.add_option('--timetag_month-field', dest='timetag_monthField',metavar='uint',type='int'
737 ,help='Field parameter value [default: %default]')
738 parser.add_option('--timetag_day-field', dest='timetag_dayField',metavar='uint',type='int'
739 ,help='Field parameter value [default: %default]')
740 parser.add_option('--timetag_hour-field', dest='timetag_hourField',metavar='uint',type='int'
741 ,help='Field parameter value [default: %default]')
742 parser.add_option('--timetag_min-field', dest='timetag_minField',metavar='uint',type='int'
743 ,help='Field parameter value [default: %default]')
744 parser.add_option('--timetag_sec-field', dest='timetag_secField',metavar='uint',type='int'
745 ,help='Field parameter value [default: %default]')
746 parser.add_option('--stationid-field', dest='stationidField',default='@@@@@@@',metavar='aisstr6',type='string'
747 ,help='Field parameter value [default: %default]')
748 parser.add_option('--station_longitude-field', dest='station_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
749 ,help='Field parameter value [default: %default]')
750 parser.add_option('--station_latitude-field', dest='station_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
751 ,help='Field parameter value [default: %default]')
752 parser.add_option('--whale_longitude-field', dest='whale_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
753 ,help='Field parameter value [default: %default]')
754 parser.add_option('--whale_latitude-field', dest='whale_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
755 ,help='Field parameter value [default: %default]')
756 parser.add_option('--timetoexpire-field', dest='timetoexpireField',default=0,metavar='uint',type='int'
757 ,help='Field parameter value [default: %default]')
758 parser.add_option('--radius-field', dest='radiusField',default=65534,metavar='uint',type='int'
759 ,help='Field parameter value [default: %default]')
760 parser.add_option('--heading-field', dest='headingField',default=511,metavar='uint',type='int'
761 ,help='Field parameter value [default: %default]')
762 parser.add_option('--numWhales-field', dest='numWhalesField',default=0,metavar='uint',type='int'
763 ,help='Field parameter value [default: %default]')
764
765
766 if __name__=='__main__':
767
768 from optparse import OptionParser
769 parser = OptionParser(usage="%prog [options]",
770 version="%prog "+__version__)
771
772 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
773 help='run the documentation tests')
774 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
775 help='run the unit tests')
776 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
777 help='Make the test output verbose')
778
779
780
781 typeChoices = ('binary','nmeapayload','nmea')
782 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
783 ,default='nmeapayload'
784 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
785
786
787 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
788 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
789 ,default='std'
790 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
791
792 parser.add_option('-o','--output',dest='outputFileName',default=None,
793 help='Name of the python file to write [default: stdout]')
794
795 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
796 choices=fieldList,
797 help='Which fields to include in the output. Currently only for csv output [default: all]')
798
799 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
800 help='Print the field name for csv')
801
802 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
803 help='Print out an sql create command for the table.')
804
805 dbChoices = ('sqlite','postgres')
806 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
807 ,choices=dbChoices,type='choice'
808 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
809
810 addMsgOptions(parser)
811
812 (options,args) = parser.parse_args()
813 success=True
814
815 if options.doctest:
816 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
817 sys.argv= [sys.argv[0]]
818 if options.verbose: sys.argv.append('-v')
819 import doctest
820 numfail,numtests=doctest.testmod()
821 if numfail==0: print 'ok'
822 else:
823 print 'FAILED'
824 success=False
825
826 if not success: sys.exit('Something Failed')
827 del success
828
829 if options.unittest:
830 sys.argv = [sys.argv[0]]
831 if options.verbose: sys.argv.append('-v')
832 unittest.main()
833
834 outfile = sys.stdout
835 if None!=options.outputFileName:
836 outfile = file(options.outputFileName,'w')
837
838
839 if options.doEncode:
840
841 if None==options.timetag_monthField: parser.error("missing value for timetag_monthField")
842 if None==options.timetag_dayField: parser.error("missing value for timetag_dayField")
843 if None==options.timetag_hourField: parser.error("missing value for timetag_hourField")
844 if None==options.timetag_minField: parser.error("missing value for timetag_minField")
845 if None==options.timetag_secField: parser.error("missing value for timetag_secField")
846 if None==options.stationidField: parser.error("missing value for stationidField")
847 if None==options.station_longitudeField: parser.error("missing value for station_longitudeField")
848 if None==options.station_latitudeField: parser.error("missing value for station_latitudeField")
849 if None==options.whale_longitudeField: parser.error("missing value for whale_longitudeField")
850 if None==options.whale_latitudeField: parser.error("missing value for whale_latitudeField")
851 if None==options.timetoexpireField: parser.error("missing value for timetoexpireField")
852 if None==options.radiusField: parser.error("missing value for radiusField")
853 if None==options.headingField: parser.error("missing value for headingField")
854 if None==options.numWhalesField: parser.error("missing value for numWhalesField")
855 msgDict={
856 'dac': '366',
857 'fid': '1',
858 'efid': '2',
859 'timetag_month': options.timetag_monthField,
860 'timetag_day': options.timetag_dayField,
861 'timetag_hour': options.timetag_hourField,
862 'timetag_min': options.timetag_minField,
863 'timetag_sec': options.timetag_secField,
864 'stationid': options.stationidField,
865 'station_longitude': options.station_longitudeField,
866 'station_latitude': options.station_latitudeField,
867 'whale_longitude': options.whale_longitudeField,
868 'whale_latitude': options.whale_latitudeField,
869 'timetoexpire': options.timetoexpireField,
870 'radius': options.radiusField,
871 'heading': options.headingField,
872 'numWhales': options.numWhalesField,
873 }
874
875 bits = encode(msgDict)
876 if 'binary'==options.ioType: print str(bits)
877 elif 'nmeapayload'==options.ioType:
878
879 print "bitLen",len(bits)
880 bitLen=len(bits)
881 if bitLen%6!=0:
882 bits = bits + BitVector(size=(6 - (bitLen%6)))
883 print "result:",binary.bitvectoais6(bits)[0]
884
885
886
887 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
888 else: sys.exit('ERROR: unknown ioType. Help!')
889
890
891 if options.sqlCreate:
892 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
893
894 if options.printCsvfieldList:
895
896 if None == options.fieldList: options.fieldList = fieldList
897 import StringIO
898 buf = StringIO.StringIO()
899 for field in options.fieldList:
900 buf.write(field+',')
901 result = buf.getvalue()
902 if result[-1] == ',': print result[:-1]
903 else: print result
904
905 if options.doDecode:
906 for msg in args:
907 bv = None
908
909 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
910
911
912 bv = binary.ais6tobitvec(msg.split(',')[5])
913 else:
914
915 binaryMsg=True
916 for c in msg:
917 if c not in ('0','1'):
918 binaryMsg=False
919 break
920 if binaryMsg:
921 bv = BitVector(bitstring=msg)
922 else:
923 bv = binary.ais6tobitvec(msg)
924
925 printFields(decode(bv)
926 ,out=outfile
927 ,format=options.outputType
928 ,fieldList=options.fieldList
929 ,dbType=options.dbType
930 )
931