1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-04-07 $'.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 'Time_year',
54 'Time_month',
55 'Time_day',
56 'Time_hour',
57 'Time_min',
58 'Time_sec',
59 'PositionAccuracy',
60 'Position_longitude',
61 'Position_latitude',
62 'fixtype',
63 'Spare',
64 'RAIM',
65 'state_syncstate',
66 'state_slottimeout',
67 'state_slotoffset',
68 )
69
70 fieldListPostgres = (
71 'MessageID',
72 'RepeatIndicator',
73 'UserID',
74 'Time_year',
75 'Time_month',
76 'Time_day',
77 'Time_hour',
78 'Time_min',
79 'Time_sec',
80 'PositionAccuracy',
81 'Position',
82 'fixtype',
83 'Spare',
84 'RAIM',
85 'state_syncstate',
86 'state_slottimeout',
87 'state_slotoffset',
88 )
89
90 toPgFields = {
91 'Position_longitude':'Position',
92 'Position_latitude':'Position',
93 }
94 '''
95 Go to the Postgis field names from the straight field name
96 '''
97
98 fromPgFields = {
99 'Position':('Position_longitude','Position_latitude',),
100 }
101 '''
102 Go from the Postgis field names to the straight field name
103 '''
104
105 pgTypes = {
106 'Position':'POINT',
107 }
108 '''
109 Lookup table for each postgis field name to get its type.
110 '''
111
112 -def encode(params, validate=False):
113 '''Create a bsreport binary message payload to pack into an AIS Msg bsreport.
114
115 Fields in params:
116 - MessageID(uint): AIS message number. Must be 4 (field automatically set to "4")
117 - RepeatIndicator(uint): Indicated how many times a message has been repeated
118 - UserID(uint): Unique ship identification number (MMSI)
119 - Time_year(uint): Current time stamp year 1-9999
120 - Time_month(uint): Current time stamp month 1..12
121 - Time_day(uint): Current time stamp day of the month 1..31
122 - Time_hour(uint): Current time stamp UTC hours 0..23
123 - Time_min(uint): Current time stamp minutes
124 - Time_sec(uint): Current time stamp seconds
125 - PositionAccuracy(uint): Accuracy of positioning fixes
126 - Position_longitude(decimal): Location of base station East West location
127 - Position_latitude(decimal): Location of base station North South location
128 - fixtype(uint): Method used for positioning
129 - Spare(uint): Not used. Should be set to zero. (field automatically set to "0")
130 - RAIM(bool): Receiver autonomous integrity monitoring flag
131 - state_syncstate(uint): Communications State - SOTDMA Sycronization state
132 - state_slottimeout(uint): Communications State - SOTDMA Frames remaining until a new slot is selected
133 - state_slotoffset(uint): Communications State - SOTDMA In what slot will the next transmission occur. BROKEN
134 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
135 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
136 @rtype: BitVector
137 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
138 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
139 '''
140
141 bvList = []
142 bvList.append(binary.setBitVectorSize(BitVector(intVal=4),6))
143 if 'RepeatIndicator' in params:
144 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2))
145 else:
146 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
147 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30))
148 if 'Time_year' in params:
149 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_year']),14))
150 else:
151 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),14))
152 if 'Time_month' in params:
153 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_month']),4))
154 else:
155 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
156 if 'Time_day' in params:
157 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_day']),5))
158 else:
159 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),5))
160 if 'Time_hour' in params:
161 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_hour']),5))
162 else:
163 bvList.append(binary.setBitVectorSize(BitVector(intVal=24),5))
164 if 'Time_min' in params:
165 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_min']),6))
166 else:
167 bvList.append(binary.setBitVectorSize(BitVector(intVal=60),6))
168 if 'Time_sec' in params:
169 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['Time_sec']),6))
170 else:
171 bvList.append(binary.setBitVectorSize(BitVector(intVal=60),6))
172 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['PositionAccuracy']),1))
173 if 'Position_longitude' in params:
174 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_longitude'])*Decimal('600000')),28))
175 else:
176 bvList.append(binary.bvFromSignedInt(108600000,28))
177 if 'Position_latitude' in params:
178 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_latitude'])*Decimal('600000')),27))
179 else:
180 bvList.append(binary.bvFromSignedInt(54600000,27))
181 if 'fixtype' in params:
182 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['fixtype']),4))
183 else:
184 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
185 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),10))
186 if params["RAIM"]: bvList.append(TrueBV)
187 else: bvList.append(FalseBV)
188 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['state_syncstate']),2))
189 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['state_slottimeout']),3))
190 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['state_slotoffset']),14))
191
192 return binary.joinBV(bvList)
193
194 -def decode(bv, validate=False):
195 '''Unpack a bsreport message
196
197 Fields in params:
198 - MessageID(uint): AIS message number. Must be 4 (field automatically set to "4")
199 - RepeatIndicator(uint): Indicated how many times a message has been repeated
200 - UserID(uint): Unique ship identification number (MMSI)
201 - Time_year(uint): Current time stamp year 1-9999
202 - Time_month(uint): Current time stamp month 1..12
203 - Time_day(uint): Current time stamp day of the month 1..31
204 - Time_hour(uint): Current time stamp UTC hours 0..23
205 - Time_min(uint): Current time stamp minutes
206 - Time_sec(uint): Current time stamp seconds
207 - PositionAccuracy(uint): Accuracy of positioning fixes
208 - Position_longitude(decimal): Location of base station East West location
209 - Position_latitude(decimal): Location of base station North South location
210 - fixtype(uint): Method used for positioning
211 - Spare(uint): Not used. Should be set to zero. (field automatically set to "0")
212 - RAIM(bool): Receiver autonomous integrity monitoring flag
213 - state_syncstate(uint): Communications State - SOTDMA Sycronization state
214 - state_slottimeout(uint): Communications State - SOTDMA Frames remaining until a new slot is selected
215 - state_slotoffset(uint): Communications State - SOTDMA In what slot will the next transmission occur. BROKEN
216 @type bv: BitVector
217 @param bv: Bits defining a message
218 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
219 @rtype: dict
220 @return: params
221 '''
222
223
224
225
226 r = {}
227 r['MessageID']=4
228 r['RepeatIndicator']=int(bv[6:8])
229 r['UserID']=int(bv[8:38])
230 r['Time_year']=int(bv[38:52])
231 r['Time_month']=int(bv[52:56])
232 r['Time_day']=int(bv[56:61])
233 r['Time_hour']=int(bv[61:66])
234 r['Time_min']=int(bv[66:72])
235 r['Time_sec']=int(bv[72:78])
236 r['PositionAccuracy']=int(bv[78:79])
237 r['Position_longitude']=Decimal(binary.signedIntFromBV(bv[79:107]))/Decimal('600000')
238 r['Position_latitude']=Decimal(binary.signedIntFromBV(bv[107:134]))/Decimal('600000')
239 r['fixtype']=int(bv[134:138])
240 r['Spare']=0
241 r['RAIM']=bool(int(bv[148:149]))
242 r['state_syncstate']=int(bv[149:151])
243 r['state_slottimeout']=int(bv[151:154])
244 r['state_slotoffset']=int(bv[154:168])
245 return r
246
249
252
255
257 return int(bv[38:52])
258
260 return int(bv[52:56])
261
263 return int(bv[56:61])
264
266 return int(bv[61:66])
267
269 return int(bv[66:72])
270
272 return int(bv[72:78])
273
275 return int(bv[78:79])
276
279
282
284 return int(bv[134:138])
285
288
290 return bool(int(bv[148:149]))
291
293 return int(bv[149:151])
294
296 return int(bv[151:154])
297
299 return int(bv[154:168])
300
301
303 out.write("<h3>bsreport<h3>\n")
304 out.write("<table border=\"1\">\n")
305 out.write("<tr bgcolor=\"orange\">\n")
306 out.write("<th align=\"left\">Field Name</th>\n")
307 out.write("<th align=\"left\">Type</th>\n")
308 out.write("<th align=\"left\">Value</th>\n")
309 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
310 out.write("<th align=\"left\">Units</th>\n")
311 out.write("\n")
312 out.write("<tr>\n")
313 out.write("<td>MessageID</td>\n")
314 out.write("<td>uint</td>\n")
315 if 'MessageID' in params:
316 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
317 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
318 out.write("</tr>\n")
319 out.write("\n")
320 out.write("<tr>\n")
321 out.write("<td>RepeatIndicator</td>\n")
322 out.write("<td>uint</td>\n")
323 if 'RepeatIndicator' in params:
324 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n")
325 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut:
326 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>")
327 else:
328 out.write("<td><i>Missing LUT entry</i></td>")
329 out.write("</tr>\n")
330 out.write("\n")
331 out.write("<tr>\n")
332 out.write("<td>UserID</td>\n")
333 out.write("<td>uint</td>\n")
334 if 'UserID' in params:
335 out.write(" <td>"+str(params['UserID'])+"</td>\n")
336 out.write(" <td>"+str(params['UserID'])+"</td>\n")
337 out.write("</tr>\n")
338 out.write("\n")
339 out.write("<tr>\n")
340 out.write("<td>Time_year</td>\n")
341 out.write("<td>uint</td>\n")
342 if 'Time_year' in params:
343 out.write(" <td>"+str(params['Time_year'])+"</td>\n")
344 out.write(" <td>"+str(params['Time_year'])+"</td>\n")
345 out.write("</tr>\n")
346 out.write("\n")
347 out.write("<tr>\n")
348 out.write("<td>Time_month</td>\n")
349 out.write("<td>uint</td>\n")
350 if 'Time_month' in params:
351 out.write(" <td>"+str(params['Time_month'])+"</td>\n")
352 out.write(" <td>"+str(params['Time_month'])+"</td>\n")
353 out.write("</tr>\n")
354 out.write("\n")
355 out.write("<tr>\n")
356 out.write("<td>Time_day</td>\n")
357 out.write("<td>uint</td>\n")
358 if 'Time_day' in params:
359 out.write(" <td>"+str(params['Time_day'])+"</td>\n")
360 out.write(" <td>"+str(params['Time_day'])+"</td>\n")
361 out.write("</tr>\n")
362 out.write("\n")
363 out.write("<tr>\n")
364 out.write("<td>Time_hour</td>\n")
365 out.write("<td>uint</td>\n")
366 if 'Time_hour' in params:
367 out.write(" <td>"+str(params['Time_hour'])+"</td>\n")
368 out.write(" <td>"+str(params['Time_hour'])+"</td>\n")
369 out.write("</tr>\n")
370 out.write("\n")
371 out.write("<tr>\n")
372 out.write("<td>Time_min</td>\n")
373 out.write("<td>uint</td>\n")
374 if 'Time_min' in params:
375 out.write(" <td>"+str(params['Time_min'])+"</td>\n")
376 out.write(" <td>"+str(params['Time_min'])+"</td>\n")
377 out.write("</tr>\n")
378 out.write("\n")
379 out.write("<tr>\n")
380 out.write("<td>Time_sec</td>\n")
381 out.write("<td>uint</td>\n")
382 if 'Time_sec' in params:
383 out.write(" <td>"+str(params['Time_sec'])+"</td>\n")
384 out.write(" <td>"+str(params['Time_sec'])+"</td>\n")
385 out.write("</tr>\n")
386 out.write("\n")
387 out.write("<tr>\n")
388 out.write("<td>PositionAccuracy</td>\n")
389 out.write("<td>uint</td>\n")
390 if 'PositionAccuracy' in params:
391 out.write(" <td>"+str(params['PositionAccuracy'])+"</td>\n")
392 if str(params['PositionAccuracy']) in PositionAccuracyDecodeLut:
393 out.write("<td>"+PositionAccuracyDecodeLut[str(params['PositionAccuracy'])]+"</td>")
394 else:
395 out.write("<td><i>Missing LUT entry</i></td>")
396 out.write("</tr>\n")
397 out.write("\n")
398 out.write("<tr>\n")
399 out.write("<td>Position_longitude</td>\n")
400 out.write("<td>decimal</td>\n")
401 if 'Position_longitude' in params:
402 out.write(" <td>"+str(params['Position_longitude'])+"</td>\n")
403 out.write(" <td>"+str(params['Position_longitude'])+"</td>\n")
404 out.write("<td>degrees</td>\n")
405 out.write("</tr>\n")
406 out.write("\n")
407 out.write("<tr>\n")
408 out.write("<td>Position_latitude</td>\n")
409 out.write("<td>decimal</td>\n")
410 if 'Position_latitude' in params:
411 out.write(" <td>"+str(params['Position_latitude'])+"</td>\n")
412 out.write(" <td>"+str(params['Position_latitude'])+"</td>\n")
413 out.write("<td>degrees</td>\n")
414 out.write("</tr>\n")
415 out.write("\n")
416 out.write("<tr>\n")
417 out.write("<td>fixtype</td>\n")
418 out.write("<td>uint</td>\n")
419 if 'fixtype' in params:
420 out.write(" <td>"+str(params['fixtype'])+"</td>\n")
421 if str(params['fixtype']) in fixtypeDecodeLut:
422 out.write("<td>"+fixtypeDecodeLut[str(params['fixtype'])]+"</td>")
423 else:
424 out.write("<td><i>Missing LUT entry</i></td>")
425 out.write("</tr>\n")
426 out.write("\n")
427 out.write("<tr>\n")
428 out.write("<td>Spare</td>\n")
429 out.write("<td>uint</td>\n")
430 if 'Spare' in params:
431 out.write(" <td>"+str(params['Spare'])+"</td>\n")
432 out.write(" <td>"+str(params['Spare'])+"</td>\n")
433 out.write("</tr>\n")
434 out.write("\n")
435 out.write("<tr>\n")
436 out.write("<td>RAIM</td>\n")
437 out.write("<td>bool</td>\n")
438 if 'RAIM' in params:
439 out.write(" <td>"+str(params['RAIM'])+"</td>\n")
440 if str(params['RAIM']) in RAIMDecodeLut:
441 out.write("<td>"+RAIMDecodeLut[str(params['RAIM'])]+"</td>")
442 else:
443 out.write("<td><i>Missing LUT entry</i></td>")
444 out.write("</tr>\n")
445 out.write("\n")
446 out.write("<tr>\n")
447 out.write("<td>state_syncstate</td>\n")
448 out.write("<td>uint</td>\n")
449 if 'state_syncstate' in params:
450 out.write(" <td>"+str(params['state_syncstate'])+"</td>\n")
451 if str(params['state_syncstate']) in state_syncstateDecodeLut:
452 out.write("<td>"+state_syncstateDecodeLut[str(params['state_syncstate'])]+"</td>")
453 else:
454 out.write("<td><i>Missing LUT entry</i></td>")
455 out.write("</tr>\n")
456 out.write("\n")
457 out.write("<tr>\n")
458 out.write("<td>state_slottimeout</td>\n")
459 out.write("<td>uint</td>\n")
460 if 'state_slottimeout' in params:
461 out.write(" <td>"+str(params['state_slottimeout'])+"</td>\n")
462 if str(params['state_slottimeout']) in state_slottimeoutDecodeLut:
463 out.write("<td>"+state_slottimeoutDecodeLut[str(params['state_slottimeout'])]+"</td>")
464 else:
465 out.write("<td><i>Missing LUT entry</i></td>")
466 out.write("<td>frames</td>\n")
467 out.write("</tr>\n")
468 out.write("\n")
469 out.write("<tr>\n")
470 out.write("<td>state_slotoffset</td>\n")
471 out.write("<td>uint</td>\n")
472 if 'state_slotoffset' in params:
473 out.write(" <td>"+str(params['state_slotoffset'])+"</td>\n")
474 out.write(" <td>"+str(params['state_slotoffset'])+"</td>\n")
475 out.write("</tr>\n")
476 out.write("</table>\n")
477
478
480 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
481 out.write("\ <Placemark>\n")
482 out.write("\t <name>"+str(params['UserID'])+"</name>\n")
483 out.write("\t\t<description>\n")
484 import StringIO
485 buf = StringIO.StringIO()
486 printHtml(params,buf)
487 import cgi
488 out.write(cgi.escape(buf.getvalue()))
489 out.write("\t\t</description>\n")
490 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
491 out.write("\t\t<Point>\n")
492 out.write("\t\t\t<coordinates>")
493 out.write(str(params['Position_longitude']))
494 out.write(',')
495 out.write(str(params['Position_latitude']))
496 out.write(",0</coordinates>\n")
497 out.write("\t\t</Point>\n")
498 out.write("\t</Placemark>\n")
499
500 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
501 '''Print a bsreport message to stdout.
502
503 Fields in params:
504 - MessageID(uint): AIS message number. Must be 4 (field automatically set to "4")
505 - RepeatIndicator(uint): Indicated how many times a message has been repeated
506 - UserID(uint): Unique ship identification number (MMSI)
507 - Time_year(uint): Current time stamp year 1-9999
508 - Time_month(uint): Current time stamp month 1..12
509 - Time_day(uint): Current time stamp day of the month 1..31
510 - Time_hour(uint): Current time stamp UTC hours 0..23
511 - Time_min(uint): Current time stamp minutes
512 - Time_sec(uint): Current time stamp seconds
513 - PositionAccuracy(uint): Accuracy of positioning fixes
514 - Position_longitude(decimal): Location of base station East West location
515 - Position_latitude(decimal): Location of base station North South location
516 - fixtype(uint): Method used for positioning
517 - Spare(uint): Not used. Should be set to zero. (field automatically set to "0")
518 - RAIM(bool): Receiver autonomous integrity monitoring flag
519 - state_syncstate(uint): Communications State - SOTDMA Sycronization state
520 - state_slottimeout(uint): Communications State - SOTDMA Frames remaining until a new slot is selected
521 - state_slotoffset(uint): Communications State - SOTDMA In what slot will the next transmission occur. BROKEN
522 @param params: Dictionary of field names/values.
523 @param out: File like object to write to
524 @rtype: stdout
525 @return: text to out
526 '''
527
528 if 'std'==format:
529 out.write("bsreport:\n")
530 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n")
531 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n")
532 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n")
533 if 'Time_year' in params: out.write(" Time_year: "+str(params['Time_year'])+"\n")
534 if 'Time_month' in params: out.write(" Time_month: "+str(params['Time_month'])+"\n")
535 if 'Time_day' in params: out.write(" Time_day: "+str(params['Time_day'])+"\n")
536 if 'Time_hour' in params: out.write(" Time_hour: "+str(params['Time_hour'])+"\n")
537 if 'Time_min' in params: out.write(" Time_min: "+str(params['Time_min'])+"\n")
538 if 'Time_sec' in params: out.write(" Time_sec: "+str(params['Time_sec'])+"\n")
539 if 'PositionAccuracy' in params: out.write(" PositionAccuracy: "+str(params['PositionAccuracy'])+"\n")
540 if 'Position_longitude' in params: out.write(" Position_longitude: "+str(params['Position_longitude'])+"\n")
541 if 'Position_latitude' in params: out.write(" Position_latitude: "+str(params['Position_latitude'])+"\n")
542 if 'fixtype' in params: out.write(" fixtype: "+str(params['fixtype'])+"\n")
543 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
544 if 'RAIM' in params: out.write(" RAIM: "+str(params['RAIM'])+"\n")
545 if 'state_syncstate' in params: out.write(" state_syncstate: "+str(params['state_syncstate'])+"\n")
546 if 'state_slottimeout' in params: out.write(" state_slottimeout: "+str(params['state_slottimeout'])+"\n")
547 if 'state_slotoffset' in params: out.write(" state_slotoffset: "+str(params['state_slotoffset'])+"\n")
548 elif 'csv'==format:
549 if None == options.fieldList:
550 options.fieldList = fieldList
551 needComma = False;
552 for field in fieldList:
553 if needComma: out.write(',')
554 needComma = True
555 if field in params:
556 out.write(str(params[field]))
557
558 out.write("\n")
559 elif 'html'==format:
560 printHtml(params,out)
561 elif 'sql'==format:
562 sqlInsertStr(params,out,dbType=dbType)
563 elif 'kml'==format:
564 printKml(params,out)
565 elif 'kml-full'==format:
566 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
567 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
568 out.write("<Document>\n")
569 out.write(" <name>bsreport</name>\n")
570 printKml(params,out)
571 out.write("</Document>\n")
572 out.write("</kml>\n")
573 else:
574 print "ERROR: unknown format:",format
575 assert False
576
577 return
578
579 RepeatIndicatorEncodeLut = {
580 'default':'0',
581 'do not repeat any more':'3',
582 }
583
584 RepeatIndicatorDecodeLut = {
585 '0':'default',
586 '3':'do not repeat any more',
587 }
588
589 PositionAccuracyEncodeLut = {
590 'low (greater than 10 m)':'0',
591 'high (less than 10 m)':'1',
592 }
593
594 PositionAccuracyDecodeLut = {
595 '0':'low (greater than 10 m)',
596 '1':'high (less than 10 m)',
597 }
598
599 fixtypeEncodeLut = {
600 'undefined':'0',
601 'GPS':'1',
602 'GLONASS':'2',
603 'combined GPS/GLONASS':'3',
604 'Loran-C':'4',
605 'Chayka':'5',
606 'integrated navigation system':'6',
607 'surveyed':'7',
608 }
609
610 fixtypeDecodeLut = {
611 '0':'undefined',
612 '1':'GPS',
613 '2':'GLONASS',
614 '3':'combined GPS/GLONASS',
615 '4':'Loran-C',
616 '5':'Chayka',
617 '6':'integrated navigation system',
618 '7':'surveyed',
619 }
620
621 RAIMEncodeLut = {
622 'not in use':'False',
623 'in use':'True',
624 }
625
626 RAIMDecodeLut = {
627 'False':'not in use',
628 'True':'in use',
629 }
630
631 state_syncstateEncodeLut = {
632 'UTC direct':'0',
633 'UTC indirect':'1',
634 'synchronized to a base station':'2',
635 'synchronized to another station':'3',
636 }
637
638 state_syncstateDecodeLut = {
639 '0':'UTC direct',
640 '1':'UTC indirect',
641 '2':'synchronized to a base station',
642 '3':'synchronized to another station',
643 }
644
645 state_slottimeoutEncodeLut = {
646 'Last frame in this slot':'0',
647 '1 frames left':'1',
648 '2 frames left':'2',
649 '3 frames left':'3',
650 '4 frames left':'4',
651 '5 frames left':'5',
652 '6 frames left':'6',
653 '7 frames left':'7',
654 }
655
656 state_slottimeoutDecodeLut = {
657 '0':'Last frame in this slot',
658 '1':'1 frames left',
659 '2':'2 frames left',
660 '3':'3 frames left',
661 '4':'4 frames left',
662 '5':'5 frames left',
663 '6':'6 frames left',
664 '7':'7 frames left',
665 }
666
667
668
669
670
671 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
672 ,addCoastGuardFields=True
673 ,dbType='postgres'
674 ):
675 '''
676 Return the SQL CREATE command for this message type
677 @param outfile: file like object to print to.
678 @param fields: which fields to put in the create. Defaults to all.
679 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
680 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
681 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
682 @type addCoastGuardFields: bool
683 @return: sql create string
684 @rtype: str
685
686 @see: sqlCreate
687 '''
688
689 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
690
691 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
692 '''
693 Return the sqlhelp object to create the table.
694
695 @param fields: which fields to put in the create. Defaults to all.
696 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
697 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
698 @type addCoastGuardFields: bool
699 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
700 @return: An object that can be used to generate a return
701 @rtype: sqlhelp.create
702 '''
703 if None == fields: fields = fieldList
704 import sqlhelp
705 c = sqlhelp.create('bsreport',dbType=dbType)
706 c.addPrimaryKey()
707 if 'MessageID' in fields: c.addInt ('MessageID')
708 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator')
709 if 'UserID' in fields: c.addInt ('UserID')
710 if 'Time_year' in fields: c.addInt ('Time_year')
711 if 'Time_month' in fields: c.addInt ('Time_month')
712 if 'Time_day' in fields: c.addInt ('Time_day')
713 if 'Time_hour' in fields: c.addInt ('Time_hour')
714 if 'Time_min' in fields: c.addInt ('Time_min')
715 if 'Time_sec' in fields: c.addInt ('Time_sec')
716 if 'PositionAccuracy' in fields: c.addInt ('PositionAccuracy')
717 if dbType != 'postgres':
718 if 'Position_longitude' in fields: c.addDecimal('Position_longitude',8,5)
719 if dbType != 'postgres':
720 if 'Position_latitude' in fields: c.addDecimal('Position_latitude',8,5)
721 if 'fixtype' in fields: c.addInt ('fixtype')
722 if 'Spare' in fields: c.addInt ('Spare')
723 if 'RAIM' in fields: c.addBool('RAIM')
724 if 'state_syncstate' in fields: c.addInt ('state_syncstate')
725 if 'state_slottimeout' in fields: c.addInt ('state_slottimeout')
726 if 'state_slotoffset' in fields: c.addInt ('state_slotoffset')
727
728 if addCoastGuardFields:
729
730
731
732
733
734 c.addVarChar('cg_r',15)
735 c.addInt('cg_sec')
736
737 c.addTimestamp('cg_timestamp')
738
739 if dbType == 'postgres':
740 c.addPostGIS('Position','POINT',2);
741
742 return c
743
744 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
745 '''
746 Return the SQL INSERT command for this message type
747 @param params: dictionary of values keyed by field name
748 @param outfile: file like object to print to.
749 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
750 @return: sql create string
751 @rtype: str
752
753 @see: sqlCreate
754 '''
755 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
756
757
758 -def sqlInsert(params,extraParams=None,dbType='postgres'):
759 '''
760 Give the SQL INSERT statement
761 @param params: dict keyed by field name of values
762 @param extraParams: any extra fields that you have created beyond the normal ais message fields
763 @rtype: sqlhelp.insert
764 @return: insert class instance
765 @todo: allow optional type checking of params?
766 @warning: this will take invalid keys happily and do what???
767 '''
768 import sqlhelp
769 i = sqlhelp.insert('bsreport',dbType=dbType)
770
771 if dbType=='postgres':
772 finished = []
773 for key in params:
774 if key in finished:
775 continue
776
777 if key not in toPgFields and key not in fromPgFields:
778 if type(params[key])==Decimal: i.add(key,float(params[key]))
779 else: i.add(key,params[key])
780 else:
781 if key in fromPgFields:
782 val = params[key]
783
784 i.addPostGIS(key,val)
785 finished.append(key)
786 else:
787
788 pgName = toPgFields[key]
789
790 valStr=pgTypes[pgName]+'('
791 vals = []
792 for nonPgKey in fromPgFields[pgName]:
793 vals.append(str(params[nonPgKey]))
794 finished.append(nonPgKey)
795 valStr+=' '.join(vals)+')'
796 i.addPostGIS(pgName,valStr)
797 else:
798 for key in params:
799 if type(params[key])==Decimal: i.add(key,float(params[key]))
800 else: i.add(key,params[key])
801
802 if None != extraParams:
803 for key in extraParams:
804 i.add(key,extraParams[key])
805
806 return i
807
808
809
810
811
814 '''
815 Return the LaTeX definition table for this message type
816 @param outfile: file like object to print to.
817 @type outfile: file obj
818 @return: LaTeX table string via the outfile
819 @rtype: str
820
821 '''
822 o = outfile
823
824 o.write('''
825 \\begin{table}%[htb]
826 \\centering
827 \\begin{tabular}{|l|c|l|}
828 \\hline
829 Parameter & Number of bits & Description
830 \\\\ \\hline\\hline
831 MessageID & 6 & AIS message number. Must be 4 \\\\ \hline
832 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline
833 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline
834 Time\_year & 14 & Current time stamp year 1-9999 \\\\ \hline
835 Time\_month & 4 & Current time stamp month 1..12 \\\\ \hline
836 Time\_day & 5 & Current time stamp day of the month 1..31 \\\\ \hline
837 Time\_hour & 5 & Current time stamp UTC hours 0..23 \\\\ \hline
838 Time\_min & 6 & Current time stamp minutes \\\\ \hline
839 Time\_sec & 6 & Current time stamp seconds \\\\ \hline
840 PositionAccuracy & 1 & Accuracy of positioning fixes \\\\ \hline
841 Position\_longitude & 28 & Location of base station East West location \\\\ \hline
842 Position\_latitude & 27 & Location of base station North South location \\\\ \hline
843 fixtype & 4 & Method used for positioning \\\\ \hline
844 Spare & 10 & Not used. Should be set to zero. \\\\ \hline
845 RAIM & 1 & Receiver autonomous integrity monitoring flag \\\\ \hline
846 state\_syncstate & 2 & Communications State - SOTDMA Sycronization state \\\\ \hline
847 state\_slottimeout & 3 & Communications State - SOTDMA Frames remaining until a new slot is selected \\\\ \hline
848 state\_slotoffset & 14 & Communications State - SOTDMA In what slot will the next transmission occur. BROKEN\\\\ \\hline \\hline
849 Total bits & 168 & Appears to take 1 slot \\\\ \\hline
850 \\end{tabular}
851 \\caption{AIS message number 4: Base station report}
852 \\label{tab:bsreport}
853 \\end{table}
854 ''')
855
856
857
858
859
860 -def textDefinitionTable(outfile=sys.stdout
861 ,delim='\t'
862 ):
863 '''
864 Return the text definition table for this message type
865 @param outfile: file like object to print to.
866 @type outfile: file obj
867 @return: text table string via the outfile
868 @rtype: str
869
870 '''
871 o = outfile
872 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description
873 MessageID'''+delim+'''6'''+delim+'''AIS message number. Must be 4
874 RepeatIndicator'''+delim+'''2'''+delim+'''Indicated how many times a message has been repeated
875 UserID'''+delim+'''30'''+delim+'''Unique ship identification number (MMSI)
876 Time_year'''+delim+'''14'''+delim+'''Current time stamp year 1-9999
877 Time_month'''+delim+'''4'''+delim+'''Current time stamp month 1..12
878 Time_day'''+delim+'''5'''+delim+'''Current time stamp day of the month 1..31
879 Time_hour'''+delim+'''5'''+delim+'''Current time stamp UTC hours 0..23
880 Time_min'''+delim+'''6'''+delim+'''Current time stamp minutes
881 Time_sec'''+delim+'''6'''+delim+'''Current time stamp seconds
882 PositionAccuracy'''+delim+'''1'''+delim+'''Accuracy of positioning fixes
883 Position_longitude'''+delim+'''28'''+delim+'''Location of base station East West location
884 Position_latitude'''+delim+'''27'''+delim+'''Location of base station North South location
885 fixtype'''+delim+'''4'''+delim+'''Method used for positioning
886 Spare'''+delim+'''10'''+delim+'''Not used. Should be set to zero.
887 RAIM'''+delim+'''1'''+delim+'''Receiver autonomous integrity monitoring flag
888 state_syncstate'''+delim+'''2'''+delim+'''Communications State - SOTDMA Sycronization state
889 state_slottimeout'''+delim+'''3'''+delim+'''Communications State - SOTDMA Frames remaining until a new slot is selected
890 state_slotoffset'''+delim+'''14'''+delim+'''Communications State - SOTDMA In what slot will the next transmission occur. BROKEN
891 Total bits'''+delim+'''168'''+delim+'''Appears to take 1 slot''')
892
893
894
895
896
897 import unittest
899 '''Return a params file base on the testvalue tags.
900 @rtype: dict
901 @return: params based on testvalue tags
902 '''
903 params = {}
904 params['MessageID'] = 4
905 params['RepeatIndicator'] = 1
906 params['UserID'] = 1193046
907 params['Time_year'] = 2
908 params['Time_month'] = 2
909 params['Time_day'] = 28
910 params['Time_hour'] = 23
911 params['Time_min'] = 45
912 params['Time_sec'] = 54
913 params['PositionAccuracy'] = 1
914 params['Position_longitude'] = Decimal('-122.16328055555556')
915 params['Position_latitude'] = Decimal('37.424458333333334')
916 params['fixtype'] = 1
917 params['Spare'] = 0
918 params['RAIM'] = False
919 params['state_syncstate'] = 2
920 params['state_slottimeout'] = 0
921 params['state_slotoffset'] = 1221
922
923 return params
924
926 '''Use testvalue tag text from each type to build test case the bsreport message'''
928
929 params = testParams()
930 bits = encode(params)
931 r = decode(bits)
932
933
934 self.failUnlessEqual(r['MessageID'],params['MessageID'])
935 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
936 self.failUnlessEqual(r['UserID'],params['UserID'])
937 self.failUnlessEqual(r['Time_year'],params['Time_year'])
938 self.failUnlessEqual(r['Time_month'],params['Time_month'])
939 self.failUnlessEqual(r['Time_day'],params['Time_day'])
940 self.failUnlessEqual(r['Time_hour'],params['Time_hour'])
941 self.failUnlessEqual(r['Time_min'],params['Time_min'])
942 self.failUnlessEqual(r['Time_sec'],params['Time_sec'])
943 self.failUnlessEqual(r['PositionAccuracy'],params['PositionAccuracy'])
944 self.failUnlessAlmostEqual(r['Position_longitude'],params['Position_longitude'],5)
945 self.failUnlessAlmostEqual(r['Position_latitude'],params['Position_latitude'],5)
946 self.failUnlessEqual(r['fixtype'],params['fixtype'])
947 self.failUnlessEqual(r['Spare'],params['Spare'])
948 self.failUnlessEqual(r['RAIM'],params['RAIM'])
949 self.failUnlessEqual(r['state_syncstate'],params['state_syncstate'])
950 self.failUnlessEqual(r['state_slottimeout'],params['state_slottimeout'])
951 self.failUnlessEqual(r['state_slotoffset'],params['state_slotoffset'])
952
954 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
955 help='decode a "bsreport" AIS message')
956 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
957 help='encode a "bsreport" AIS message')
958 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
959 ,help='Field parameter value [default: %default]')
960 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
961 ,help='Field parameter value [default: %default]')
962 parser.add_option('--Time_year-field', dest='Time_yearField',default=0,metavar='uint',type='int'
963 ,help='Field parameter value [default: %default]')
964 parser.add_option('--Time_month-field', dest='Time_monthField',default=0,metavar='uint',type='int'
965 ,help='Field parameter value [default: %default]')
966 parser.add_option('--Time_day-field', dest='Time_dayField',default=0,metavar='uint',type='int'
967 ,help='Field parameter value [default: %default]')
968 parser.add_option('--Time_hour-field', dest='Time_hourField',default=24,metavar='uint',type='int'
969 ,help='Field parameter value [default: %default]')
970 parser.add_option('--Time_min-field', dest='Time_minField',default=60,metavar='uint',type='int'
971 ,help='Field parameter value [default: %default]')
972 parser.add_option('--Time_sec-field', dest='Time_secField',default=60,metavar='uint',type='int'
973 ,help='Field parameter value [default: %default]')
974 parser.add_option('--PositionAccuracy-field', dest='PositionAccuracyField',metavar='uint',type='int'
975 ,help='Field parameter value [default: %default]')
976 parser.add_option('--Position_longitude-field', dest='Position_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
977 ,help='Field parameter value [default: %default]')
978 parser.add_option('--Position_latitude-field', dest='Position_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
979 ,help='Field parameter value [default: %default]')
980 parser.add_option('--fixtype-field', dest='fixtypeField',default=0,metavar='uint',type='int'
981 ,help='Field parameter value [default: %default]')
982 parser.add_option('--RAIM-field', dest='RAIMField',metavar='bool',type='int'
983 ,help='Field parameter value [default: %default]')
984 parser.add_option('--state_syncstate-field', dest='state_syncstateField',metavar='uint',type='int'
985 ,help='Field parameter value [default: %default]')
986 parser.add_option('--state_slottimeout-field', dest='state_slottimeoutField',metavar='uint',type='int'
987 ,help='Field parameter value [default: %default]')
988 parser.add_option('--state_slotoffset-field', dest='state_slotoffsetField',metavar='uint',type='int'
989 ,help='Field parameter value [default: %default]')
990
991
992 if __name__=='__main__':
993
994 from optparse import OptionParser
995 parser = OptionParser(usage="%prog [options]",
996 version="%prog "+__version__)
997
998 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
999 help='run the documentation tests')
1000 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
1001 help='run the unit tests')
1002 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
1003 help='Make the test output verbose')
1004
1005
1006
1007 typeChoices = ('binary','nmeapayload','nmea')
1008 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
1009 ,default='nmeapayload'
1010 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
1011
1012
1013 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
1014 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
1015 ,default='std'
1016 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
1017
1018 parser.add_option('-o','--output',dest='outputFileName',default=None,
1019 help='Name of the python file to write [default: stdout]')
1020
1021 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
1022 choices=fieldList,
1023 help='Which fields to include in the output. Currently only for csv output [default: all]')
1024
1025 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
1026 help='Print the field name for csv')
1027
1028 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
1029 help='Print out an sql create command for the table.')
1030
1031 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
1032 help='Print a LaTeX table of the type')
1033
1034 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true',
1035 help='Print delimited table of the type (for Word table importing)')
1036 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t'
1037 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)')
1038
1039
1040 dbChoices = ('sqlite','postgres')
1041 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
1042 ,choices=dbChoices,type='choice'
1043 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
1044
1045 addMsgOptions(parser)
1046
1047 (options,args) = parser.parse_args()
1048 success=True
1049
1050 if options.doctest:
1051 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
1052 sys.argv= [sys.argv[0]]
1053 if options.verbose: sys.argv.append('-v')
1054 import doctest
1055 numfail,numtests=doctest.testmod()
1056 if numfail==0: print 'ok'
1057 else:
1058 print 'FAILED'
1059 success=False
1060
1061 if not success: sys.exit('Something Failed')
1062 del success
1063
1064 if options.unittest:
1065 sys.argv = [sys.argv[0]]
1066 if options.verbose: sys.argv.append('-v')
1067 unittest.main()
1068
1069 outfile = sys.stdout
1070 if None!=options.outputFileName:
1071 outfile = file(options.outputFileName,'w')
1072
1073
1074 if options.doEncode:
1075
1076 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
1077 if None==options.UserIDField: parser.error("missing value for UserIDField")
1078 if None==options.Time_yearField: parser.error("missing value for Time_yearField")
1079 if None==options.Time_monthField: parser.error("missing value for Time_monthField")
1080 if None==options.Time_dayField: parser.error("missing value for Time_dayField")
1081 if None==options.Time_hourField: parser.error("missing value for Time_hourField")
1082 if None==options.Time_minField: parser.error("missing value for Time_minField")
1083 if None==options.Time_secField: parser.error("missing value for Time_secField")
1084 if None==options.PositionAccuracyField: parser.error("missing value for PositionAccuracyField")
1085 if None==options.Position_longitudeField: parser.error("missing value for Position_longitudeField")
1086 if None==options.Position_latitudeField: parser.error("missing value for Position_latitudeField")
1087 if None==options.fixtypeField: parser.error("missing value for fixtypeField")
1088 if None==options.RAIMField: parser.error("missing value for RAIMField")
1089 if None==options.state_syncstateField: parser.error("missing value for state_syncstateField")
1090 if None==options.state_slottimeoutField: parser.error("missing value for state_slottimeoutField")
1091 if None==options.state_slotoffsetField: parser.error("missing value for state_slotoffsetField")
1092 msgDict={
1093 'MessageID': '4',
1094 'RepeatIndicator': options.RepeatIndicatorField,
1095 'UserID': options.UserIDField,
1096 'Time_year': options.Time_yearField,
1097 'Time_month': options.Time_monthField,
1098 'Time_day': options.Time_dayField,
1099 'Time_hour': options.Time_hourField,
1100 'Time_min': options.Time_minField,
1101 'Time_sec': options.Time_secField,
1102 'PositionAccuracy': options.PositionAccuracyField,
1103 'Position_longitude': options.Position_longitudeField,
1104 'Position_latitude': options.Position_latitudeField,
1105 'fixtype': options.fixtypeField,
1106 'Spare': '0',
1107 'RAIM': options.RAIMField,
1108 'state_syncstate': options.state_syncstateField,
1109 'state_slottimeout': options.state_slottimeoutField,
1110 'state_slotoffset': options.state_slotoffsetField,
1111 }
1112
1113 bits = encode(msgDict)
1114 if 'binary'==options.ioType: print str(bits)
1115 elif 'nmeapayload'==options.ioType:
1116
1117 print "bitLen",len(bits)
1118 bitLen=len(bits)
1119 if bitLen%6!=0:
1120 bits = bits + BitVector(size=(6 - (bitLen%6)))
1121 print "result:",binary.bitvectoais6(bits)[0]
1122
1123
1124
1125 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
1126 else: sys.exit('ERROR: unknown ioType. Help!')
1127
1128
1129 if options.sqlCreate:
1130 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
1131
1132 if options.latexDefinitionTable:
1133 latexDefinitionTable(outfile)
1134
1135
1136 if options.textDefinitionTable:
1137 textDefinitionTable(outfile,options.delimTextDefinitionTable)
1138
1139 if options.printCsvfieldList:
1140
1141 if None == options.fieldList: options.fieldList = fieldList
1142 import StringIO
1143 buf = StringIO.StringIO()
1144 for field in options.fieldList:
1145 buf.write(field+',')
1146 result = buf.getvalue()
1147 if result[-1] == ',': print result[:-1]
1148 else: print result
1149
1150 if options.doDecode:
1151 for msg in args:
1152 bv = None
1153
1154 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
1155
1156
1157 bv = binary.ais6tobitvec(msg.split(',')[5])
1158 else:
1159
1160 binaryMsg=True
1161 for c in msg:
1162 if c not in ('0','1'):
1163 binaryMsg=False
1164 break
1165 if binaryMsg:
1166 bv = BitVector(bitstring=msg)
1167 else:
1168 bv = binary.ais6tobitvec(msg)
1169
1170 printFields(decode(bv)
1171 ,out=outfile
1172 ,format=options.outputType
1173 ,fieldList=options.fieldList
1174 ,dbType=options.dbType
1175 )
1176