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