1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-03-31 $'.split()[1]
5 __author__ = 'xmlbinmsg'
6
7 __doc__='''
8
9 Autogenerated python functions to serialize/deserialize binary messages.
10
11 Generated by: ./aisxmlbinmsg2py.py
12
13 Need to then wrap these functions with the outer AIS packet and then
14 convert the whole binary blob to a NMEA string. Those functions are
15 not currently provided in this file.
16
17 serialize: python to ais binary
18 deserialize: ais binary to python
19
20 The generated code uses translators.py, binary.py, and aisstring.py
21 which should be packaged with the resulting files.
22
23
24 @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3
25 @requires: U{BitVector<http://cheeseshop.python.org/pypi/BitVector>}
26
27 @author: '''+__author__+'''
28 @version: ''' + __version__ +'''
29 @var __date__: Date of last svn commit
30 @undocumented: __version__ __author__ __doc__ parser
31 @status: under development
32 @license: Generated code has no license
33 @todo: FIX: put in a description of the message here with fields and types.
34 '''
35
36 import sys
37 from decimal import Decimal
38 from BitVector import BitVector
39
40 import binary, aisstring
41
42
43 TrueBV = BitVector(bitstring="1")
44 "Why always rebuild the True bit? This should speed things up a bunch"
45 FalseBV = BitVector(bitstring="0")
46 "Why always rebuild the False bit? This should speed things up a bunch"
47
48
49 fieldList = (
50 'MessageID',
51 'RepeatIndicator',
52 'UserID',
53 'AISversion',
54 'IMOnumber',
55 'callsign',
56 'name',
57 'shipandcargo',
58 'dimA',
59 'dimB',
60 'dimC',
61 'dimD',
62 'fixtype',
63 'ETAminute',
64 'ETAhour',
65 'ETAday',
66 'ETAmonth',
67 'draught',
68 'destination',
69 'dte',
70 'Spare',
71 )
72
73 fieldListPostgres = (
74 'MessageID',
75 'RepeatIndicator',
76 'UserID',
77 'AISversion',
78 'IMOnumber',
79 'callsign',
80 'name',
81 'shipandcargo',
82 'dimA',
83 'dimB',
84 'dimC',
85 'dimD',
86 'fixtype',
87 'ETAminute',
88 'ETAhour',
89 'ETAday',
90 'ETAmonth',
91 'draught',
92 'destination',
93 'dte',
94 'Spare',
95 )
96
97 toPgFields = {
98 }
99 '''
100 Go to the Postgis field names from the straight field name
101 '''
102
103 fromPgFields = {
104 }
105 '''
106 Go from the Postgis field names to the straight field name
107 '''
108
109 pgTypes = {
110 }
111 '''
112 Lookup table for each postgis field name to get its type.
113 '''
114
115 -def encode(params, validate=False):
116 '''Create a shipdata binary message payload to pack into an AIS Msg shipdata.
117
118 Fields in params:
119 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5")
120 - RepeatIndicator(uint): Indicated how many times a message has been repeated
121 - UserID(uint): Unique ship identification number (MMSI)
122 - AISversion(uint): Compliant with what edition. 0 is the first edition.
123 - IMOnumber(uint): vessel identification number (different than mmsi)
124 - callsign(aisstr6): Ship radio call sign
125 - name(aisstr6): Vessel name
126 - shipandcargo(uint): what
127 - dimA(uint): Distance from bow to reference position
128 - dimB(uint): Distance from reference position to stern
129 - dimC(uint): Distance from port side to reference position
130 - dimD(uint): Distance from reference position to starboard side
131 - fixtype(uint): Method used for positioning
132 - ETAminute(uint): Estimated time of arrival - minutes
133 - ETAhour(uint): Estimated time of arrival - hour
134 - ETAday(uint): Estimated time of arrival - day
135 - ETAmonth(uint): Estimated time of arrival - month
136 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater
137 - destination(aisstr6): Where is the vessel going
138 - dte(uint): Data terminal ready
139 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
140 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
141 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
142 @rtype: BitVector
143 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
144 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
145 '''
146
147 bvList = []
148 bvList.append(binary.setBitVectorSize(BitVector(intVal=5),6))
149 if 'RepeatIndicator' in params:
150 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2))
151 else:
152 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
153 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30))
154 if 'AISversion' in params:
155 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['AISversion']),2))
156 else:
157 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
158 if 'IMOnumber' in params:
159 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['IMOnumber']),30))
160 else:
161 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),30))
162 if 'callsign' in params:
163 bvList.append(aisstring.encode(params['callsign'],42))
164 else:
165 bvList.append(aisstring.encode('@@@@@@@',42))
166 if 'name' in params:
167 bvList.append(aisstring.encode(params['name'],120))
168 else:
169 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@@@@@@',120))
170 if 'shipandcargo' in params:
171 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['shipandcargo']),8))
172 else:
173 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8))
174 if 'dimA' in params:
175 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimA']),9))
176 else:
177 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),9))
178 if 'dimB' in params:
179 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimB']),9))
180 else:
181 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),9))
182 if 'dimC' in params:
183 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimC']),6))
184 else:
185 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6))
186 if 'dimD' in params:
187 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dimD']),6))
188 else:
189 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),6))
190 if 'fixtype' in params:
191 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['fixtype']),4))
192 else:
193 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
194 if 'ETAminute' in params:
195 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAminute']),6))
196 else:
197 bvList.append(binary.setBitVectorSize(BitVector(intVal=60),6))
198 if 'ETAhour' in params:
199 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAhour']),5))
200 else:
201 bvList.append(binary.setBitVectorSize(BitVector(intVal=24),5))
202 if 'ETAday' in params:
203 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAday']),5))
204 else:
205 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),5))
206 if 'ETAmonth' in params:
207 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETAmonth']),4))
208 else:
209 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
210 if 'draught' in params:
211 bvList.append(binary.setBitVectorSize(BitVector(intVal=int((Decimal(params['draught'])*Decimal('10')))),8))
212 else:
213 bvList.append(binary.setBitVectorSize(BitVector(intVal=int(0)),8))
214 if 'destination' in params:
215 bvList.append(aisstring.encode(params['destination'],120))
216 else:
217 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@@@@@@',120))
218 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dte']),1))
219 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),1))
220
221 return binary.joinBV(bvList)
222
223 -def decode(bv, validate=False):
224 '''Unpack a shipdata message
225
226 Fields in params:
227 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5")
228 - RepeatIndicator(uint): Indicated how many times a message has been repeated
229 - UserID(uint): Unique ship identification number (MMSI)
230 - AISversion(uint): Compliant with what edition. 0 is the first edition.
231 - IMOnumber(uint): vessel identification number (different than mmsi)
232 - callsign(aisstr6): Ship radio call sign
233 - name(aisstr6): Vessel name
234 - shipandcargo(uint): what
235 - dimA(uint): Distance from bow to reference position
236 - dimB(uint): Distance from reference position to stern
237 - dimC(uint): Distance from port side to reference position
238 - dimD(uint): Distance from reference position to starboard side
239 - fixtype(uint): Method used for positioning
240 - ETAminute(uint): Estimated time of arrival - minutes
241 - ETAhour(uint): Estimated time of arrival - hour
242 - ETAday(uint): Estimated time of arrival - day
243 - ETAmonth(uint): Estimated time of arrival - month
244 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater
245 - destination(aisstr6): Where is the vessel going
246 - dte(uint): Data terminal ready
247 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
248 @type bv: BitVector
249 @param bv: Bits defining a message
250 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
251 @rtype: dict
252 @return: params
253 '''
254
255
256
257
258 r = {}
259 r['MessageID']=5
260 r['RepeatIndicator']=int(bv[6:8])
261 r['UserID']=int(bv[8:38])
262 r['AISversion']=int(bv[38:40])
263 r['IMOnumber']=int(bv[40:70])
264 r['callsign']=aisstring.decode(bv[70:112])
265 r['name']=aisstring.decode(bv[112:232])
266 r['shipandcargo']=int(bv[232:240])
267 r['dimA']=int(bv[240:249])
268 r['dimB']=int(bv[249:258])
269 r['dimC']=int(bv[258:264])
270 r['dimD']=int(bv[264:270])
271 r['fixtype']=int(bv[270:274])
272 r['ETAminute']=int(bv[274:280])
273 r['ETAhour']=int(bv[280:285])
274 r['ETAday']=int(bv[285:290])
275 r['ETAmonth']=int(bv[290:294])
276 r['draught']=Decimal(int(bv[294:302]))/Decimal('10')
277 r['destination']=aisstring.decode(bv[302:422])
278 r['dte']=int(bv[422:423])
279 r['Spare']=0
280 return r
281
284
287
290
292 return int(bv[38:40])
293
295 return int(bv[40:70])
296
299
302
304 return int(bv[232:240])
305
307 return int(bv[240:249])
308
310 return int(bv[249:258])
311
313 return int(bv[258:264])
314
316 return int(bv[264:270])
317
319 return int(bv[270:274])
320
322 return int(bv[274:280])
323
325 return int(bv[280:285])
326
328 return int(bv[285:290])
329
331 return int(bv[290:294])
332
334 return Decimal(int(bv[294:302]))/Decimal('10')
335
338
340 return int(bv[422:423])
341
344
345
347 out.write("<h3>shipdata<h3>\n")
348 out.write("<table border=\"1\">\n")
349 out.write("<tr bgcolor=\"orange\">\n")
350 out.write("<th align=\"left\">Field Name</th>\n")
351 out.write("<th align=\"left\">Type</th>\n")
352 out.write("<th align=\"left\">Value</th>\n")
353 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
354 out.write("<th align=\"left\">Units</th>\n")
355 out.write("\n")
356 out.write("<tr>\n")
357 out.write("<td>MessageID</td>\n")
358 out.write("<td>uint</td>\n")
359 if 'MessageID' in params:
360 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
361 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
362 out.write("</tr>\n")
363 out.write("\n")
364 out.write("<tr>\n")
365 out.write("<td>RepeatIndicator</td>\n")
366 out.write("<td>uint</td>\n")
367 if 'RepeatIndicator' in params:
368 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n")
369 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut:
370 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>")
371 else:
372 out.write("<td><i>Missing LUT entry</i></td>")
373 out.write("</tr>\n")
374 out.write("\n")
375 out.write("<tr>\n")
376 out.write("<td>UserID</td>\n")
377 out.write("<td>uint</td>\n")
378 if 'UserID' in params:
379 out.write(" <td>"+str(params['UserID'])+"</td>\n")
380 out.write(" <td>"+str(params['UserID'])+"</td>\n")
381 out.write("</tr>\n")
382 out.write("\n")
383 out.write("<tr>\n")
384 out.write("<td>AISversion</td>\n")
385 out.write("<td>uint</td>\n")
386 if 'AISversion' in params:
387 out.write(" <td>"+str(params['AISversion'])+"</td>\n")
388 out.write(" <td>"+str(params['AISversion'])+"</td>\n")
389 out.write("</tr>\n")
390 out.write("\n")
391 out.write("<tr>\n")
392 out.write("<td>IMOnumber</td>\n")
393 out.write("<td>uint</td>\n")
394 if 'IMOnumber' in params:
395 out.write(" <td>"+str(params['IMOnumber'])+"</td>\n")
396 out.write(" <td>"+str(params['IMOnumber'])+"</td>\n")
397 out.write("</tr>\n")
398 out.write("\n")
399 out.write("<tr>\n")
400 out.write("<td>callsign</td>\n")
401 out.write("<td>aisstr6</td>\n")
402 if 'callsign' in params:
403 out.write(" <td>"+str(params['callsign'])+"</td>\n")
404 out.write(" <td>"+str(params['callsign'])+"</td>\n")
405 out.write("</tr>\n")
406 out.write("\n")
407 out.write("<tr>\n")
408 out.write("<td>name</td>\n")
409 out.write("<td>aisstr6</td>\n")
410 if 'name' in params:
411 out.write(" <td>"+str(params['name'])+"</td>\n")
412 out.write(" <td>"+str(params['name'])+"</td>\n")
413 out.write("</tr>\n")
414 out.write("\n")
415 out.write("<tr>\n")
416 out.write("<td>shipandcargo</td>\n")
417 out.write("<td>uint</td>\n")
418 if 'shipandcargo' in params:
419 out.write(" <td>"+str(params['shipandcargo'])+"</td>\n")
420 if str(params['shipandcargo']) in shipandcargoDecodeLut:
421 out.write("<td>"+shipandcargoDecodeLut[str(params['shipandcargo'])]+"</td>")
422 else:
423 out.write("<td><i>Missing LUT entry</i></td>")
424 out.write("</tr>\n")
425 out.write("\n")
426 out.write("<tr>\n")
427 out.write("<td>dimA</td>\n")
428 out.write("<td>uint</td>\n")
429 if 'dimA' in params:
430 out.write(" <td>"+str(params['dimA'])+"</td>\n")
431 out.write(" <td>"+str(params['dimA'])+"</td>\n")
432 out.write("<td>m</td>\n")
433 out.write("</tr>\n")
434 out.write("\n")
435 out.write("<tr>\n")
436 out.write("<td>dimB</td>\n")
437 out.write("<td>uint</td>\n")
438 if 'dimB' in params:
439 out.write(" <td>"+str(params['dimB'])+"</td>\n")
440 out.write(" <td>"+str(params['dimB'])+"</td>\n")
441 out.write("<td>m</td>\n")
442 out.write("</tr>\n")
443 out.write("\n")
444 out.write("<tr>\n")
445 out.write("<td>dimC</td>\n")
446 out.write("<td>uint</td>\n")
447 if 'dimC' in params:
448 out.write(" <td>"+str(params['dimC'])+"</td>\n")
449 if str(params['dimC']) in dimCDecodeLut:
450 out.write("<td>"+dimCDecodeLut[str(params['dimC'])]+"</td>")
451 else:
452 out.write("<td><i>Missing LUT entry</i></td>")
453 out.write("<td>m</td>\n")
454 out.write("</tr>\n")
455 out.write("\n")
456 out.write("<tr>\n")
457 out.write("<td>dimD</td>\n")
458 out.write("<td>uint</td>\n")
459 if 'dimD' in params:
460 out.write(" <td>"+str(params['dimD'])+"</td>\n")
461 if str(params['dimD']) in dimDDecodeLut:
462 out.write("<td>"+dimDDecodeLut[str(params['dimD'])]+"</td>")
463 else:
464 out.write("<td><i>Missing LUT entry</i></td>")
465 out.write("<td>m</td>\n")
466 out.write("</tr>\n")
467 out.write("\n")
468 out.write("<tr>\n")
469 out.write("<td>fixtype</td>\n")
470 out.write("<td>uint</td>\n")
471 if 'fixtype' in params:
472 out.write(" <td>"+str(params['fixtype'])+"</td>\n")
473 if str(params['fixtype']) in fixtypeDecodeLut:
474 out.write("<td>"+fixtypeDecodeLut[str(params['fixtype'])]+"</td>")
475 else:
476 out.write("<td><i>Missing LUT entry</i></td>")
477 out.write("</tr>\n")
478 out.write("\n")
479 out.write("<tr>\n")
480 out.write("<td>ETAminute</td>\n")
481 out.write("<td>uint</td>\n")
482 if 'ETAminute' in params:
483 out.write(" <td>"+str(params['ETAminute'])+"</td>\n")
484 out.write(" <td>"+str(params['ETAminute'])+"</td>\n")
485 out.write("</tr>\n")
486 out.write("\n")
487 out.write("<tr>\n")
488 out.write("<td>ETAhour</td>\n")
489 out.write("<td>uint</td>\n")
490 if 'ETAhour' in params:
491 out.write(" <td>"+str(params['ETAhour'])+"</td>\n")
492 out.write(" <td>"+str(params['ETAhour'])+"</td>\n")
493 out.write("</tr>\n")
494 out.write("\n")
495 out.write("<tr>\n")
496 out.write("<td>ETAday</td>\n")
497 out.write("<td>uint</td>\n")
498 if 'ETAday' in params:
499 out.write(" <td>"+str(params['ETAday'])+"</td>\n")
500 out.write(" <td>"+str(params['ETAday'])+"</td>\n")
501 out.write("</tr>\n")
502 out.write("\n")
503 out.write("<tr>\n")
504 out.write("<td>ETAmonth</td>\n")
505 out.write("<td>uint</td>\n")
506 if 'ETAmonth' in params:
507 out.write(" <td>"+str(params['ETAmonth'])+"</td>\n")
508 out.write(" <td>"+str(params['ETAmonth'])+"</td>\n")
509 out.write("</tr>\n")
510 out.write("\n")
511 out.write("<tr>\n")
512 out.write("<td>draught</td>\n")
513 out.write("<td>udecimal</td>\n")
514 if 'draught' in params:
515 out.write(" <td>"+str(params['draught'])+"</td>\n")
516 out.write(" <td>"+str(params['draught'])+"</td>\n")
517 out.write("<td>m</td>\n")
518 out.write("</tr>\n")
519 out.write("\n")
520 out.write("<tr>\n")
521 out.write("<td>destination</td>\n")
522 out.write("<td>aisstr6</td>\n")
523 if 'destination' in params:
524 out.write(" <td>"+str(params['destination'])+"</td>\n")
525 out.write(" <td>"+str(params['destination'])+"</td>\n")
526 out.write("</tr>\n")
527 out.write("\n")
528 out.write("<tr>\n")
529 out.write("<td>dte</td>\n")
530 out.write("<td>uint</td>\n")
531 if 'dte' in params:
532 out.write(" <td>"+str(params['dte'])+"</td>\n")
533 if str(params['dte']) in dteDecodeLut:
534 out.write("<td>"+dteDecodeLut[str(params['dte'])]+"</td>")
535 else:
536 out.write("<td><i>Missing LUT entry</i></td>")
537 out.write("</tr>\n")
538 out.write("\n")
539 out.write("<tr>\n")
540 out.write("<td>Spare</td>\n")
541 out.write("<td>uint</td>\n")
542 if 'Spare' in params:
543 out.write(" <td>"+str(params['Spare'])+"</td>\n")
544 out.write(" <td>"+str(params['Spare'])+"</td>\n")
545 out.write("</tr>\n")
546 out.write("</table>\n")
547
548 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
549 '''Print a shipdata message to stdout.
550
551 Fields in params:
552 - MessageID(uint): AIS message number. Must be 5 (field automatically set to "5")
553 - RepeatIndicator(uint): Indicated how many times a message has been repeated
554 - UserID(uint): Unique ship identification number (MMSI)
555 - AISversion(uint): Compliant with what edition. 0 is the first edition.
556 - IMOnumber(uint): vessel identification number (different than mmsi)
557 - callsign(aisstr6): Ship radio call sign
558 - name(aisstr6): Vessel name
559 - shipandcargo(uint): what
560 - dimA(uint): Distance from bow to reference position
561 - dimB(uint): Distance from reference position to stern
562 - dimC(uint): Distance from port side to reference position
563 - dimD(uint): Distance from reference position to starboard side
564 - fixtype(uint): Method used for positioning
565 - ETAminute(uint): Estimated time of arrival - minutes
566 - ETAhour(uint): Estimated time of arrival - hour
567 - ETAday(uint): Estimated time of arrival - day
568 - ETAmonth(uint): Estimated time of arrival - month
569 - draught(udecimal): Maximum present static draught. 25.5 is 25.5 m or greater
570 - destination(aisstr6): Where is the vessel going
571 - dte(uint): Data terminal ready
572 - Spare(uint): Reserved for definition by a regional authority. (field automatically set to "0")
573 @param params: Dictionary of field names/values.
574 @param out: File like object to write to
575 @rtype: stdout
576 @return: text to out
577 '''
578
579 if 'std'==format:
580 out.write("shipdata:\n")
581 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n")
582 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n")
583 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n")
584 if 'AISversion' in params: out.write(" AISversion: "+str(params['AISversion'])+"\n")
585 if 'IMOnumber' in params: out.write(" IMOnumber: "+str(params['IMOnumber'])+"\n")
586 if 'callsign' in params: out.write(" callsign: "+str(params['callsign'])+"\n")
587 if 'name' in params: out.write(" name: "+str(params['name'])+"\n")
588 if 'shipandcargo' in params: out.write(" shipandcargo: "+str(params['shipandcargo'])+"\n")
589 if 'dimA' in params: out.write(" dimA: "+str(params['dimA'])+"\n")
590 if 'dimB' in params: out.write(" dimB: "+str(params['dimB'])+"\n")
591 if 'dimC' in params: out.write(" dimC: "+str(params['dimC'])+"\n")
592 if 'dimD' in params: out.write(" dimD: "+str(params['dimD'])+"\n")
593 if 'fixtype' in params: out.write(" fixtype: "+str(params['fixtype'])+"\n")
594 if 'ETAminute' in params: out.write(" ETAminute: "+str(params['ETAminute'])+"\n")
595 if 'ETAhour' in params: out.write(" ETAhour: "+str(params['ETAhour'])+"\n")
596 if 'ETAday' in params: out.write(" ETAday: "+str(params['ETAday'])+"\n")
597 if 'ETAmonth' in params: out.write(" ETAmonth: "+str(params['ETAmonth'])+"\n")
598 if 'draught' in params: out.write(" draught: "+str(params['draught'])+"\n")
599 if 'destination' in params: out.write(" destination: "+str(params['destination'])+"\n")
600 if 'dte' in params: out.write(" dte: "+str(params['dte'])+"\n")
601 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
602 elif 'csv'==format:
603 if None == options.fieldList:
604 options.fieldList = fieldList
605 needComma = False;
606 for field in fieldList:
607 if needComma: out.write(',')
608 needComma = True
609 if field in params:
610 out.write(str(params[field]))
611
612 out.write("\n")
613 elif 'html'==format:
614 printHtml(params,out)
615 elif 'sql'==format:
616 sqlInsertStr(params,out,dbType=dbType)
617 else:
618 print "ERROR: unknown format:",format
619 assert False
620
621 return
622
623 RepeatIndicatorEncodeLut = {
624 'default':'0',
625 'do not repeat any more':'3',
626 }
627
628 RepeatIndicatorDecodeLut = {
629 '0':'default',
630 '3':'do not repeat any more',
631 }
632
633 shipandcargoEncodeLut = {
634 'Wing in ground (WIG), all ships of this type':'20',
635 'Wing in ground (WIG), Hazardous catagory A':'21',
636 'Wing in ground (WIG), Hazardous catagory B':'22',
637 'Wing in ground (WIG), Hazardous catagory C':'23',
638 'Wing in ground (WIG), Hazardous catagory D':'24',
639 'Wing in ground (WIG), Reserved for future use':'25',
640 'Wing in ground (WIG), Reserved for future use':'26',
641 'Wing in ground (WIG), Reserved for future use':'27',
642 'Wing in ground (WIG), Reserved for future use':'28',
643 'Wing in ground (WIG), No additional information':'29',
644 'fishing':'30',
645 'towing':'31',
646 'towing length exceeds 200m or breadth exceeds 25m':'32',
647 'dredging or underwater ops':'33',
648 'diving ops':'34',
649 'military ops':'35',
650 'sailing':'36',
651 'pleasure craft':'37',
652 'reserved':'38',
653 'reserved':'39',
654 'High speed craft (HSC), all ships of this type':'40',
655 'High speed craft (HSC), Hazardous catagory A':'41',
656 'High speed craft (HSC), Hazardous catagory B':'42',
657 'High speed craft (HSC), Hazardous catagory C':'43',
658 'High speed craft (HSC), Hazardous catagory D':'44',
659 'High speed craft (HSC), Reserved for future use':'45',
660 'High speed craft (HSC), Reserved for future use':'46',
661 'High speed craft (HSC), Reserved for future use':'47',
662 'High speed craft (HSC), Reserved for future use':'48',
663 'High speed craft (HSC), No additional information':'49',
664 'pilot vessel':'50',
665 'search and rescue vessel':'51',
666 'tug':'52',
667 'port tender':'53',
668 'anti-polution equipment':'54',
669 'law enforcement':'55',
670 'spare - local vessel':'56',
671 'spare - local vessel':'57',
672 'medical transport':'58',
673 'ship according to RR Resolution No. 18':'59',
674 'passenger, all ships of this type':'60',
675 'passenger, Hazardous catagory A':'61',
676 'passenger, Hazardous catagory B':'62',
677 'passenger, Hazardous catagory C':'63',
678 'passenger, Hazardous catagory D':'64',
679 'passenger, Reserved for future use':'65',
680 'passenger, Reserved for future use':'66',
681 'passenger, Reserved for future use':'67',
682 'passenger, Reserved for future use':'68',
683 'passenger, No additional information':'69',
684 'cargo, all ships of this type':'70',
685 'cargo, Hazardous catagory A':'71',
686 'cargo, Hazardous catagory B':'72',
687 'cargo, Hazardous catagory C':'73',
688 'cargo, Hazardous catagory D':'74',
689 'cargo, Reserved for future use':'75',
690 'cargo, Reserved for future use':'76',
691 'cargo, Reserved for future use':'77',
692 'cargo, Reserved for future use':'78',
693 'cargo, No additional information':'79',
694 'tanker, all ships of this type':'80',
695 'tanker, Hazardous catagory A':'81',
696 'tanker, Hazardous catagory B':'82',
697 'tanker, Hazardous catagory C':'83',
698 'tanker, Hazardous catagory D':'84',
699 'tanker, Reserved for future use':'85',
700 'tanker, Reserved for future use':'86',
701 'tanker, Reserved for future use':'87',
702 'tanker, Reserved for future use':'88',
703 'tanker, No additional information':'89',
704 'other type, all ships of this type':'90',
705 'other type, Hazardous catagory A':'91',
706 'other type, Hazardous catagory B':'92',
707 'other type, Hazardous catagory C':'93',
708 'other type, Hazardous catagory D':'94',
709 'other type, Reserved for future use':'95',
710 'other type, Reserved for future use':'96',
711 'other type, Reserved for future use':'97',
712 'other type, Reserved for future use':'98',
713 'other type, No additional information':'99',
714 }
715
716 shipandcargoDecodeLut = {
717 '20':'Wing in ground (WIG), all ships of this type',
718 '21':'Wing in ground (WIG), Hazardous catagory A',
719 '22':'Wing in ground (WIG), Hazardous catagory B',
720 '23':'Wing in ground (WIG), Hazardous catagory C',
721 '24':'Wing in ground (WIG), Hazardous catagory D',
722 '25':'Wing in ground (WIG), Reserved for future use',
723 '26':'Wing in ground (WIG), Reserved for future use',
724 '27':'Wing in ground (WIG), Reserved for future use',
725 '28':'Wing in ground (WIG), Reserved for future use',
726 '29':'Wing in ground (WIG), No additional information',
727 '30':'fishing',
728 '31':'towing',
729 '32':'towing length exceeds 200m or breadth exceeds 25m',
730 '33':'dredging or underwater ops',
731 '34':'diving ops',
732 '35':'military ops',
733 '36':'sailing',
734 '37':'pleasure craft',
735 '38':'reserved',
736 '39':'reserved',
737 '40':'High speed craft (HSC), all ships of this type',
738 '41':'High speed craft (HSC), Hazardous catagory A',
739 '42':'High speed craft (HSC), Hazardous catagory B',
740 '43':'High speed craft (HSC), Hazardous catagory C',
741 '44':'High speed craft (HSC), Hazardous catagory D',
742 '45':'High speed craft (HSC), Reserved for future use',
743 '46':'High speed craft (HSC), Reserved for future use',
744 '47':'High speed craft (HSC), Reserved for future use',
745 '48':'High speed craft (HSC), Reserved for future use',
746 '49':'High speed craft (HSC), No additional information',
747 '50':'pilot vessel',
748 '51':'search and rescue vessel',
749 '52':'tug',
750 '53':'port tender',
751 '54':'anti-polution equipment',
752 '55':'law enforcement',
753 '56':'spare - local vessel',
754 '57':'spare - local vessel',
755 '58':'medical transport',
756 '59':'ship according to RR Resolution No. 18',
757 '60':'passenger, all ships of this type',
758 '61':'passenger, Hazardous catagory A',
759 '62':'passenger, Hazardous catagory B',
760 '63':'passenger, Hazardous catagory C',
761 '64':'passenger, Hazardous catagory D',
762 '65':'passenger, Reserved for future use',
763 '66':'passenger, Reserved for future use',
764 '67':'passenger, Reserved for future use',
765 '68':'passenger, Reserved for future use',
766 '69':'passenger, No additional information',
767 '70':'cargo, all ships of this type',
768 '71':'cargo, Hazardous catagory A',
769 '72':'cargo, Hazardous catagory B',
770 '73':'cargo, Hazardous catagory C',
771 '74':'cargo, Hazardous catagory D',
772 '75':'cargo, Reserved for future use',
773 '76':'cargo, Reserved for future use',
774 '77':'cargo, Reserved for future use',
775 '78':'cargo, Reserved for future use',
776 '79':'cargo, No additional information',
777 '80':'tanker, all ships of this type',
778 '81':'tanker, Hazardous catagory A',
779 '82':'tanker, Hazardous catagory B',
780 '83':'tanker, Hazardous catagory C',
781 '84':'tanker, Hazardous catagory D',
782 '85':'tanker, Reserved for future use',
783 '86':'tanker, Reserved for future use',
784 '87':'tanker, Reserved for future use',
785 '88':'tanker, Reserved for future use',
786 '89':'tanker, No additional information',
787 '90':'other type, all ships of this type',
788 '91':'other type, Hazardous catagory A',
789 '92':'other type, Hazardous catagory B',
790 '93':'other type, Hazardous catagory C',
791 '94':'other type, Hazardous catagory D',
792 '95':'other type, Reserved for future use',
793 '96':'other type, Reserved for future use',
794 '97':'other type, Reserved for future use',
795 '98':'other type, Reserved for future use',
796 '99':'other type, No additional information',
797 }
798
799 dimCEncodeLut = {
800 '63 m or greater':'63',
801 }
802
803 dimCDecodeLut = {
804 '63':'63 m or greater',
805 }
806
807 dimDEncodeLut = {
808 '63 m or greater':'63',
809 }
810
811 dimDDecodeLut = {
812 '63':'63 m or greater',
813 }
814
815 fixtypeEncodeLut = {
816 'undefined':'0',
817 'GPS':'1',
818 'GLONASS':'2',
819 'combined GPS/GLONASS':'3',
820 'Loran-C':'4',
821 'Chayka':'5',
822 'integrated navigation system':'6',
823 'surveyed':'7',
824 }
825
826 fixtypeDecodeLut = {
827 '0':'undefined',
828 '1':'GPS',
829 '2':'GLONASS',
830 '3':'combined GPS/GLONASS',
831 '4':'Loran-C',
832 '5':'Chayka',
833 '6':'integrated navigation system',
834 '7':'surveyed',
835 }
836
837 dteEncodeLut = {
838 'available':'0',
839 'not available':'1',
840 }
841
842 dteDecodeLut = {
843 '0':'available',
844 '1':'not available',
845 }
846
847
848
849
850
851 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
852 ,addCoastGuardFields=True
853 ,dbType='postgres'
854 ):
855 '''
856 Return the SQL CREATE command for this message type
857 @param outfile: file like object to print to.
858 @param fields: which fields to put in the create. Defaults to all.
859 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
860 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
861 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
862 @type addCoastGuardFields: bool
863 @return: sql create string
864 @rtype: str
865
866 @see: sqlCreate
867 '''
868
869 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
870
871 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
872 '''
873 Return the sqlhelp object to create the table.
874
875 @param fields: which fields to put in the create. Defaults to all.
876 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
877 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
878 @type addCoastGuardFields: bool
879 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
880 @return: An object that can be used to generate a return
881 @rtype: sqlhelp.create
882 '''
883 if None == fields: fields = fieldList
884 import sqlhelp
885 c = sqlhelp.create('shipdata',dbType=dbType)
886 c.addPrimaryKey()
887 if 'MessageID' in fields: c.addInt ('MessageID')
888 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator')
889 if 'UserID' in fields: c.addInt ('UserID')
890 if 'AISversion' in fields: c.addInt ('AISversion')
891 if 'IMOnumber' in fields: c.addInt ('IMOnumber')
892 if 'callsign' in fields: c.addVarChar('callsign',7)
893 if 'name' in fields: c.addVarChar('name',20)
894 if 'shipandcargo' in fields: c.addInt ('shipandcargo')
895 if 'dimA' in fields: c.addInt ('dimA')
896 if 'dimB' in fields: c.addInt ('dimB')
897 if 'dimC' in fields: c.addInt ('dimC')
898 if 'dimD' in fields: c.addInt ('dimD')
899 if 'fixtype' in fields: c.addInt ('fixtype')
900 if 'ETAminute' in fields: c.addInt ('ETAminute')
901 if 'ETAhour' in fields: c.addInt ('ETAhour')
902 if 'ETAday' in fields: c.addInt ('ETAday')
903 if 'ETAmonth' in fields: c.addInt ('ETAmonth')
904 if 'draught' in fields: c.addDecimal('draught',3,1)
905 if 'destination' in fields: c.addVarChar('destination',20)
906 if 'dte' in fields: c.addInt ('dte')
907 if 'Spare' in fields: c.addInt ('Spare')
908
909 if addCoastGuardFields:
910
911
912
913
914
915 c.addVarChar('cg_r',15)
916 c.addInt('cg_sec')
917
918 c.addTimestamp('cg_timestamp')
919
920 return c
921
922 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
923 '''
924 Return the SQL INSERT command for this message type
925 @param params: dictionary of values keyed by field name
926 @param outfile: file like object to print to.
927 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
928 @return: sql create string
929 @rtype: str
930
931 @see: sqlCreate
932 '''
933 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
934
935
936 -def sqlInsert(params,extraParams=None,dbType='postgres'):
937 '''
938 Give the SQL INSERT statement
939 @param params: dict keyed by field name of values
940 @param extraParams: any extra fields that you have created beyond the normal ais message fields
941 @rtype: sqlhelp.insert
942 @return: insert class instance
943 @todo: allow optional type checking of params?
944 @warning: this will take invalid keys happily and do what???
945 '''
946 import sqlhelp
947 i = sqlhelp.insert('shipdata',dbType=dbType)
948
949 if dbType=='postgres':
950 finished = []
951 for key in params:
952 if key in finished:
953 continue
954
955 if key not in toPgFields and key not in fromPgFields:
956 if type(params[key])==Decimal: i.add(key,float(params[key]))
957 else: i.add(key,params[key])
958 else:
959 if key in fromPgFields:
960 val = params[key]
961
962 i.addPostGIS(key,val)
963 finished.append(key)
964 else:
965
966 pgName = toPgFields[key]
967
968 valStr=pgTypes[pgName]+'('
969 vals = []
970 for nonPgKey in fromPgFields[pgName]:
971 vals.append(str(params[nonPgKey]))
972 finished.append(nonPgKey)
973 valStr+=' '.join(vals)+')'
974 i.addPostGIS(pgName,valStr)
975 else:
976 for key in params:
977 if type(params[key])==Decimal: i.add(key,float(params[key]))
978 else: i.add(key,params[key])
979
980 if None != extraParams:
981 for key in extraParams:
982 i.add(key,extraParams[key])
983
984 return i
985
986
987
988
989
992 '''
993 Return the LaTeX definition table for this message type
994 @param outfile: file like object to print to.
995 @type outfile: file obj
996 @return: LaTeX table string via the outfile
997 @rtype: str
998
999 '''
1000 o = outfile
1001
1002 o.write('''
1003 \\begin{table}%[htb]
1004 \\centering
1005 \\begin{tabular}{|l|c|l|}
1006 \\hline
1007 Parameter & Number of bits & Description
1008 \\\\ \\hline\\hline
1009 MessageID & 6 & AIS message number. Must be 5 \\\\ \hline
1010 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline
1011 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline
1012 AISversion & 2 & Compliant with what edition. 0 is the first edition. \\\\ \hline
1013 IMOnumber & 30 & vessel identification number (different than mmsi) \\\\ \hline
1014 callsign & 42 & Ship radio call sign \\\\ \hline
1015 name & 120 & Vessel name \\\\ \hline
1016 shipandcargo & 8 & Type of ship and cargo type. FIX: need to verify that I got this lookup table right. Also need to handle entryranges in the lookup table \\\\ \hline
1017 dimA & 9 & Distance from bow to reference position \\\\ \hline
1018 dimB & 9 & Distance from reference position to stern \\\\ \hline
1019 dimC & 6 & Distance from port side to reference position \\\\ \hline
1020 dimD & 6 & Distance from reference position to starboard side \\\\ \hline
1021 fixtype & 4 & Method used for positioning \\\\ \hline
1022 ETAminute & 6 & Estimated time of arrival - minutes \\\\ \hline
1023 ETAhour & 5 & Estimated time of arrival - hour \\\\ \hline
1024 ETAday & 5 & Estimated time of arrival - day \\\\ \hline
1025 ETAmonth & 4 & Estimated time of arrival - month \\\\ \hline
1026 draught & 8 & Maximum present static draught. 25.5 is 25.5 m or greater \\\\ \hline
1027 destination & 120 & Where is the vessel going \\\\ \hline
1028 dte & 1 & Data terminal ready \\\\ \hline
1029 Spare & 1 & Reserved for definition by a regional authority.\\\\ \\hline \\hline
1030 Total bits & 424 & Appears to take 2 slots \\\\ \\hline
1031 \\end{tabular}
1032 \\caption{AIS message number 5: Class A vessel data report}
1033 \\label{tab:shipdata}
1034 \\end{table}
1035 ''')
1036
1037
1038
1039
1040
1041 import unittest
1043 '''Return a params file base on the testvalue tags.
1044 @rtype: dict
1045 @return: params based on testvalue tags
1046 '''
1047 params = {}
1048 params['MessageID'] = 5
1049 params['RepeatIndicator'] = 1
1050 params['UserID'] = 1193046
1051 params['AISversion'] = 0
1052 params['IMOnumber'] = 3210
1053 params['callsign'] = 'PIRATE1'
1054 params['name'] = 'BLACK PEARL@@@@@@@@@'
1055 params['shipandcargo'] = 55
1056 params['dimA'] = 10
1057 params['dimB'] = 11
1058 params['dimC'] = 12
1059 params['dimD'] = 13
1060 params['fixtype'] = 1
1061 params['ETAminute'] = 54
1062 params['ETAhour'] = 9
1063 params['ETAday'] = 28
1064 params['ETAmonth'] = 2
1065 params['draught'] = Decimal('21.1')
1066 params['destination'] = 'NOWHERE@@@@@@@@@@@@@'
1067 params['dte'] = 0
1068 params['Spare'] = 0
1069
1070 return params
1071
1073 '''Use testvalue tag text from each type to build test case the shipdata message'''
1075
1076 params = testParams()
1077 bits = encode(params)
1078 r = decode(bits)
1079
1080
1081 self.failUnlessEqual(r['MessageID'],params['MessageID'])
1082 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
1083 self.failUnlessEqual(r['UserID'],params['UserID'])
1084 self.failUnlessEqual(r['AISversion'],params['AISversion'])
1085 self.failUnlessEqual(r['IMOnumber'],params['IMOnumber'])
1086 self.failUnlessEqual(r['callsign'],params['callsign'])
1087 self.failUnlessEqual(r['name'],params['name'])
1088 self.failUnlessEqual(r['shipandcargo'],params['shipandcargo'])
1089 self.failUnlessEqual(r['dimA'],params['dimA'])
1090 self.failUnlessEqual(r['dimB'],params['dimB'])
1091 self.failUnlessEqual(r['dimC'],params['dimC'])
1092 self.failUnlessEqual(r['dimD'],params['dimD'])
1093 self.failUnlessEqual(r['fixtype'],params['fixtype'])
1094 self.failUnlessEqual(r['ETAminute'],params['ETAminute'])
1095 self.failUnlessEqual(r['ETAhour'],params['ETAhour'])
1096 self.failUnlessEqual(r['ETAday'],params['ETAday'])
1097 self.failUnlessEqual(r['ETAmonth'],params['ETAmonth'])
1098 self.failUnlessAlmostEqual(r['draught'],params['draught'],1)
1099 self.failUnlessEqual(r['destination'],params['destination'])
1100 self.failUnlessEqual(r['dte'],params['dte'])
1101 self.failUnlessEqual(r['Spare'],params['Spare'])
1102
1104 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
1105 help='decode a "shipdata" AIS message')
1106 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
1107 help='encode a "shipdata" AIS message')
1108 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
1109 ,help='Field parameter value [default: %default]')
1110 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
1111 ,help='Field parameter value [default: %default]')
1112 parser.add_option('--AISversion-field', dest='AISversionField',default=0,metavar='uint',type='int'
1113 ,help='Field parameter value [default: %default]')
1114 parser.add_option('--IMOnumber-field', dest='IMOnumberField',default=0,metavar='uint',type='int'
1115 ,help='Field parameter value [default: %default]')
1116 parser.add_option('--callsign-field', dest='callsignField',default='@@@@@@@',metavar='aisstr6',type='string'
1117 ,help='Field parameter value [default: %default]')
1118 parser.add_option('--name-field', dest='nameField',default='@@@@@@@@@@@@@@@@@@@@',metavar='aisstr6',type='string'
1119 ,help='Field parameter value [default: %default]')
1120 parser.add_option('--shipandcargo-field', dest='shipandcargoField',default=0,metavar='uint',type='int'
1121 ,help='Field parameter value [default: %default]')
1122 parser.add_option('--dimA-field', dest='dimAField',default=0,metavar='uint',type='int'
1123 ,help='Field parameter value [default: %default]')
1124 parser.add_option('--dimB-field', dest='dimBField',default=0,metavar='uint',type='int'
1125 ,help='Field parameter value [default: %default]')
1126 parser.add_option('--dimC-field', dest='dimCField',default=0,metavar='uint',type='int'
1127 ,help='Field parameter value [default: %default]')
1128 parser.add_option('--dimD-field', dest='dimDField',default=0,metavar='uint',type='int'
1129 ,help='Field parameter value [default: %default]')
1130 parser.add_option('--fixtype-field', dest='fixtypeField',default=0,metavar='uint',type='int'
1131 ,help='Field parameter value [default: %default]')
1132 parser.add_option('--ETAminute-field', dest='ETAminuteField',default=60,metavar='uint',type='int'
1133 ,help='Field parameter value [default: %default]')
1134 parser.add_option('--ETAhour-field', dest='ETAhourField',default=24,metavar='uint',type='int'
1135 ,help='Field parameter value [default: %default]')
1136 parser.add_option('--ETAday-field', dest='ETAdayField',default=0,metavar='uint',type='int'
1137 ,help='Field parameter value [default: %default]')
1138 parser.add_option('--ETAmonth-field', dest='ETAmonthField',default=0,metavar='uint',type='int'
1139 ,help='Field parameter value [default: %default]')
1140 parser.add_option('--draught-field', dest='draughtField',default=Decimal('0'),metavar='udecimal',type='string'
1141 ,help='Field parameter value [default: %default]')
1142 parser.add_option('--destination-field', dest='destinationField',default='@@@@@@@@@@@@@@@@@@@@',metavar='aisstr6',type='string'
1143 ,help='Field parameter value [default: %default]')
1144 parser.add_option('--dte-field', dest='dteField',metavar='uint',type='int'
1145 ,help='Field parameter value [default: %default]')
1146
1147
1148 if __name__=='__main__':
1149
1150 from optparse import OptionParser
1151 parser = OptionParser(usage="%prog [options]",
1152 version="%prog "+__version__)
1153
1154 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
1155 help='run the documentation tests')
1156 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
1157 help='run the unit tests')
1158 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
1159 help='Make the test output verbose')
1160
1161
1162
1163 typeChoices = ('binary','nmeapayload','nmea')
1164 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
1165 ,default='nmeapayload'
1166 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
1167
1168
1169 outputChoices = ('std','html','csv','sql' )
1170 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
1171 ,default='std'
1172 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
1173
1174 parser.add_option('-o','--output',dest='outputFileName',default=None,
1175 help='Name of the python file to write [default: stdout]')
1176
1177 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
1178 choices=fieldList,
1179 help='Which fields to include in the output. Currently only for csv output [default: all]')
1180
1181 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
1182 help='Print the field name for csv')
1183
1184 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
1185 help='Print out an sql create command for the table.')
1186
1187 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
1188 help='Print a LaTeX table of the type')
1189
1190 dbChoices = ('sqlite','postgres')
1191 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
1192 ,choices=dbChoices,type='choice'
1193 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
1194
1195 addMsgOptions(parser)
1196
1197 (options,args) = parser.parse_args()
1198 success=True
1199
1200 if options.doctest:
1201 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
1202 sys.argv= [sys.argv[0]]
1203 if options.verbose: sys.argv.append('-v')
1204 import doctest
1205 numfail,numtests=doctest.testmod()
1206 if numfail==0: print 'ok'
1207 else:
1208 print 'FAILED'
1209 success=False
1210
1211 if not success: sys.exit('Something Failed')
1212 del success
1213
1214 if options.unittest:
1215 sys.argv = [sys.argv[0]]
1216 if options.verbose: sys.argv.append('-v')
1217 unittest.main()
1218
1219 outfile = sys.stdout
1220 if None!=options.outputFileName:
1221 outfile = file(options.outputFileName,'w')
1222
1223
1224 if options.doEncode:
1225
1226 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
1227 if None==options.UserIDField: parser.error("missing value for UserIDField")
1228 if None==options.AISversionField: parser.error("missing value for AISversionField")
1229 if None==options.IMOnumberField: parser.error("missing value for IMOnumberField")
1230 if None==options.callsignField: parser.error("missing value for callsignField")
1231 if None==options.nameField: parser.error("missing value for nameField")
1232 if None==options.shipandcargoField: parser.error("missing value for shipandcargoField")
1233 if None==options.dimAField: parser.error("missing value for dimAField")
1234 if None==options.dimBField: parser.error("missing value for dimBField")
1235 if None==options.dimCField: parser.error("missing value for dimCField")
1236 if None==options.dimDField: parser.error("missing value for dimDField")
1237 if None==options.fixtypeField: parser.error("missing value for fixtypeField")
1238 if None==options.ETAminuteField: parser.error("missing value for ETAminuteField")
1239 if None==options.ETAhourField: parser.error("missing value for ETAhourField")
1240 if None==options.ETAdayField: parser.error("missing value for ETAdayField")
1241 if None==options.ETAmonthField: parser.error("missing value for ETAmonthField")
1242 if None==options.draughtField: parser.error("missing value for draughtField")
1243 if None==options.destinationField: parser.error("missing value for destinationField")
1244 if None==options.dteField: parser.error("missing value for dteField")
1245 msgDict={
1246 'MessageID': '5',
1247 'RepeatIndicator': options.RepeatIndicatorField,
1248 'UserID': options.UserIDField,
1249 'AISversion': options.AISversionField,
1250 'IMOnumber': options.IMOnumberField,
1251 'callsign': options.callsignField,
1252 'name': options.nameField,
1253 'shipandcargo': options.shipandcargoField,
1254 'dimA': options.dimAField,
1255 'dimB': options.dimBField,
1256 'dimC': options.dimCField,
1257 'dimD': options.dimDField,
1258 'fixtype': options.fixtypeField,
1259 'ETAminute': options.ETAminuteField,
1260 'ETAhour': options.ETAhourField,
1261 'ETAday': options.ETAdayField,
1262 'ETAmonth': options.ETAmonthField,
1263 'draught': options.draughtField,
1264 'destination': options.destinationField,
1265 'dte': options.dteField,
1266 'Spare': '0',
1267 }
1268
1269 bits = encode(msgDict)
1270 if 'binary'==options.ioType: print str(bits)
1271 elif 'nmeapayload'==options.ioType:
1272
1273 print "bitLen",len(bits)
1274 bitLen=len(bits)
1275 if bitLen%6!=0:
1276 bits = bits + BitVector(size=(6 - (bitLen%6)))
1277 print "result:",binary.bitvectoais6(bits)[0]
1278
1279
1280
1281 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
1282 else: sys.exit('ERROR: unknown ioType. Help!')
1283
1284
1285 if options.sqlCreate:
1286 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
1287
1288 if options.latexDefinitionTable:
1289 latexDefinitionTable(outfile)
1290
1291 if options.printCsvfieldList:
1292
1293 if None == options.fieldList: options.fieldList = fieldList
1294 import StringIO
1295 buf = StringIO.StringIO()
1296 for field in options.fieldList:
1297 buf.write(field+',')
1298 result = buf.getvalue()
1299 if result[-1] == ',': print result[:-1]
1300 else: print result
1301
1302 if options.doDecode:
1303 for msg in args:
1304 bv = None
1305
1306 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
1307
1308
1309 bv = binary.ais6tobitvec(msg.split(',')[5])
1310 else:
1311
1312 binaryMsg=True
1313 for c in msg:
1314 if c not in ('0','1'):
1315 binaryMsg=False
1316 break
1317 if binaryMsg:
1318 bv = BitVector(bitstring=msg)
1319 else:
1320 bv = binary.ais6tobitvec(msg)
1321
1322 printFields(decode(bv)
1323 ,out=outfile
1324 ,format=options.outputType
1325 ,fieldList=options.fieldList
1326 ,dbType=options.dbType
1327 )
1328