1
2
3 __version__ = '$Revision: 4791 $'.split()[1]
4 __date__ = '$Date: 2007-02-08 $'.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 fieldList = [
49 'vessel',
50 'direction',
51 'ETA_month',
52 'ETA_day',
53 'ETA_hour',
54 'ETA_min',
55 'reserved',
56 ]
57
58 -def encode(params, validate=False):
59 '''Create a sls_lockorder binary message payload to pack into an AIS Msg sls_lockorder.
60
61 Fields in params:
62 - vessel(aisstr6): Vessel Name
63 - direction(bool): Up bound/Down bound
64 - ETA_month(uint): Estimated time of arrival month 1..12
65 - ETA_day(uint): Estimated time of arrival day of the month 1..31
66 - ETA_hour(uint): Estimated time of arrival UTC hours 0..23
67 - ETA_min(uint): Estimated time of arrival minutes
68 - reserved(uint): Reserved bits for future use (field automatically set to "0")
69 @param params: Dictionary of field names/values. Throws a ValueError exception if required is missing
70 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
71 @rtype: BitVector
72 @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
73 @note: The returned bits may not be 6 bit aligned. It is up to you to pad out the bits.
74 '''
75
76 bvList = []
77 if 'vessel' in params:
78 bvList.append(aisstring.encode(params['vessel'],90))
79 else:
80 bvList.append(aisstring.encode('@@@@@@@@@@@@@@@',90))
81 if params["direction"]: bvList.append(TrueBV)
82 else: bvList.append(FalseBV)
83 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETA_month']),4))
84 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETA_day']),5))
85 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETA_hour']),5))
86 bvList.append(binary.setBitVectorSize(BitVector(intVal=params['ETA_min']),6))
87 bvList.append(binary.setBitVectorSize(BitVector(intVal=0),19))
88
89 return binary.joinBV(bvList)
90
91 -def decode(bv, validate=False):
92 '''Unpack a sls_lockorder message
93
94 Fields in params:
95 - vessel(aisstr6): Vessel Name
96 - direction(bool): Up bound/Down bound
97 - ETA_month(uint): Estimated time of arrival month 1..12
98 - ETA_day(uint): Estimated time of arrival day of the month 1..31
99 - ETA_hour(uint): Estimated time of arrival UTC hours 0..23
100 - ETA_min(uint): Estimated time of arrival minutes
101 - reserved(uint): Reserved bits for future use (field automatically set to "0")
102 @type bv: BitVector
103 @param bv: Bits defining a message
104 @param validate: Set to true to cause checking to occur. Runs slower. FIX: not implemented.
105 @rtype: dict
106 @return: params
107 '''
108
109
110
111
112 r = {}
113 r['vessel']=aisstring.decode(bv[0:90])
114 r['direction']=bool(int(bv[90:91]))
115 r['ETA_month']=int(bv[91:95])
116 r['ETA_day']=int(bv[95:100])
117 r['ETA_hour']=int(bv[100:105])
118 r['ETA_min']=int(bv[105:111])
119 r['reserved']=0
120 return r
121
124
126 return bool(int(bv[90:91]))
127
129 return int(bv[91:95])
130
132 return int(bv[95:100])
133
135 return int(bv[100:105])
136
138 return int(bv[105:111])
139
141 return 0
142
143
145 out.write("<h3>sls_lockorder<h3>\n")
146 out.write("<table border=\"1\">\n")
147 out.write("<tr bgcolor=\"orange\">\n")
148 out.write("<th align=\"left\">Field Name</th>\n")
149 out.write("<th align=\"left\">Type</th>\n")
150 out.write("<th align=\"left\">Value</th>\n")
151 out.write("<th align=\"left\">Value in Lookup Table</th>\n")
152 out.write("<th align=\"left\">Units</th>\n")
153 out.write("\n")
154 out.write("<tr>\n")
155 out.write("<td>vessel</td>\n")
156 out.write("<td>aisstr6</td>\n")
157 if 'vessel' in params:
158 out.write(" <td>"+str(params['vessel'])+"</td>\n")
159 out.write(" <td>"+str(params['vessel'])+"</td>\n")
160 out.write("</tr>\n")
161 out.write("\n")
162 out.write("<tr>\n")
163 out.write("<td>direction</td>\n")
164 out.write("<td>bool</td>\n")
165 if 'direction' in params:
166 out.write(" <td>"+str(params['direction'])+"</td>\n")
167 if str(params['direction']) in directionDecodeLut:
168 out.write("<td>"+directionDecodeLut[str(params['direction'])]+"</td>")
169 else:
170 out.write("<td><i>Missing LUT entry</i></td>")
171 out.write("</tr>\n")
172 out.write("\n")
173 out.write("<tr>\n")
174 out.write("<td>ETA_month</td>\n")
175 out.write("<td>uint</td>\n")
176 if 'ETA_month' in params:
177 out.write(" <td>"+str(params['ETA_month'])+"</td>\n")
178 out.write(" <td>"+str(params['ETA_month'])+"</td>\n")
179 out.write("</tr>\n")
180 out.write("\n")
181 out.write("<tr>\n")
182 out.write("<td>ETA_day</td>\n")
183 out.write("<td>uint</td>\n")
184 if 'ETA_day' in params:
185 out.write(" <td>"+str(params['ETA_day'])+"</td>\n")
186 out.write(" <td>"+str(params['ETA_day'])+"</td>\n")
187 out.write("</tr>\n")
188 out.write("\n")
189 out.write("<tr>\n")
190 out.write("<td>ETA_hour</td>\n")
191 out.write("<td>uint</td>\n")
192 if 'ETA_hour' in params:
193 out.write(" <td>"+str(params['ETA_hour'])+"</td>\n")
194 out.write(" <td>"+str(params['ETA_hour'])+"</td>\n")
195 out.write("</tr>\n")
196 out.write("\n")
197 out.write("<tr>\n")
198 out.write("<td>ETA_min</td>\n")
199 out.write("<td>uint</td>\n")
200 if 'ETA_min' in params:
201 out.write(" <td>"+str(params['ETA_min'])+"</td>\n")
202 out.write(" <td>"+str(params['ETA_min'])+"</td>\n")
203 out.write("</tr>\n")
204 out.write("\n")
205 out.write("<tr>\n")
206 out.write("<td>reserved</td>\n")
207 out.write("<td>uint</td>\n")
208 if 'reserved' in params:
209 out.write(" <td>"+str(params['reserved'])+"</td>\n")
210 out.write(" <td>"+str(params['reserved'])+"</td>\n")
211 out.write("</tr>\n")
212 out.write("</table>\n")
213
214 -def printFields(params, out=sys.stdout, format='std', fieldList=None):
215 '''Print a reserved message to stdout.
216
217 Fields in params:
218 - vessel(aisstr6): Vessel Name
219 - direction(bool): Up bound/Down bound
220 - ETA_month(uint): Estimated time of arrival month 1..12
221 - ETA_day(uint): Estimated time of arrival day of the month 1..31
222 - ETA_hour(uint): Estimated time of arrival UTC hours 0..23
223 - ETA_min(uint): Estimated time of arrival minutes
224 - reserved(uint): Reserved bits for future use (field automatically set to "0")
225 @param params: Dictionary of field names/values.
226 @param out: File like object to write to
227 @rtype: stdout
228 @return: text to out
229 '''
230
231 if 'std'==format:
232 out.write("reserved:\n")
233 if 'vessel' in params: out.write(" vessel: "+str(params['vessel'])+"\n")
234 if 'direction' in params: out.write(" direction: "+str(params['direction'])+"\n")
235 if 'ETA_month' in params: out.write(" ETA_month: "+str(params['ETA_month'])+"\n")
236 if 'ETA_day' in params: out.write(" ETA_day: "+str(params['ETA_day'])+"\n")
237 if 'ETA_hour' in params: out.write(" ETA_hour: "+str(params['ETA_hour'])+"\n")
238 if 'ETA_min' in params: out.write(" ETA_min: "+str(params['ETA_min'])+"\n")
239 if 'reserved' in params: out.write(" reserved: "+str(params['reserved'])+"\n")
240 elif 'csv'==format:
241 if None == options.fieldList:
242 options.fieldList = fieldList
243 needComma = False;
244 for field in fieldList:
245 if needComma: out.write(',')
246 needComma = True
247 if field in params:
248 out.write(str(params[field]))
249
250 out.write("\n")
251 elif 'html'==format:
252 printHtml(params,out)
253 elif 'sql'==format:
254 sqlInsertStr(params,out)
255 else:
256 print "ERROR: unknown format:",format
257 assert False
258
259 return
260
261 directionEncodeLut = {
262 'Down bound':'0',
263 'Up bound':'1',
264 }
265
266 directionDecodeLut = {
267 '0':'Down bound',
268 '1':'Up bound',
269 }
270
271
272
273
274
275 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None, addCoastGuardFields=True):
276 '''
277 Return the SQL CREATE command for this message type
278 @param outfile: file like object to print to.
279 @param fields: which fields to put in the create. Defaults to all.
280 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
281 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
282 @type addCoastGuardFields: bool
283 @return: sql create string
284 @rtype: str
285
286 @see: sqlCreate
287 '''
288 outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields)))
289
290 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True):
291 '''
292 Return the sqlhelp object to create the table.
293
294 @param fields: which fields to put in the create. Defaults to all.
295 @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
296 @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
297 @type addCoastGuardFields: bool
298 @return: An object that can be used to generate a return
299 @rtype: sqlhelp.create
300 '''
301 if None == fields: fields = fieldList
302 import sqlhelp
303 c = sqlhelp.create('sls_lockorder')
304 if 'vessel' in fields: c.addVarChar('vessel',15)
305 if 'direction' in fields: c.addBool('direction')
306 if 'ETA_month' in fields: c.addInt ('ETA_month')
307 if 'ETA_day' in fields: c.addInt ('ETA_day')
308 if 'ETA_hour' in fields: c.addInt ('ETA_hour')
309 if 'ETA_min' in fields: c.addInt ('ETA_min')
310 if 'reserved' in fields: c.addInt ('reserved')
311
312 if addCoastGuardFields:
313
314
315
316
317
318 c.addVarChar('cg_r',15)
319 c.addInt('cg_timestamp')
320
321
322 return c
323
324 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None):
325 '''
326 Return the SQL CREATE command for this message type
327 @param params: dictionary of values keyed by field name
328 @param outfile: file like object to print to.
329 @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
330 @return: sql create string
331 @rtype: str
332
333 @see: sqlCreate
334 '''
335 outfile.write(str(sqlInsert(params,extraParams)))
336
337
339 '''
340 Give the SQL insert statement
341 @param params: dict keyed by field name of values
342 @param extraParams: any extra fields that you have created beyond the normal ais message fields
343 @rtype: sqlhelp.insert
344 @return: insert class instance
345 @todo: allow optional type checking of params?
346 @warning: this will take invalid keys happily and do what???
347 '''
348 import sqlhelp
349 i = sqlhelp.insert('sls_lockorder')
350 for key in params:
351
352 if type(params[key])==Decimal: i.add(key,float(params[key]))
353 else: i.add(key,params[key])
354 if None != extraParams:
355 for key in extraParams:
356 i.add(key,extraParams[key])
357
358 return i
359
360
361
362
363
364 import unittest
366 '''Return a params file base on the testvalue tags.
367 @rtype: dict
368 @return: params based on testvalue tags
369 '''
370 params = {}
371 params['vessel'] = 'ICEBERG@@@@@@@@'
372 params['direction'] = True
373 params['ETA_month'] = 2
374 params['ETA_day'] = 28
375 params['ETA_hour'] = 23
376 params['ETA_min'] = 45
377 params['reserved'] = 0
378
379 return params
380
382 '''Use testvalue tag text from each type to build test case the sls_lockorder message'''
384
385 params = testParams()
386 bits = encode(params)
387 r = decode(bits)
388
389
390 self.failUnlessEqual(r['vessel'],params['vessel'])
391 self.failUnlessEqual(r['direction'],params['direction'])
392 self.failUnlessEqual(r['ETA_month'],params['ETA_month'])
393 self.failUnlessEqual(r['ETA_day'],params['ETA_day'])
394 self.failUnlessEqual(r['ETA_hour'],params['ETA_hour'])
395 self.failUnlessEqual(r['ETA_min'],params['ETA_min'])
396 self.failUnlessEqual(r['reserved'],params['reserved'])
397
399 parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
400 help='decode a "sls_lockorder" AIS message')
401 parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
402 help='encode a "sls_lockorder" AIS message')
403 parser.add_option('--vessel-field', dest='vesselField',default='@@@@@@@@@@@@@@@',metavar='aisstr6',type='string'
404 ,help='Field parameter value [default: %default]')
405 parser.add_option('--direction-field', dest='directionField',metavar='bool',type='int'
406 ,help='Field parameter value [default: %default]')
407 parser.add_option('--ETA_month-field', dest='ETA_monthField',metavar='uint',type='int'
408 ,help='Field parameter value [default: %default]')
409 parser.add_option('--ETA_day-field', dest='ETA_dayField',metavar='uint',type='int'
410 ,help='Field parameter value [default: %default]')
411 parser.add_option('--ETA_hour-field', dest='ETA_hourField',metavar='uint',type='int'
412 ,help='Field parameter value [default: %default]')
413 parser.add_option('--ETA_min-field', dest='ETA_minField',metavar='uint',type='int'
414 ,help='Field parameter value [default: %default]')
415
416
417 if __name__=='__main__':
418
419 from optparse import OptionParser
420 parser = OptionParser(usage="%prog [options]",
421 version="%prog "+__version__)
422
423 parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
424 help='run the documentation tests')
425 parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
426 help='run the unit tests')
427 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
428 help='Make the test output verbose')
429
430
431
432 typeChoices = ('binary','nmeapayload','nmea')
433 parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType'
434 ,default='nmeapayload'
435 ,help='What kind of string to expect ('+', '.join(typeChoices)+') [default: %default]')
436
437
438 outputChoices = ('std','html','csv','sql' )
439 parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType'
440 ,default='std'
441 ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]')
442
443 parser.add_option('-o','--output',dest='outputFileName',default=None,
444 help='Name of the python file to write [default: stdout]')
445
446 parser.add_option('-f','--fields',dest='fieldList',default=None, action='append',
447 choices=fieldList,
448 help='Which fields to include in the output. Currently only for csv output [default: all]')
449
450 parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true',
451 help='Print the field name for csv')
452
453 parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true',
454 help='Print out an sql create command for the table.')
455
456 addMsgOptions(parser)
457
458 (options,args) = parser.parse_args()
459 success=True
460
461 if options.doctest:
462 import os; print os.path.basename(sys.argv[0]), 'doctests ...',
463 sys.argv= [sys.argv[0]]
464 if options.verbose: sys.argv.append('-v')
465 import doctest
466 numfail,numtests=doctest.testmod()
467 if numfail==0: print 'ok'
468 else:
469 print 'FAILED'
470 success=False
471
472 if not success: sys.exit('Something Failed')
473 del success
474
475 if options.unittest:
476 sys.argv = [sys.argv[0]]
477 if options.verbose: sys.argv.append('-v')
478 unittest.main()
479
480 outfile = sys.stdout
481 if None!=options.outputFileName:
482 outfile = file(options.outputFileName,'w')
483
484
485 if options.doEncode:
486
487 if None==options.vesselField: parser.error("missing value for vesselField")
488 if None==options.directionField: parser.error("missing value for directionField")
489 if None==options.ETA_monthField: parser.error("missing value for ETA_monthField")
490 if None==options.ETA_dayField: parser.error("missing value for ETA_dayField")
491 if None==options.ETA_hourField: parser.error("missing value for ETA_hourField")
492 if None==options.ETA_minField: parser.error("missing value for ETA_minField")
493 msgDict={
494 'vessel': options.vesselField,
495 'direction': options.directionField,
496 'ETA_month': options.ETA_monthField,
497 'ETA_day': options.ETA_dayField,
498 'ETA_hour': options.ETA_hourField,
499 'ETA_min': options.ETA_minField,
500 'reserved': '0',
501 }
502
503 bits = encode(msgDict)
504 if 'binary'==options.ioType: print str(bits)
505 elif 'nmeapayload'==options.ioType:
506
507 print "bitLen",len(bits)
508 bitLen=len(bits)
509 if bitLen%6!=0:
510 bits = bits + BitVector(size=(6 - (bitLen%6)))
511 print "result:",binary.bitvectoais6(bits)[0]
512
513
514
515 elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability")
516 else: sys.exit('ERROR: unknown ioType. Help!')
517
518
519 if options.sqlCreate:
520 sqlCreateStr(outfile,options.fieldList)
521
522 if options.printCsvfieldList:
523
524 if None == options.fieldList: options.fieldList = fieldList
525 import StringIO
526 buf = StringIO.StringIO()
527 for field in options.fieldList:
528 buf.write(field+',')
529 result = buf.getvalue()
530 if result[-1] == ',': print result[:-1]
531 else: print result
532
533 if options.doDecode:
534 for msg in args:
535 bv = None
536 if 'binary' == options.ioType: bv = BitVector(bitstring=msg)
537 elif 'nmeapayload'== options.ioType: bv = binary.ais6tobitvec(msg)
538 elif 'nmea' == options.ioType: bv = binary.ais6tobitvec(msg.split(',')[5])
539 else: sys.exit('ERROR: unknown ioType. Help!')
540
541 printFields(decode(bv),out=outfile,format=options.outputType,fieldList=options.fieldList)
542