1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2008-01-09 $'.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 dbTableName='bsreport'
672 'Database table name'
673
674 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
675 ,addCoastGuardFields=True
676 ,dbType='postgres'
677 ):
678 '''
679 Return the SQL CREATE command for this message type
680 @param outfile: file like object to print to.
681 @param fields: which fields to put in the create. Defaults to all.
682 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
683 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
684 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
685 @type addCoastGuardFields: bool
686 @return: sql create string
687 @rtype: str
688
689 @see: sqlCreate
690 '''
691
692 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
693
694 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
695 '''
696 Return the sqlhelp object to create the table.
697
698 @param fields: which fields to put in the create. Defaults to all.
699 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
700 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
701 @type addCoastGuardFields: bool
702 @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
703 @return: An object that can be used to generate a return
704 @rtype: sqlhelp.create
705 '''
706 if None == fields: fields = fieldList
707 import sqlhelp
708 c = sqlhelp.create('bsreport',dbType=dbType)
709 c.addPrimaryKey()
710 if 'MessageID' in fields: c.addInt ('MessageID')
711 if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator')
712 if 'UserID' in fields: c.addInt ('UserID')
713 if 'Time_year' in fields: c.addInt ('Time_year')
714 if 'Time_month' in fields: c.addInt ('Time_month')
715 if 'Time_day' in fields: c.addInt ('Time_day')
716 if 'Time_hour' in fields: c.addInt ('Time_hour')
717 if 'Time_min' in fields: c.addInt ('Time_min')
718 if 'Time_sec' in fields: c.addInt ('Time_sec')
719 if 'PositionAccuracy' in fields: c.addInt ('PositionAccuracy')
720 if dbType != 'postgres':
721 if 'Position_longitude' in fields: c.addDecimal('Position_longitude',8,5)
722 if dbType != 'postgres':
723 if 'Position_latitude' in fields: c.addDecimal('Position_latitude',8,5)
724 if 'fixtype' in fields: c.addInt ('fixtype')
725 if 'Spare' in fields: c.addInt ('Spare')
726 if 'RAIM' in fields: c.addBool('RAIM')
727 if 'state_syncstate' in fields: c.addInt ('state_syncstate')
728 if 'state_slottimeout' in fields: c.addInt ('state_slottimeout')
729 if 'state_slotoffset' in fields: c.addInt ('state_slotoffset')
730
731 if addCoastGuardFields:
732
733
734
735
736
737 c.addVarChar('cg_r',15)
738 c.addInt('cg_sec')
739
740 c.addTimestamp('cg_timestamp')
741
742 if dbType == 'postgres':
743
744
745 c.addPostGIS('Position','POINT',2,SRID=4326);
746
747 return c
748
749 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
750 '''
751 Return the SQL INSERT command for this message type
752 @param params: dictionary of values keyed by field name
753 @param outfile: file like object to print to.
754 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
755 @return: sql create string
756 @rtype: str
757
758 @see: sqlCreate
759 '''
760 outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
761
762
763 -def sqlInsert(params,extraParams=None,dbType='postgres'):
764 '''
765 Give the SQL INSERT statement
766 @param params: dict keyed by field name of values
767 @param extraParams: any extra fields that you have created beyond the normal ais message fields
768 @rtype: sqlhelp.insert
769 @return: insert class instance
770 @todo: allow optional type checking of params?
771 @warning: this will take invalid keys happily and do what???
772 '''
773 import sqlhelp
774 i = sqlhelp.insert('bsreport',dbType=dbType)
775
776 if dbType=='postgres':
777 finished = []
778 for key in params:
779 if key in finished:
780 continue
781
782 if key not in toPgFields and key not in fromPgFields:
783 if type(params[key])==Decimal: i.add(key,float(params[key]))
784 else: i.add(key,params[key])
785 else:
786 if key in fromPgFields:
787 val = params[key]
788
789 i.addPostGIS(key,val)
790 finished.append(key)
791 else:
792
793 pgName = toPgFields[key]
794
795 valStr=pgTypes[pgName]+'('
796 vals = []
797 for nonPgKey in fromPgFields[pgName]:
798 vals.append(str(params[nonPgKey]))
799 finished.append(nonPgKey)
800 valStr+=' '.join(vals)+')'
801 i.addPostGIS(pgName,valStr)
802 else:
803 for key in params:
804 if type(params[key])==Decimal: i.add(key,float(params[key]))
805 else: i.add(key,params[key])
806
807 if None != extraParams:
808 for key in extraParams:
809 i.add(key,extraParams[key])
810
811 return i
812
813
814
815
816
819 '''
820 Return the LaTeX definition table for this message type
821 @param outfile: file like object to print to.
822 @type outfile: file obj
823 @return: LaTeX table string via the outfile
824 @rtype: str
825
826 '''
827 o = outfile
828
829 o.write('''
830 \\begin{table}%[htb]
831 \\centering
832 \\begin{tabular}{|l|c|l|}
833 \\hline
834 Parameter & Number of bits & Description
835 \\\\ \\hline\\hline
836 MessageID & 6 & AIS message number. Must be 4 \\\\ \hline
837 RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline
838 UserID & 30 & Unique ship identification number (MMSI) \\\\ \hline
839 Time\_year & 14 & Current time stamp year 1-9999 \\\\ \hline
840 Time\_month & 4 & Current time stamp month 1..12 \\\\ \hline
841 Time\_day & 5 & Current time stamp day of the month 1..31 \\\\ \hline
842 Time\_hour & 5 & Current time stamp UTC hours 0..23 \\\\ \hline
843 Time\_min & 6 & Current time stamp minutes \\\\ \hline
844 Time\_sec & 6 & Current time stamp seconds \\\\ \hline
845 PositionAccuracy & 1 & Accuracy of positioning fixes \\\\ \hline
846 Position\_longitude & 28 & Location of base station East West location \\\\ \hline
847 Position\_latitude & 27 & Location of base station North South location \\\\ \hline
848 fixtype & 4 & Method used for positioning \\\\ \hline
849 Spare & 10 & Not used. Should be set to zero. \\\\ \hline
850 RAIM & 1 & Receiver autonomous integrity monitoring flag \\\\ \hline
851 state\_syncstate & 2 & Communications State - SOTDMA Sycronization state \\\\ \hline
852 state\_slottimeout & 3 & Communications State - SOTDMA Frames remaining until a new slot is selected \\\\ \hline
853 state\_slotoffset & 14 & Communications State - SOTDMA In what slot will the next transmission occur. BROKEN\\\\ \\hline \\hline
854 Total bits & 168 & Appears to take 1 slot \\\\ \\hline
855 \\end{tabular}
856 \\caption{AIS message number 4: Base station report}
857 \\label{tab:bsreport}
858 \\end{table}
859 ''')
860
861
862
863
864
865 -def textDefinitionTable(outfile=sys.stdout
866 ,delim='\t'
867 ):
868 '''
869 Return the text definition table for this message type
870 @param outfile: file like object to print to.
871 @type outfile: file obj
872 @return: text table string via the outfile
873 @rtype: str
874
875 '''
876 o = outfile
877 o.write('''Parameter'''+delim+'Number of bits'''+delim+'''Description
878 MessageID'''+delim+'''6'''+delim+'''AIS message number. Must be 4
879 RepeatIndicator'''+delim+'''2'''+delim+'''Indicated how many times a message has been repeated
880 UserID'''+delim+'''30'''+delim+'''Unique ship identification number (MMSI)
881 Time_year'''+delim+'''14'''+delim+'''Current time stamp year 1-9999
882 Time_month'''+delim+'''4'''+delim+'''Current time stamp month 1..12
883 Time_day'''+delim+'''5'''+delim+'''Current time stamp day of the month 1..31
884 Time_hour'''+delim+'''5'''+delim+'''Current time stamp UTC hours 0..23
885 Time_min'''+delim+'''6'''+delim+'''Current time stamp minutes
886 Time_sec'''+delim+'''6'''+delim+'''Current time stamp seconds
887 PositionAccuracy'''+delim+'''1'''+delim+'''Accuracy of positioning fixes
888 Position_longitude'''+delim+'''28'''+delim+'''Location of base station East West location
889 Position_latitude'''+delim+'''27'''+delim+'''Location of base station North South location
890 fixtype'''+delim+'''4'''+delim+'''Method used for positioning
891 Spare'''+delim+'''10'''+delim+'''Not used. Should be set to zero.
892 RAIM'''+delim+'''1'''+delim+'''Receiver autonomous integrity monitoring flag
893 state_syncstate'''+delim+'''2'''+delim+'''Communications State - SOTDMA Sycronization state
894 state_slottimeout'''+delim+'''3'''+delim+'''Communications State - SOTDMA Frames remaining until a new slot is selected
895 state_slotoffset'''+delim+'''14'''+delim+'''Communications State - SOTDMA In what slot will the next transmission occur. BROKEN
896 Total bits'''+delim+'''168'''+delim+'''Appears to take 1 slot''')
897
898
899
900
901
902 import unittest
904 '''Return a params file base on the testvalue tags.
905 @rtype: dict
906 @return: params based on testvalue tags
907 '''
908 params = {}
909 params['MessageID'] = 4
910 params['RepeatIndicator'] = 1
911 params['UserID'] = 1193046
912 params['Time_year'] = 2
913 params['Time_month'] = 2
914 params['Time_day'] = 28
915 params['Time_hour'] = 23
916 params['Time_min'] = 45
917 params['Time_sec'] = 54
918 params['PositionAccuracy'] = 1
919 params['Position_longitude'] = Decimal('-122.16328055555556')
920 params['Position_latitude'] = Decimal('37.424458333333334')
921 params['fixtype'] = 1
922 params['Spare'] = 0
923 params['RAIM'] = False
924 params['state_syncstate'] = 2
925 params['state_slottimeout'] = 0
926 params['state_slotoffset'] = 1221
927
928 return params
929
931 '''Use testvalue tag text from each type to build test case the bsreport message'''
933
934 params = testParams()
935 bits = encode(params)
936 r = decode(bits)
937
938
939 self.failUnlessEqual(r['MessageID'],params['MessageID'])
940 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
941 self.failUnlessEqual(r['UserID'],params['UserID'])
942 self.failUnlessEqual(r['Time_year'],params['Time_year'])
943 self.failUnlessEqual(r['Time_month'],params['Time_month'])
944 self.failUnlessEqual(r['Time_day'],params['Time_day'])
945 self.failUnlessEqual(r['Time_hour'],params['Time_hour'])
946 self.failUnlessEqual(r['Time_min'],params['Time_min'])
947 self.failUnlessEqual(r['Time_sec'],params['Time_sec'])
948 self.failUnlessEqual(r['PositionAccuracy'],params['PositionAccuracy'])
949 self.failUnlessAlmostEqual(r['Position_longitude'],params['Position_longitude'],5)
950 self.failUnlessAlmostEqual(r['Position_latitude'],params['Position_latitude'],5)
951 self.failUnlessEqual(r['fixtype'],params['fixtype'])
952 self.failUnlessEqual(r['Spare'],params['Spare'])
953 self.failUnlessEqual(r['RAIM'],params['RAIM'])
954 self.failUnlessEqual(r['state_syncstate'],params['state_syncstate'])
955 self.failUnlessEqual(r['state_slottimeout'],params['state_slottimeout'])
956 self.failUnlessEqual(r['state_slotoffset'],params['state_slotoffset'])
957
959 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
960 help='decode a "bsreport" AIS message')
961 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
962 help='encode a "bsreport" AIS message')
963 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
964 ,help='Field parameter value [default: %default]')
965 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
966 ,help='Field parameter value [default: %default]')
967 parser.add_option('--Time_year-field', dest='Time_yearField',default=0,metavar='uint',type='int'
968 ,help='Field parameter value [default: %default]')
969 parser.add_option('--Time_month-field', dest='Time_monthField',default=0,metavar='uint',type='int'
970 ,help='Field parameter value [default: %default]')
971 parser.add_option('--Time_day-field', dest='Time_dayField',default=0,metavar='uint',type='int'
972 ,help='Field parameter value [default: %default]')
973 parser.add_option('--Time_hour-field', dest='Time_hourField',default=24,metavar='uint',type='int'
974 ,help='Field parameter value [default: %default]')
975 parser.add_option('--Time_min-field', dest='Time_minField',default=60,metavar='uint',type='int'
976 ,help='Field parameter value [default: %default]')
977 parser.add_option('--Time_sec-field', dest='Time_secField',default=60,metavar='uint',type='int'
978 ,help='Field parameter value [default: %default]')
979 parser.add_option('--PositionAccuracy-field', dest='PositionAccuracyField',metavar='uint',type='int'
980 ,help='Field parameter value [default: %default]')
981 parser.add_option('--Position_longitude-field', dest='Position_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
982 ,help='Field parameter value [default: %default]')
983 parser.add_option('--Position_latitude-field', dest='Position_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
984 ,help='Field parameter value [default: %default]')
985 parser.add_option('--fixtype-field', dest='fixtypeField',default=0,metavar='uint',type='int'
986 ,help='Field parameter value [default: %default]')
987 parser.add_option('--RAIM-field', dest='RAIMField',metavar='bool',type='int'
988 ,help='Field parameter value [default: %default]')
989 parser.add_option('--state_syncstate-field', dest='state_syncstateField',metavar='uint',type='int'
990 ,help='Field parameter value [default: %default]')
991 parser.add_option('--state_slottimeout-field', dest='state_slottimeoutField',metavar='uint',type='int'
992 ,help='Field parameter value [default: %default]')
993 parser.add_option('--state_slotoffset-field', dest='state_slotoffsetField',metavar='uint',type='int'
994 ,help='Field parameter value [default: %default]')
995
996
997 if __name__=='__main__':
998
999 from optparse import OptionParser
1000 parser = OptionParser(usage="%prog [options]",
1001 version="%prog "+__version__)
1002
1003 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
1004 help='run the documentation tests')
1005 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
1006 help='run the unit tests')
1007 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
1008 help='Make the test output verbose')
1009
1010
1011
1012 typeChoices = ('binary','nmeapayload','nmea')
1013 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
1014 ,default='nmeapayload'
1015 ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
1016
1017
1018 outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
1019 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
1020 ,default='std'
1021 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
1022
1023 parser.add_option('-o','--output',dest='outputFileName',default=None,
1024 help='Name of the python file to write [default: stdout]')
1025
1026 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
1027 choices=fieldList,
1028 help='Which fields to include in the output. Currently only for csv output [default: all]')
1029
1030 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
1031 help='Print the field name for csv')
1032
1033 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
1034 help='Print out an sql create command for the table.')
1035
1036 parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true',
1037 help='Print a LaTeX table of the type')
1038
1039 parser.add_option('--text-table',dest='textDefinitionTable',default=False,action='store_true',
1040 help='Print delimited table of the type (for Word table importing)')
1041 parser.add_option('--delimt-text-table',dest='delimTextDefinitionTable',default='\t'
1042 ,help='Delimiter for text table [default: \'%default\'](for Word table importing)')
1043
1044
1045 dbChoices = ('sqlite','postgres')
1046 parser.add_option('-D','--db-type',dest='dbType',default='postgres'
1047 ,choices=dbChoices,type='choice'
1048 ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]')
1049
1050 addMsgOptions(parser)
1051
1052 (options,args) = parser.parse_args()
1053 success=True
1054
1055 if options.doctest:
1056 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
1057 sys.argv= [sys.argv[0]]
1058 if options.verbose: sys.argv.append('-v')
1059 import doctest
1060 numfail,numtests=doctest.testmod()
1061 if numfail==0: print 'ok'
1062 else:
1063 print 'FAILED'
1064 success=False
1065
1066 if not success: sys.exit('Something Failed')
1067 del success
1068
1069 if options.unittest:
1070 sys.argv = [sys.argv[0]]
1071 if options.verbose: sys.argv.append('-v')
1072 unittest.main()
1073
1074 outfile = sys.stdout
1075 if None!=options.outputFileName:
1076 outfile = file(options.outputFileName,'w')
1077
1078
1079 if options.doEncode:
1080
1081 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
1082 if None==options.UserIDField: parser.error("missing value for UserIDField")
1083 if None==options.Time_yearField: parser.error("missing value for Time_yearField")
1084 if None==options.Time_monthField: parser.error("missing value for Time_monthField")
1085 if None==options.Time_dayField: parser.error("missing value for Time_dayField")
1086 if None==options.Time_hourField: parser.error("missing value for Time_hourField")
1087 if None==options.Time_minField: parser.error("missing value for Time_minField")
1088 if None==options.Time_secField: parser.error("missing value for Time_secField")
1089 if None==options.PositionAccuracyField: parser.error("missing value for PositionAccuracyField")
1090 if None==options.Position_longitudeField: parser.error("missing value for Position_longitudeField")
1091 if None==options.Position_latitudeField: parser.error("missing value for Position_latitudeField")
1092 if None==options.fixtypeField: parser.error("missing value for fixtypeField")
1093 if None==options.RAIMField: parser.error("missing value for RAIMField")
1094 if None==options.state_syncstateField: parser.error("missing value for state_syncstateField")
1095 if None==options.state_slottimeoutField: parser.error("missing value for state_slottimeoutField")
1096 if None==options.state_slotoffsetField: parser.error("missing value for state_slotoffsetField")
1097 msgDict={
1098 'MessageID': '4',
1099 'RepeatIndicator': options.RepeatIndicatorField,
1100 'UserID': options.UserIDField,
1101 'Time_year': options.Time_yearField,
1102 'Time_month': options.Time_monthField,
1103 'Time_day': options.Time_dayField,
1104 'Time_hour': options.Time_hourField,
1105 'Time_min': options.Time_minField,
1106 'Time_sec': options.Time_secField,
1107 'PositionAccuracy': options.PositionAccuracyField,
1108 'Position_longitude': options.Position_longitudeField,
1109 'Position_latitude': options.Position_latitudeField,
1110 'fixtype': options.fixtypeField,
1111 'Spare': '0',
1112 'RAIM': options.RAIMField,
1113 'state_syncstate': options.state_syncstateField,
1114 'state_slottimeout': options.state_slottimeoutField,
1115 'state_slotoffset': options.state_slotoffsetField,
1116 }
1117
1118 bits = encode(msgDict)
1119 if 'binary'==options.ioType: print str(bits)
1120 elif 'nmeapayload'==options.ioType:
1121
1122 print "bitLen",len(bits)
1123 bitLen=len(bits)
1124 if bitLen%6!=0:
1125 bits = bits + BitVector(size=(6 - (bitLen%6)))
1126 print "result:",binary.bitvectoais6(bits)[0]
1127
1128
1129
1130 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
1131 else: sys.exit('ERROR: unknown ioType. Help!')
1132
1133
1134 if options.sqlCreate:
1135 sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
1136
1137 if options.latexDefinitionTable:
1138 latexDefinitionTable(outfile)
1139
1140
1141 if options.textDefinitionTable:
1142 textDefinitionTable(outfile,options.delimTextDefinitionTable)
1143
1144 if options.printCsvfieldList:
1145
1146 if None == options.fieldList: options.fieldList = fieldList
1147 import StringIO
1148 buf = StringIO.StringIO()
1149 for field in options.fieldList:
1150 buf.write(field+',')
1151 result = buf.getvalue()
1152 if result[-1] == ',': print result[:-1]
1153 else: print result
1154
1155 if options.doDecode:
1156 if len(args)==0: args = sys.stdin
1157 for msg in args:
1158 bv = None
1159
1160 if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
1161
1162
1163 bv = binary.ais6tobitvec(msg.split(',')[5])
1164 else:
1165
1166 binaryMsg=True
1167 for c in msg:
1168 if c not in ('0','1'):
1169 binaryMsg=False
1170 break
1171 if binaryMsg:
1172 bv = BitVector(bitstring=msg)
1173 else:
1174 bv = binary.ais6tobitvec(msg)
1175
1176 printFields(decode(bv)
1177 ,out=outfile
1178 ,format=options.outputType
1179 ,fieldList=options.fieldList
1180 ,dbType=options.dbType
1181 )
1182