1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-01-18 $'.split()[1]
5 __author__ = 'xmlbinmsg'
6
7 __doc__='''
8
9 Autogenerated python functions to serialize/deserialize binary messages.
10
11 Generated by: ./aisxmlbinmsg2py.py
12
13 Need to then wrap these functions with the outer AIS packet and then
14 convert the whole binary blob to a NMEA string. Those functions are
15 not currently provided in this file.
16
17 serialize: python to ais binary
18 deserialize: ais binary to python
19
20 The generated code uses translators.py, binary.py, and aisstring.py
21 which should be packaged with the resulting files.
22
23
24 @requires: U{epydoc<http://epydoc.sourceforge.net/>} > 3.0alpha3
25 @requires: U{BitVector<http://cheeseshop.python.org/pypi/BitVector>}
26
27 @author: '''+__author__+'''
28 @version: ''' + __version__ +'''
29 @var __date__: Date of last svn commit
30 @undocumented: __version__ __author__ __doc__ parser
31 @status: under development
32 @license: Generated code has no license
33 '''
34
35 import sys
36 from decimal import Decimal
37 from BitVector import BitVector
38
39 import binary, aisstring
40
41
42 TrueBV = BitVector(bitstring="1")
43 "Why always rebuild the True bit? This should speed things up a bunch"
44 FalseBV = BitVector(bitstring="0")
45 "Why always rebuild the False bit? This should speed things up a bunch"
46
47
48 -def encode(params, validate=False):
49 '''Create a AidsToNavReport binary message payload to pack into an AIS Msg AidsToNavReport.
50
51 Fields in params:
52 - MessageID(uint): AIS message number. Must be 21 aka 'F' (field automatically set to "21")
53 - RepeatIndicator(uint): Indicated how many times a message has been repeated
54 - UserID(uint): Unique ship identification number (MMSI)
55 - type(uint): IALA type of aid-to-navigation
56 - name(aisstr6): Name of the aid-to-navigation
57 - PositionAccuracy(uint): Accuracy of positioning fixes
58 - Position_longitude(decimal): Location of the vessel East West location
59 - Position_latitude(decimal): Location of the vessel North South location
60 - dim(uint): FIX: break this out.
61 - FixType(uint): Type of electronic position fixing device
62 - timestamp(uint): UTC second when report was generated
63 - OffPosition(bool): True when the AtoN is off station
64 - RegionalApp(uint): Should be set to zero (field automatically set to "0")
65 - RAIM(bool): Receiver autonomous integrity monitoring flag
66 - Spare(uint): Not Used (field automatically set to "0")
67 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
68 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
69 @rtype: BitVector
70 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
71 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
72 '''
73
74 bvList = []
75 bvList.append(binary.setBitVectorSize(BitVector(intVal=21),6))
76 if 'RepeatIndicator' in params:
77 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2))
78 else:
79 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2))
80 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30))
81 if 'type' in params:
82 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['type']),5))
83 else:
84 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),5))
85 if 'name' in params:
86 bvList.append(aisstring.encode(params['name'],120))
87 else:
88 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@@@@@@',120))
89 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['PositionAccuracy']),1))
90 if 'Position_longitude' in params:
91 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_longitude'])*Decimal('600000')),28))
92 else:
93 bvList.append(binary.bvFromSignedInt(108600000,28))
94 if 'Position_latitude' in params:
95 bvList.append(binary.bvFromSignedInt(int(Decimal(params['Position_latitude'])*Decimal('600000')),27))
96 else:
97 bvList.append(binary.bvFromSignedInt(54600000,27))
98 if 'dim' in params:
99 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['dim']),30))
100 else:
101 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),30))
102 if 'FixType' in params:
103 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['FixType']),4))
104 else:
105 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),4))
106 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['timestamp']),6))
107 if params["OffPosition"]: bvList.append(TrueBV)
108 else: bvList.append(FalseBV)
109 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),8))
110 if params["RAIM"]: bvList.append(TrueBV)
111 else: bvList.append(FalseBV)
112 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),3))
113
114 return binary.joinBV(bvList)
115
116 -def decode(bv, validate=False):
117 '''Unpack a AidsToNavReport message
118
119 Fields in params:
120 - MessageID(uint): AIS message number. Must be 21 aka 'F' (field automatically set to "21")
121 - RepeatIndicator(uint): Indicated how many times a message has been repeated
122 - UserID(uint): Unique ship identification number (MMSI)
123 - type(uint): IALA type of aid-to-navigation
124 - name(aisstr6): Name of the aid-to-navigation
125 - PositionAccuracy(uint): Accuracy of positioning fixes
126 - Position_longitude(decimal): Location of the vessel East West location
127 - Position_latitude(decimal): Location of the vessel North South location
128 - dim(uint): FIX: break this out.
129 - FixType(uint): Type of electronic position fixing device
130 - timestamp(uint): UTC second when report was generated
131 - OffPosition(bool): True when the AtoN is off station
132 - RegionalApp(uint): Should be set to zero (field automatically set to "0")
133 - RAIM(bool): Receiver autonomous integrity monitoring flag
134 - Spare(uint): Not Used (field automatically set to "0")
135 @type bv: BitVector
136 @param bv: Bits defining a message
137 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
138 @rtype: dict
139 @return: params
140 '''
141
142
143
144
145 r = {}
146 r['MessageID']=21
147 r['RepeatIndicator']=int(bv[6:8])
148 r['UserID']=int(bv[8:38])
149 r['type']=int(bv[38:43])
150 r['name']=aisstring.decode(bv[43:163])
151 r['PositionAccuracy']=int(bv[163:164])
152 r['Position_longitude']=Decimal(binary.signedIntFromBV(bv[164:192]))/Decimal('600000')
153 r['Position_latitude']=Decimal(binary.signedIntFromBV(bv[192:219]))/Decimal('600000')
154 r['dim']=int(bv[219:249])
155 r['FixType']=int(bv[249:253])
156 r['timestamp']=int(bv[253:259])
157 r['OffPosition']=bool(int(bv[259:260]))
158 r['RegionalApp']=0
159 r['RAIM']=bool(int(bv[268:269]))
160 r['Spare']=0
161 return r
162
164 return 21
165
168
171
173 return int(bv[38:43])
174
177
179 return int(bv[163:164])
180
183
186
188 return int(bv[219:249])
189
191 return int(bv[249:253])
192
194 return int(bv[253:259])
195
197 return bool(int(bv[259:260]))
198
200 return 0
201
203 return bool(int(bv[268:269]))
204
206 return 0
207
208
210 out.write("<h3>AidsToNavReport<h3>\n")
211 out.write("<table border=\"1\">\n")
212 out.write("<tr bgcolor=\"orange\">\n")
213 out.write("<th align=\"left\">Field Name</th>\n")
214 out.write("<th align=\"left\">Type</th>\n")
215 out.write("<th align=\"left\">Value</th>\n")
216 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
217 out.write("<th align=\"left\">Units</th>\n")
218 out.write("\n")
219 out.write("<tr>\n")
220 out.write("<td>MessageID</td>\n")
221 out.write("<td>uint</td>\n")
222 if 'MessageID' in params:
223 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
224 out.write(" <td>"+str(params['MessageID'])+"</td>\n")
225 out.write("</tr>\n")
226 out.write("\n")
227 out.write("<tr>\n")
228 out.write("<td>RepeatIndicator</td>\n")
229 out.write("<td>uint</td>\n")
230 if 'RepeatIndicator' in params:
231 out.write(" <td>"+str(params['RepeatIndicator'])+"</td>\n")
232 if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut:
233 out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>")
234 else:
235 out.write("<td><i>Missing LUT entry</i></td>")
236 out.write("</tr>\n")
237 out.write("\n")
238 out.write("<tr>\n")
239 out.write("<td>UserID</td>\n")
240 out.write("<td>uint</td>\n")
241 if 'UserID' in params:
242 out.write(" <td>"+str(params['UserID'])+"</td>\n")
243 out.write(" <td>"+str(params['UserID'])+"</td>\n")
244 out.write("</tr>\n")
245 out.write("\n")
246 out.write("<tr>\n")
247 out.write("<td>type</td>\n")
248 out.write("<td>uint</td>\n")
249 if 'type' in params:
250 out.write(" <td>"+str(params['type'])+"</td>\n")
251 if str(params['type']) in typeDecodeLut:
252 out.write("<td>"+typeDecodeLut[str(params['type'])]+"</td>")
253 else:
254 out.write("<td><i>Missing LUT entry</i></td>")
255 out.write("</tr>\n")
256 out.write("\n")
257 out.write("<tr>\n")
258 out.write("<td>name</td>\n")
259 out.write("<td>aisstr6</td>\n")
260 if 'name' in params:
261 out.write(" <td>"+str(params['name'])+"</td>\n")
262 out.write(" <td>"+str(params['name'])+"</td>\n")
263 out.write("</tr>\n")
264 out.write("\n")
265 out.write("<tr>\n")
266 out.write("<td>PositionAccuracy</td>\n")
267 out.write("<td>uint</td>\n")
268 if 'PositionAccuracy' in params:
269 out.write(" <td>"+str(params['PositionAccuracy'])+"</td>\n")
270 if str(params['PositionAccuracy']) in PositionAccuracyDecodeLut:
271 out.write("<td>"+PositionAccuracyDecodeLut[str(params['PositionAccuracy'])]+"</td>")
272 else:
273 out.write("<td><i>Missing LUT entry</i></td>")
274 out.write("</tr>\n")
275 out.write("\n")
276 out.write("<tr>\n")
277 out.write("<td>Position_longitude</td>\n")
278 out.write("<td>decimal</td>\n")
279 if 'Position_longitude' in params:
280 out.write(" <td>"+str(params['Position_longitude'])+"</td>\n")
281 out.write(" <td>"+str(params['Position_longitude'])+"</td>\n")
282 out.write("<td>degrees</td>\n")
283 out.write("</tr>\n")
284 out.write("\n")
285 out.write("<tr>\n")
286 out.write("<td>Position_latitude</td>\n")
287 out.write("<td>decimal</td>\n")
288 if 'Position_latitude' in params:
289 out.write(" <td>"+str(params['Position_latitude'])+"</td>\n")
290 out.write(" <td>"+str(params['Position_latitude'])+"</td>\n")
291 out.write("<td>degrees</td>\n")
292 out.write("</tr>\n")
293 out.write("\n")
294 out.write("<tr>\n")
295 out.write("<td>dim</td>\n")
296 out.write("<td>uint</td>\n")
297 if 'dim' in params:
298 out.write(" <td>"+str(params['dim'])+"</td>\n")
299 out.write(" <td>"+str(params['dim'])+"</td>\n")
300 out.write("</tr>\n")
301 out.write("\n")
302 out.write("<tr>\n")
303 out.write("<td>FixType</td>\n")
304 out.write("<td>uint</td>\n")
305 if 'FixType' in params:
306 out.write(" <td>"+str(params['FixType'])+"</td>\n")
307 if str(params['FixType']) in FixTypeDecodeLut:
308 out.write("<td>"+FixTypeDecodeLut[str(params['FixType'])]+"</td>")
309 else:
310 out.write("<td><i>Missing LUT entry</i></td>")
311 out.write("</tr>\n")
312 out.write("\n")
313 out.write("<tr>\n")
314 out.write("<td>timestamp</td>\n")
315 out.write("<td>uint</td>\n")
316 if 'timestamp' in params:
317 out.write(" <td>"+str(params['timestamp'])+"</td>\n")
318 if str(params['timestamp']) in timestampDecodeLut:
319 out.write("<td>"+timestampDecodeLut[str(params['timestamp'])]+"</td>")
320 else:
321 out.write("<td><i>Missing LUT entry</i></td>")
322 out.write("</tr>\n")
323 out.write("\n")
324 out.write("<tr>\n")
325 out.write("<td>OffPosition</td>\n")
326 out.write("<td>bool</td>\n")
327 if 'OffPosition' in params:
328 out.write(" <td>"+str(params['OffPosition'])+"</td>\n")
329 if str(params['OffPosition']) in OffPositionDecodeLut:
330 out.write("<td>"+OffPositionDecodeLut[str(params['OffPosition'])]+"</td>")
331 else:
332 out.write("<td><i>Missing LUT entry</i></td>")
333 out.write("</tr>\n")
334 out.write("\n")
335 out.write("<tr>\n")
336 out.write("<td>RegionalApp</td>\n")
337 out.write("<td>uint</td>\n")
338 if 'RegionalApp' in params:
339 out.write(" <td>"+str(params['RegionalApp'])+"</td>\n")
340 out.write(" <td>"+str(params['RegionalApp'])+"</td>\n")
341 out.write("</tr>\n")
342 out.write("\n")
343 out.write("<tr>\n")
344 out.write("<td>RAIM</td>\n")
345 out.write("<td>bool</td>\n")
346 if 'RAIM' in params:
347 out.write(" <td>"+str(params['RAIM'])+"</td>\n")
348 if str(params['RAIM']) in RAIMDecodeLut:
349 out.write("<td>"+RAIMDecodeLut[str(params['RAIM'])]+"</td>")
350 else:
351 out.write("<td><i>Missing LUT entry</i></td>")
352 out.write("</tr>\n")
353 out.write("\n")
354 out.write("<tr>\n")
355 out.write("<td>Spare</td>\n")
356 out.write("<td>uint</td>\n")
357 if 'Spare' in params:
358 out.write(" <td>"+str(params['Spare'])+"</td>\n")
359 out.write(" <td>"+str(params['Spare'])+"</td>\n")
360 out.write("</tr>\n")
361 out.write("</table>\n")
362
364 '''KML (Keyhole Markup Language) for Google Earth, but without the header/footer'''
365 out.write("\ <Placemark>\n")
366 out.write("\t <name>"+str(params['UserID'])+"</name>\n")
367 out.write("\t\t<description>\n")
368 import StringIO
369 buf = StringIO.StringIO()
370 printHtml(params,buf)
371 import cgi
372 out.write(cgi.escape(buf.getvalue()))
373 out.write("\t\t</description>\n")
374 out.write("\t\t<styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
375 out.write("\t\t<Point>\n")
376 out.write("\t\t\t<coordinates>")
377 out.write(str(params['Position_longitude']))
378 out.write(',')
379 out.write(str(params['Position_latitude']))
380 out.write(",0</coordinates>\n")
381 out.write("\t\t</Point>\n")
382 out.write("\t</Placemark>\n")
383
385 '''Print a Spare message to stdout.
386
387 Fields in params:
388 - MessageID(uint): AIS message number. Must be 21 aka 'F' (field automatically set to "21")
389 - RepeatIndicator(uint): Indicated how many times a message has been repeated
390 - UserID(uint): Unique ship identification number (MMSI)
391 - type(uint): IALA type of aid-to-navigation
392 - name(aisstr6): Name of the aid-to-navigation
393 - PositionAccuracy(uint): Accuracy of positioning fixes
394 - Position_longitude(decimal): Location of the vessel East West location
395 - Position_latitude(decimal): Location of the vessel North South location
396 - dim(uint): FIX: break this out.
397 - FixType(uint): Type of electronic position fixing device
398 - timestamp(uint): UTC second when report was generated
399 - OffPosition(bool): True when the AtoN is off station
400 - RegionalApp(uint): Should be set to zero (field automatically set to "0")
401 - RAIM(bool): Receiver autonomous integrity monitoring flag
402 - Spare(uint): Not Used (field automatically set to "0")
403 @param params: Dictionary of field names/values.
404 @param out: File like object to write to
405 @rtype: stdout
406 @return: text to out
407 '''
408
409 if 'std'==format:
410 out.write("Spare:\n")
411 if 'MessageID' in params: out.write(" MessageID: "+str(params['MessageID'])+"\n")
412 if 'RepeatIndicator' in params: out.write(" RepeatIndicator: "+str(params['RepeatIndicator'])+"\n")
413 if 'UserID' in params: out.write(" UserID: "+str(params['UserID'])+"\n")
414 if 'type' in params: out.write(" type: "+str(params['type'])+"\n")
415 if 'name' in params: out.write(" name: "+str(params['name'])+"\n")
416 if 'PositionAccuracy' in params: out.write(" PositionAccuracy: "+str(params['PositionAccuracy'])+"\n")
417 if 'Position_longitude' in params: out.write(" Position_longitude: "+str(params['Position_longitude'])+"\n")
418 if 'Position_latitude' in params: out.write(" Position_latitude: "+str(params['Position_latitude'])+"\n")
419 if 'dim' in params: out.write(" dim: "+str(params['dim'])+"\n")
420 if 'FixType' in params: out.write(" FixType: "+str(params['FixType'])+"\n")
421 if 'timestamp' in params: out.write(" timestamp: "+str(params['timestamp'])+"\n")
422 if 'OffPosition' in params: out.write(" OffPosition: "+str(params['OffPosition'])+"\n")
423 if 'RegionalApp' in params: out.write(" RegionalApp: "+str(params['RegionalApp'])+"\n")
424 if 'RAIM' in params: out.write(" RAIM: "+str(params['RAIM'])+"\n")
425 if 'Spare' in params: out.write(" Spare: "+str(params['Spare'])+"\n")
426 elif 'html'==format:
427 printHtml(params,out)
428 elif 'kml'==format:
429 printKml(params,out)
430 elif 'kml-full'==format:
431 out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
432 out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
433 out.write("<Document>\n")
434 out.write(" <name>Position</name>\n")
435 printKml(params,out)
436 out.write("</Document>\n")
437 out.write("</kml>\n")
438 else:
439 print "ERROR: unknown format:",format
440 assert False
441
442 return
443
444 RepeatIndicatorEncodeLut = {
445 'default':'0',
446 'do not repeat any more':'3',
447 }
448
449 RepeatIndicatorDecodeLut = {
450 '0':'default',
451 '3':'do not repeat any more',
452 }
453
454 typeEncodeLut = {
455 'Default, Type of A to N not specified':'0',
456 'Reference point':'1',
457 'RACON':'2',
458 'Off Shore Structure':'3',
459 'Spare':'4',
460 'Light, without sectors':'5',
461 'Light, with sectors':'6',
462 'Leading Light Front':'7',
463 'Leading Light Rear':'8',
464 'Beacon, Cardinal N':'9',
465 'Beacon, Cardinal E':'10',
466 'Beacon, Cardinal S':'11',
467 'Beacon, Cardinal W':'12',
468 'Beacon, Port hand':'13',
469 'Beacon, Starbord hand':'14',
470 'Beacon, Preferred channel port hand':'15',
471 'Beacon, Preferred channel starboard hand':'16',
472 'Beacon, Isolated danger':'17',
473 'Beacon, Safe water':'18',
474 'Beacon, Special mark':'19',
475 'Cardinal Mark N':'20',
476 'Cardinal Mark E':'21',
477 'Cardinal Mark S':'22',
478 'Cardinal Mark W':'23',
479 'Port hand Mark':'24',
480 'Starbord hand Mark':'25',
481 'Preferred Channel Port hand':'26',
482 'Preferred Channel Starboard hand':'27',
483 'Isolated danger':'28',
484 'Safe water':'29',
485 'Special Mark':'30',
486 'Light Vessel/LANBY':'31',
487 }
488
489 typeDecodeLut = {
490 '0':'Default, Type of A to N not specified',
491 '1':'Reference point',
492 '2':'RACON',
493 '3':'Off Shore Structure',
494 '4':'Spare',
495 '5':'Light, without sectors',
496 '6':'Light, with sectors',
497 '7':'Leading Light Front',
498 '8':'Leading Light Rear',
499 '9':'Beacon, Cardinal N',
500 '10':'Beacon, Cardinal E',
501 '11':'Beacon, Cardinal S',
502 '12':'Beacon, Cardinal W',
503 '13':'Beacon, Port hand',
504 '14':'Beacon, Starbord hand',
505 '15':'Beacon, Preferred channel port hand',
506 '16':'Beacon, Preferred channel starboard hand',
507 '17':'Beacon, Isolated danger',
508 '18':'Beacon, Safe water',
509 '19':'Beacon, Special mark',
510 '20':'Cardinal Mark N',
511 '21':'Cardinal Mark E',
512 '22':'Cardinal Mark S',
513 '23':'Cardinal Mark W',
514 '24':'Port hand Mark',
515 '25':'Starbord hand Mark',
516 '26':'Preferred Channel Port hand',
517 '27':'Preferred Channel Starboard hand',
518 '28':'Isolated danger',
519 '29':'Safe water',
520 '30':'Special Mark',
521 '31':'Light Vessel/LANBY',
522 }
523
524 PositionAccuracyEncodeLut = {
525 'low (greater than 10 m)':'0',
526 'high (less than 10 m)':'1',
527 }
528
529 PositionAccuracyDecodeLut = {
530 '0':'low (greater than 10 m)',
531 '1':'high (less than 10 m)',
532 }
533
534 FixTypeEncodeLut = {
535 'Undefined (default)':'0',
536 'GPS':'1',
537 'GLONASS':'2',
538 'Combined GPS/GLONASS':'3',
539 'Loran-C':'4',
540 'Chayka':'5',
541 'Integrated Navigation System':'6',
542 'surveyed':'7',
543 'not used - 8':'8',
544 'not used - 9':'9',
545 'not used - 10':'10',
546 'not used - 11':'11',
547 'not used - 12':'12',
548 'not used - 13':'13',
549 'not used - 14':'14',
550 'not used - 15':'15',
551 }
552
553 FixTypeDecodeLut = {
554 '0':'Undefined (default)',
555 '1':'GPS',
556 '2':'GLONASS',
557 '3':'Combined GPS/GLONASS',
558 '4':'Loran-C',
559 '5':'Chayka',
560 '6':'Integrated Navigation System',
561 '7':'surveyed',
562 '8':'not used - 8',
563 '9':'not used - 9',
564 '10':'not used - 10',
565 '11':'not used - 11',
566 '12':'not used - 12',
567 '13':'not used - 13',
568 '14':'not used - 14',
569 '15':'not used - 15',
570 }
571
572 timestampEncodeLut = {
573 'Positioning system is in manual mode':'61',
574 'Electronic position fixing system operates in estimated mode':'62',
575 'Positioning system is inoperative':'63',
576 }
577
578 timestampDecodeLut = {
579 '61':'Positioning system is in manual mode',
580 '62':'Electronic position fixing system operates in estimated mode',
581 '63':'Positioning system is inoperative',
582 }
583
584 OffPositionEncodeLut = {
585 'On position':'False',
586 'Off position':'True',
587 }
588
589 OffPositionDecodeLut = {
590 'False':'On position',
591 'True':'Off position',
592 }
593
594 RAIMEncodeLut = {
595 'not in use':'False',
596 'in use':'True',
597 }
598
599 RAIMDecodeLut = {
600 'False':'not in use',
601 'True':'in use',
602 }
603
604
605
606
607
608
609 import unittest
611 '''Return a params file base on the testvalue tags.
612 @rtype: dict
613 @return: params based on testvalue tags
614 '''
615 params = {}
616 params['MessageID'] = 21
617 params['RepeatIndicator'] = 1
618 params['UserID'] = 1193046
619 params['type'] = 28
620 params['name'] = 'BUNCH OF ROCKS ATON@'
621 params['PositionAccuracy'] = 1
622 params['Position_longitude'] = Decimal('-122.16328055555556')
623 params['Position_latitude'] = Decimal('37.424458333333334')
624 params['dim'] = 0
625 params['FixType'] = 2
626 params['timestamp'] = 62
627 params['OffPosition'] = False
628 params['RegionalApp'] = 0
629 params['RAIM'] = False
630 params['Spare'] = 0
631
632 return params
633
635 '''Use testvalue tag text from each type to build test case the AidsToNavReport message'''
637
638 params = testParams()
639 bits = encode(params)
640 r = decode(bits)
641
642
643 self.failUnlessEqual(r['MessageID'],params['MessageID'])
644 self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator'])
645 self.failUnlessEqual(r['UserID'],params['UserID'])
646 self.failUnlessEqual(r['type'],params['type'])
647 self.failUnlessEqual(r['name'],params['name'])
648 self.failUnlessEqual(r['PositionAccuracy'],params['PositionAccuracy'])
649 self.failUnlessAlmostEqual(r['Position_longitude'],params['Position_longitude'],5)
650 self.failUnlessAlmostEqual(r['Position_latitude'],params['Position_latitude'],5)
651 self.failUnlessEqual(r['dim'],params['dim'])
652 self.failUnlessEqual(r['FixType'],params['FixType'])
653 self.failUnlessEqual(r['timestamp'],params['timestamp'])
654 self.failUnlessEqual(r['OffPosition'],params['OffPosition'])
655 self.failUnlessEqual(r['RegionalApp'],params['RegionalApp'])
656 self.failUnlessEqual(r['RAIM'],params['RAIM'])
657 self.failUnlessEqual(r['Spare'],params['Spare'])
658
660 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
661 help='decode a "AidsToNavReport" AIS message')
662 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
663 help='encode a "AidsToNavReport" AIS message')
664 parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int'
665 ,help='Field parameter value [default: %default]')
666 parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int'
667 ,help='Field parameter value [default: %default]')
668 parser.add_option('--type-field', dest='typeField',default=0,metavar='uint',type='int'
669 ,help='Field parameter value [default: %default]')
670 parser.add_option('--name-field', dest='nameField',default='@@@@@@@@@@@@@@@@@@@@',metavar='aisstr6',type='string'
671 ,help='Field parameter value [default: %default]')
672 parser.add_option('--PositionAccuracy-field', dest='PositionAccuracyField',metavar='uint',type='int'
673 ,help='Field parameter value [default: %default]')
674 parser.add_option('--Position_longitude-field', dest='Position_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
675 ,help='Field parameter value [default: %default]')
676 parser.add_option('--Position_latitude-field', dest='Position_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
677 ,help='Field parameter value [default: %default]')
678 parser.add_option('--dim-field', dest='dimField',default=0,metavar='uint',type='int'
679 ,help='Field parameter value [default: %default]')
680 parser.add_option('--FixType-field', dest='FixTypeField',default=0,metavar='uint',type='int'
681 ,help='Field parameter value [default: %default]')
682 parser.add_option('--timestamp-field', dest='timestampField',metavar='uint',type='int'
683 ,help='Field parameter value [default: %default]')
684 parser.add_option('--OffPosition-field', dest='OffPositionField',metavar='bool',type='int'
685 ,help='Field parameter value [default: %default]')
686 parser.add_option('--RAIM-field', dest='RAIMField',metavar='bool',type='int'
687 ,help='Field parameter value [default: %default]')
688
689
690 if __name__=='__main__':
691
692 from optparse import OptionParser
693 parser = OptionParser(usage="%prog [options]",
694 version="%prog "+__version__)
695
696 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
697 help='run the documentation tests')
698 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
699 help='run the unit tests')
700 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
701 help='Make the test output verbose')
702
703
704
705 typeChoices = ('binary','nmeapayload','nmea')
706 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
707 ,default='nmeapayload'
708 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]')
709
710
711 outputChoices = ('std','html','xml' , 'kml','kml-full')
712 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
713 ,default='std'
714 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
715
716 parser.add_option('-o','--output',dest='outputFileName',default=None,
717 help='Name of the python file to write [default: stdout]')
718
719 addMsgOptions(parser)
720
721 (options,args) = parser.parse_args()
722 success=True
723
724 if options.doctest:
725 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
726 sys.argv= [sys.argv[0]]
727 if options.verbose: sys.argv.append('-v')
728 import doctest
729 numfail,numtests=doctest.testmod()
730 if numfail==0: print 'ok'
731 else:
732 print 'FAILED'
733 success=False
734
735 if not success: sys.exit('Something Failed')
736 del success
737
738 if options.unittest:
739 sys.argv = [sys.argv[0]]
740 if options.verbose: sys.argv.append('-v')
741 unittest.main()
742
743 outfile = sys.stdout
744 if None!=options.outputFileName:
745 outfile = file(options.outputFileName,'w')
746
747
748 if options.doEncode:
749
750 if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField")
751 if None==options.UserIDField: parser.error("missing value for UserIDField")
752 if None==options.typeField: parser.error("missing value for typeField")
753 if None==options.nameField: parser.error("missing value for nameField")
754 if None==options.PositionAccuracyField: parser.error("missing value for PositionAccuracyField")
755 if None==options.Position_longitudeField: parser.error("missing value for Position_longitudeField")
756 if None==options.Position_latitudeField: parser.error("missing value for Position_latitudeField")
757 if None==options.dimField: parser.error("missing value for dimField")
758 if None==options.FixTypeField: parser.error("missing value for FixTypeField")
759 if None==options.timestampField: parser.error("missing value for timestampField")
760 if None==options.OffPositionField: parser.error("missing value for OffPositionField")
761 if None==options.RAIMField: parser.error("missing value for RAIMField")
762 msgDict={
763 'MessageID': '21',
764 'RepeatIndicator': options.RepeatIndicatorField,
765 'UserID': options.UserIDField,
766 'type': options.typeField,
767 'name': options.nameField,
768 'PositionAccuracy': options.PositionAccuracyField,
769 'Position_longitude': options.Position_longitudeField,
770 'Position_latitude': options.Position_latitudeField,
771 'dim': options.dimField,
772 'FixType': options.FixTypeField,
773 'timestamp': options.timestampField,
774 'OffPosition': options.OffPositionField,
775 'RegionalApp': '0',
776 'RAIM': options.RAIMField,
777 'Spare': '0',
778 }
779
780 bits = encode(msgDict)
781 if 'binary'==options.ioType: print str(bits)
782 elif 'nmeapayload'==options.ioType:
783
784 print "bitLen",len(bits)
785 bitLen=len(bits)
786 if bitLen%6!=0:
787 bits = bits + BitVector(size=(6 - (bitLen%6)))
788 print "result:",binary.bitvectoais6(bits)[0]
789
790
791
792 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
793 else: sys.exit('ERROR: unknown ioType. Help!')
794
795 if options.doDecode:
796 for msg in args:
797 bv = None
798 if 'binary' == options.ioType: bv = BitVector(bitstring=msg)
799 elif 'nmeapayload'== options.ioType: bv = binary.ais6tobitvec(msg)
800 elif 'nmea' == options.ioType: bv = binary.ais6tobitvec(msg.split(',')[5])
801 else: sys.exit('ERROR: unknown ioType. Help!')
802
803 printFields(decode(bv),out=outfile,format=options.outputType)
804