1   
  2   
  3  __version__ = '$Revision: 4791 $'.split()[1] 
  4  __date__ = '$Date: 2007-03-31 $'.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          'Spare', 
 54          'DestID1', 
 55          'SeqID1', 
 56          'DestID2', 
 57          'SeqID2', 
 58          'DestID3', 
 59          'SeqID3', 
 60          'DestID4', 
 61          'SeqID4', 
 62  ) 
 63   
 64  fieldListPostgres = ( 
 65          'MessageID', 
 66          'RepeatIndicator', 
 67          'UserID', 
 68          'Spare', 
 69          'DestID1', 
 70          'SeqID1', 
 71          'DestID2', 
 72          'SeqID2', 
 73          'DestID3', 
 74          'SeqID3', 
 75          'DestID4', 
 76          'SeqID4', 
 77  ) 
 78   
 79  toPgFields = { 
 80  } 
 81  ''' 
 82  Go to the Postgis field names from the straight field name 
 83  ''' 
 84   
 85  fromPgFields = { 
 86  } 
 87  ''' 
 88  Go from the Postgis field names to the straight field name 
 89  ''' 
 90   
 91  pgTypes = { 
 92  } 
 93  ''' 
 94  Lookup table for each postgis field name to get its type. 
 95  ''' 
 96   
 97 -def encode(params, validate=False): 
  98          '''Create a binack binary message payload to pack into an AIS Msg binack. 
 99   
100          Fields in params: 
101            - MessageID(uint): AIS message number.  Must be 7 (field automatically set to "7") 
102            - RepeatIndicator(uint): Indicated how many times a message has been repeated 
103            - UserID(uint): Unique ship identification number (MMSI).  Also known as the Source ID 
104            - Spare(uint): Not used.  Should be set to zero. (field automatically set to "0") 
105            - DestID1(uint): MMSI destication to ACK 
106            - SeqID1(uint): Sequence ID of the message to be acknowledged 
107            - DestID2(uint): MMSI destication to ACK 
108            - SeqID2(uint): Sequence ID of the message to be acknowledged 
109            - DestID3(uint): MMSI destication to ACK 
110            - SeqID3(uint): Sequence ID of the message to be acknowledged 
111            - DestID4(uint): MMSI destication to ACK 
112            - SeqID4(uint): Sequence ID of the message to be acknowledged 
113          @param params: Dictionary of field names/values.  Throws a ValueError exception if required is missing 
114          @param validate: Set to true to cause checking to occur.  Runs slower.  FIX: not implemented. 
115          @rtype: BitVector 
116          @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8 
117          @note: The returned bits may not be 6 bit aligned.  It is up to you to pad out the bits. 
118          ''' 
119   
120          bvList = [] 
121          bvList.append(binary.setBitVectorSize(BitVector(intVal=7),6)) 
122          if 'RepeatIndicator' in params: 
123                  bvList.append(binary.setBitVectorSize(BitVector(intVal=params['RepeatIndicator']),2)) 
124          else: 
125                  bvList.append(binary.setBitVectorSize(BitVector(intVal=0),2)) 
126          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['UserID']),30)) 
127          bvList.append(binary.setBitVectorSize(BitVector(intVal=0),1)) 
128          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['DestID1']),30)) 
129          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['SeqID1']),2)) 
130          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['DestID2']),30)) 
131          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['SeqID2']),2)) 
132          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['DestID3']),30)) 
133          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['SeqID3']),2)) 
134          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['DestID4']),30)) 
135          bvList.append(binary.setBitVectorSize(BitVector(intVal=params['SeqID4']),2)) 
136   
137          return binary.joinBV(bvList) 
 138   
139 -def decode(bv, validate=False): 
 140          '''Unpack a binack message  
141   
142          Fields in params: 
143            - MessageID(uint): AIS message number.  Must be 7 (field automatically set to "7") 
144            - RepeatIndicator(uint): Indicated how many times a message has been repeated 
145            - UserID(uint): Unique ship identification number (MMSI).  Also known as the Source ID 
146            - Spare(uint): Not used.  Should be set to zero. (field automatically set to "0") 
147            - DestID1(uint): MMSI destication to ACK 
148            - SeqID1(uint): Sequence ID of the message to be acknowledged 
149            - DestID2(uint): MMSI destication to ACK 
150            - SeqID2(uint): Sequence ID of the message to be acknowledged 
151            - DestID3(uint): MMSI destication to ACK 
152            - SeqID3(uint): Sequence ID of the message to be acknowledged 
153            - DestID4(uint): MMSI destication to ACK 
154            - SeqID4(uint): Sequence ID of the message to be acknowledged 
155          @type bv: BitVector 
156          @param bv: Bits defining a message 
157          @param validate: Set to true to cause checking to occur.  Runs slower.  FIX: not implemented. 
158          @rtype: dict 
159          @return: params 
160          ''' 
161   
162           
163           
164           
165          r = {} 
166          r['MessageID']=7 
167          r['RepeatIndicator']=int(bv[6:8]) 
168          r['UserID']=int(bv[8:38]) 
169          r['Spare']=0 
170          r['DestID1']=int(bv[39:69]) 
171          r['SeqID1']=int(bv[69:71]) 
172          r['DestID2']=int(bv[71:101]) 
173          r['SeqID2']=int(bv[101:103]) 
174          r['DestID3']=int(bv[103:133]) 
175          r['SeqID3']=int(bv[133:135]) 
176          r['DestID4']=int(bv[135:165]) 
177          r['SeqID4']=int(bv[165:167]) 
178          return r 
 179   
182   
185   
188   
191   
193          return int(bv[39:69]) 
 194   
196          return int(bv[69:71]) 
 197   
199          return int(bv[71:101]) 
 200   
202          return int(bv[101:103]) 
 203   
205          return int(bv[103:133]) 
 206   
208          return int(bv[133:135]) 
 209   
211          return int(bv[135:165]) 
 212   
214          return int(bv[165:167]) 
 215   
216   
218                  out.write("<h3>binack<h3>\n") 
219                  out.write("<table border=\"1\">\n") 
220                  out.write("<tr bgcolor=\"orange\">\n") 
221                  out.write("<th align=\"left\">Field Name</th>\n") 
222                  out.write("<th align=\"left\">Type</th>\n") 
223                  out.write("<th align=\"left\">Value</th>\n") 
224                  out.write("<th align=\"left\">Value in Lookup Table</th>\n") 
225                  out.write("<th align=\"left\">Units</th>\n") 
226                  out.write("\n") 
227                  out.write("<tr>\n") 
228                  out.write("<td>MessageID</td>\n") 
229                  out.write("<td>uint</td>\n") 
230                  if 'MessageID' in params: 
231                          out.write("     <td>"+str(params['MessageID'])+"</td>\n") 
232                          out.write("     <td>"+str(params['MessageID'])+"</td>\n") 
233                  out.write("</tr>\n") 
234                  out.write("\n") 
235                  out.write("<tr>\n") 
236                  out.write("<td>RepeatIndicator</td>\n") 
237                  out.write("<td>uint</td>\n") 
238                  if 'RepeatIndicator' in params: 
239                          out.write("     <td>"+str(params['RepeatIndicator'])+"</td>\n") 
240                          if str(params['RepeatIndicator']) in RepeatIndicatorDecodeLut: 
241                                  out.write("<td>"+RepeatIndicatorDecodeLut[str(params['RepeatIndicator'])]+"</td>") 
242                          else: 
243                                  out.write("<td><i>Missing LUT entry</i></td>") 
244                  out.write("</tr>\n") 
245                  out.write("\n") 
246                  out.write("<tr>\n") 
247                  out.write("<td>UserID</td>\n") 
248                  out.write("<td>uint</td>\n") 
249                  if 'UserID' in params: 
250                          out.write("     <td>"+str(params['UserID'])+"</td>\n") 
251                          out.write("     <td>"+str(params['UserID'])+"</td>\n") 
252                  out.write("</tr>\n") 
253                  out.write("\n") 
254                  out.write("<tr>\n") 
255                  out.write("<td>Spare</td>\n") 
256                  out.write("<td>uint</td>\n") 
257                  if 'Spare' in params: 
258                          out.write("     <td>"+str(params['Spare'])+"</td>\n") 
259                          out.write("     <td>"+str(params['Spare'])+"</td>\n") 
260                  out.write("</tr>\n") 
261                  out.write("\n") 
262                  out.write("<tr>\n") 
263                  out.write("<td>DestID1</td>\n") 
264                  out.write("<td>uint</td>\n") 
265                  if 'DestID1' in params: 
266                          out.write("     <td>"+str(params['DestID1'])+"</td>\n") 
267                          out.write("     <td>"+str(params['DestID1'])+"</td>\n") 
268                  out.write("</tr>\n") 
269                  out.write("\n") 
270                  out.write("<tr>\n") 
271                  out.write("<td>SeqID1</td>\n") 
272                  out.write("<td>uint</td>\n") 
273                  if 'SeqID1' in params: 
274                          out.write("     <td>"+str(params['SeqID1'])+"</td>\n") 
275                          out.write("     <td>"+str(params['SeqID1'])+"</td>\n") 
276                  out.write("</tr>\n") 
277                  out.write("\n") 
278                  out.write("<tr>\n") 
279                  out.write("<td>DestID2</td>\n") 
280                  out.write("<td>uint</td>\n") 
281                  if 'DestID2' in params: 
282                          out.write("     <td>"+str(params['DestID2'])+"</td>\n") 
283                          out.write("     <td>"+str(params['DestID2'])+"</td>\n") 
284                  out.write("</tr>\n") 
285                  out.write("\n") 
286                  out.write("<tr>\n") 
287                  out.write("<td>SeqID2</td>\n") 
288                  out.write("<td>uint</td>\n") 
289                  if 'SeqID2' in params: 
290                          out.write("     <td>"+str(params['SeqID2'])+"</td>\n") 
291                          out.write("     <td>"+str(params['SeqID2'])+"</td>\n") 
292                  out.write("</tr>\n") 
293                  out.write("\n") 
294                  out.write("<tr>\n") 
295                  out.write("<td>DestID3</td>\n") 
296                  out.write("<td>uint</td>\n") 
297                  if 'DestID3' in params: 
298                          out.write("     <td>"+str(params['DestID3'])+"</td>\n") 
299                          out.write("     <td>"+str(params['DestID3'])+"</td>\n") 
300                  out.write("</tr>\n") 
301                  out.write("\n") 
302                  out.write("<tr>\n") 
303                  out.write("<td>SeqID3</td>\n") 
304                  out.write("<td>uint</td>\n") 
305                  if 'SeqID3' in params: 
306                          out.write("     <td>"+str(params['SeqID3'])+"</td>\n") 
307                          out.write("     <td>"+str(params['SeqID3'])+"</td>\n") 
308                  out.write("</tr>\n") 
309                  out.write("\n") 
310                  out.write("<tr>\n") 
311                  out.write("<td>DestID4</td>\n") 
312                  out.write("<td>uint</td>\n") 
313                  if 'DestID4' in params: 
314                          out.write("     <td>"+str(params['DestID4'])+"</td>\n") 
315                          out.write("     <td>"+str(params['DestID4'])+"</td>\n") 
316                  out.write("</tr>\n") 
317                  out.write("\n") 
318                  out.write("<tr>\n") 
319                  out.write("<td>SeqID4</td>\n") 
320                  out.write("<td>uint</td>\n") 
321                  if 'SeqID4' in params: 
322                          out.write("     <td>"+str(params['SeqID4'])+"</td>\n") 
323                          out.write("     <td>"+str(params['SeqID4'])+"</td>\n") 
324                  out.write("</tr>\n") 
325                  out.write("</table>\n") 
 326   
327 -def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'): 
 328          '''Print a binack message to stdout. 
329   
330          Fields in params: 
331            - MessageID(uint): AIS message number.  Must be 7 (field automatically set to "7") 
332            - RepeatIndicator(uint): Indicated how many times a message has been repeated 
333            - UserID(uint): Unique ship identification number (MMSI).  Also known as the Source ID 
334            - Spare(uint): Not used.  Should be set to zero. (field automatically set to "0") 
335            - DestID1(uint): MMSI destication to ACK 
336            - SeqID1(uint): Sequence ID of the message to be acknowledged 
337            - DestID2(uint): MMSI destication to ACK 
338            - SeqID2(uint): Sequence ID of the message to be acknowledged 
339            - DestID3(uint): MMSI destication to ACK 
340            - SeqID3(uint): Sequence ID of the message to be acknowledged 
341            - DestID4(uint): MMSI destication to ACK 
342            - SeqID4(uint): Sequence ID of the message to be acknowledged 
343          @param params: Dictionary of field names/values.   
344          @param out: File like object to write to 
345          @rtype: stdout 
346          @return: text to out 
347          ''' 
348   
349          if 'std'==format: 
350                  out.write("binack:\n") 
351                  if 'MessageID' in params: out.write("   MessageID:        "+str(params['MessageID'])+"\n") 
352                  if 'RepeatIndicator' in params: out.write("     RepeatIndicator:  "+str(params['RepeatIndicator'])+"\n") 
353                  if 'UserID' in params: out.write("      UserID:           "+str(params['UserID'])+"\n") 
354                  if 'Spare' in params: out.write("       Spare:            "+str(params['Spare'])+"\n") 
355                  if 'DestID1' in params: out.write("     DestID1:          "+str(params['DestID1'])+"\n") 
356                  if 'SeqID1' in params: out.write("      SeqID1:           "+str(params['SeqID1'])+"\n") 
357                  if 'DestID2' in params: out.write("     DestID2:          "+str(params['DestID2'])+"\n") 
358                  if 'SeqID2' in params: out.write("      SeqID2:           "+str(params['SeqID2'])+"\n") 
359                  if 'DestID3' in params: out.write("     DestID3:          "+str(params['DestID3'])+"\n") 
360                  if 'SeqID3' in params: out.write("      SeqID3:           "+str(params['SeqID3'])+"\n") 
361                  if 'DestID4' in params: out.write("     DestID4:          "+str(params['DestID4'])+"\n") 
362                  if 'SeqID4' in params: out.write("      SeqID4:           "+str(params['SeqID4'])+"\n") 
363          elif 'csv'==format: 
364                  if None == options.fieldList: 
365                          options.fieldList = fieldList 
366                  needComma = False; 
367                  for field in fieldList: 
368                          if needComma: out.write(',') 
369                          needComma = True 
370                          if field in params: 
371                                  out.write(str(params[field])) 
372                           
373                  out.write("\n") 
374          elif 'html'==format: 
375                  printHtml(params,out) 
376          elif 'sql'==format: 
377                  sqlInsertStr(params,out,dbType=dbType) 
378          else:  
379                  print "ERROR: unknown format:",format 
380                  assert False 
381   
382          return  
 383   
384  RepeatIndicatorEncodeLut = { 
385          'default':'0', 
386          'do not repeat any more':'3', 
387          }  
388   
389  RepeatIndicatorDecodeLut = { 
390          '0':'default', 
391          '3':'do not repeat any more', 
392          }  
393   
394   
395   
396   
397   
398 -def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None 
399                  ,addCoastGuardFields=True 
400                  ,dbType='postgres' 
401                  ): 
 402          ''' 
403          Return the SQL CREATE command for this message type 
404          @param outfile: file like object to print to. 
405          @param fields: which fields to put in the create.  Defaults to all. 
406          @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 
407          @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 
408          @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 
409          @type addCoastGuardFields: bool 
410          @return: sql create string 
411          @rtype: str 
412   
413          @see: sqlCreate 
414          ''' 
415           
416          outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType))) 
 417   
418 -def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'): 
 419          ''' 
420          Return the sqlhelp object to create the table. 
421   
422          @param fields: which fields to put in the create.  Defaults to all. 
423          @param extraFields: A sequence of tuples containing (name,sql type) for additional fields 
424          @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format 
425          @type addCoastGuardFields: bool 
426          @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres') 
427          @return: An object that can be used to generate a return 
428          @rtype: sqlhelp.create 
429          ''' 
430          if None == fields: fields = fieldList 
431          import sqlhelp 
432          c = sqlhelp.create('binack',dbType=dbType) 
433          c.addPrimaryKey() 
434          if 'MessageID' in fields: c.addInt ('MessageID') 
435          if 'RepeatIndicator' in fields: c.addInt ('RepeatIndicator') 
436          if 'UserID' in fields: c.addInt ('UserID') 
437          if 'Spare' in fields: c.addInt ('Spare') 
438          if 'DestID1' in fields: c.addInt ('DestID1') 
439          if 'SeqID1' in fields: c.addInt ('SeqID1') 
440          if 'DestID2' in fields: c.addInt ('DestID2') 
441          if 'SeqID2' in fields: c.addInt ('SeqID2') 
442          if 'DestID3' in fields: c.addInt ('DestID3') 
443          if 'SeqID3' in fields: c.addInt ('SeqID3') 
444          if 'DestID4' in fields: c.addInt ('DestID4') 
445          if 'SeqID4' in fields: c.addInt ('SeqID4') 
446   
447          if addCoastGuardFields: 
448                   
449                   
450                   
451                   
452                   
453                  c.addVarChar('cg_r',15)    
454                  c.addInt('cg_sec')         
455   
456                  c.addTimestamp('cg_timestamp')  
457   
458          return c 
 459   
460 -def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'): 
 461          ''' 
462          Return the SQL INSERT command for this message type 
463          @param params: dictionary of values keyed by field name 
464          @param outfile: file like object to print to. 
465          @param extraParams: A sequence of tuples containing (name,sql type) for additional fields 
466          @return: sql create string 
467          @rtype: str 
468   
469          @see: sqlCreate 
470          ''' 
471          outfile.write(str(sqlInsert(params,extraParams,dbType=dbType))) 
 472   
473   
474 -def sqlInsert(params,extraParams=None,dbType='postgres'): 
 475          ''' 
476          Give the SQL INSERT statement 
477          @param params: dict keyed by field name of values 
478          @param extraParams: any extra fields that you have created beyond the normal ais message fields 
479          @rtype: sqlhelp.insert 
480          @return: insert class instance 
481          @todo: allow optional type checking of params? 
482          @warning: this will take invalid keys happily and do what??? 
483          ''' 
484          import sqlhelp 
485          i = sqlhelp.insert('binack',dbType=dbType) 
486   
487          if dbType=='postgres': 
488                  finished = [] 
489                  for key in params: 
490                          if key in finished:  
491                                  continue 
492   
493                          if key not in toPgFields and key not in fromPgFields: 
494                                  if type(params[key])==Decimal: i.add(key,float(params[key])) 
495                                  else: i.add(key,params[key]) 
496                          else: 
497                                  if key in fromPgFields: 
498                                          val = params[key] 
499                                           
500                                          i.addPostGIS(key,val) 
501                                          finished.append(key) 
502                                  else: 
503                                           
504                                          pgName = toPgFields[key] 
505                                           
506                                          valStr=pgTypes[pgName]+'(' 
507                                          vals = [] 
508                                          for nonPgKey in fromPgFields[pgName]: 
509                                                  vals.append(str(params[nonPgKey])) 
510                                                  finished.append(nonPgKey) 
511                                          valStr+=' '.join(vals)+')' 
512                                          i.addPostGIS(pgName,valStr) 
513          else: 
514                  for key in params:  
515                          if type(params[key])==Decimal: i.add(key,float(params[key])) 
516                          else: i.add(key,params[key]) 
517   
518          if None != extraParams: 
519                  for key in extraParams:  
520                          i.add(key,extraParams[key]) 
521   
522          return i 
 523   
524   
525   
526   
527   
530          ''' 
531          Return the LaTeX definition table for this message type 
532          @param outfile: file like object to print to. 
533          @type outfile: file obj 
534          @return: LaTeX table string via the outfile 
535          @rtype: str 
536   
537          ''' 
538          o = outfile 
539   
540          o.write(''' 
541  \\begin{table}%[htb] 
542  \\centering 
543  \\begin{tabular}{|l|c|l|} 
544  \\hline 
545  Parameter & Number of bits & Description  
546  \\\\  \\hline\\hline 
547  MessageID & 6 & AIS message number.  Must be 7 \\\\ \hline  
548  RepeatIndicator & 2 & Indicated how many times a message has been repeated \\\\ \hline  
549  UserID & 30 & Unique ship identification number (MMSI).  Also known as the Source ID \\\\ \hline  
550  Spare & 1 & Not used.  Should be set to zero. \\\\ \hline  
551  DestID1 & 30 & MMSI destication to ACK \\\\ \hline  
552  SeqID1 & 2 & Sequence ID of the message to be acknowledged \\\\ \hline  
553  DestID2 & 30 & MMSI destication to ACK \\\\ \hline  
554  SeqID2 & 2 & Sequence ID of the message to be acknowledged \\\\ \hline  
555  DestID3 & 30 & MMSI destication to ACK \\\\ \hline  
556  SeqID3 & 2 & Sequence ID of the message to be acknowledged \\\\ \hline  
557  DestID4 & 30 & MMSI destication to ACK \\\\ \hline  
558  SeqID4 & 2 & Sequence ID of the message to be acknowledged\\\\ \\hline \\hline 
559  Total bits & 167 & Appears to take 1 slot with 1 pad bits to fill the last slot \\\\ \\hline 
560  \\end{tabular} 
561  \\caption{AIS message number 8: Binary acknowledgement of addressed message} 
562  \\label{tab:binack} 
563  \\end{table} 
564  ''') 
 565   
566   
567   
568   
569   
570  import unittest 
572          '''Return a params file base on the testvalue tags. 
573          @rtype: dict 
574          @return: params based on testvalue tags 
575          ''' 
576          params = {} 
577          params['MessageID'] = 7 
578          params['RepeatIndicator'] = 1 
579          params['UserID'] = 1193046 
580          params['Spare'] = 0 
581          params['DestID1'] = 1193001 
582          params['SeqID1'] = 1 
583          params['DestID2'] = 1193002 
584          params['SeqID2'] = 2 
585          params['DestID3'] = 1193003 
586          params['SeqID3'] = 3 
587          params['DestID4'] = 1193004 
588          params['SeqID4'] = 0 
589   
590          return params 
 591   
593          '''Use testvalue tag text from each type to build test case the binack message''' 
595   
596                  params = testParams() 
597                  bits   = encode(params) 
598                  r      = decode(bits) 
599   
600                   
601                  self.failUnlessEqual(r['MessageID'],params['MessageID']) 
602                  self.failUnlessEqual(r['RepeatIndicator'],params['RepeatIndicator']) 
603                  self.failUnlessEqual(r['UserID'],params['UserID']) 
604                  self.failUnlessEqual(r['Spare'],params['Spare']) 
605                  self.failUnlessEqual(r['DestID1'],params['DestID1']) 
606                  self.failUnlessEqual(r['SeqID1'],params['SeqID1']) 
607                  self.failUnlessEqual(r['DestID2'],params['DestID2']) 
608                  self.failUnlessEqual(r['SeqID2'],params['SeqID2']) 
609                  self.failUnlessEqual(r['DestID3'],params['DestID3']) 
610                  self.failUnlessEqual(r['SeqID3'],params['SeqID3']) 
611                  self.failUnlessEqual(r['DestID4'],params['DestID4']) 
612                  self.failUnlessEqual(r['SeqID4'],params['SeqID4']) 
  613   
615          parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true', 
616                  help='decode a "binack" AIS message') 
617          parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true', 
618                  help='encode a "binack" AIS message') 
619          parser.add_option('--RepeatIndicator-field', dest='RepeatIndicatorField',default=0,metavar='uint',type='int' 
620                  ,help='Field parameter value [default: %default]') 
621          parser.add_option('--UserID-field', dest='UserIDField',metavar='uint',type='int' 
622                  ,help='Field parameter value [default: %default]') 
623          parser.add_option('--DestID1-field', dest='DestID1Field',metavar='uint',type='int' 
624                  ,help='Field parameter value [default: %default]') 
625          parser.add_option('--SeqID1-field', dest='SeqID1Field',metavar='uint',type='int' 
626                  ,help='Field parameter value [default: %default]') 
627          parser.add_option('--DestID2-field', dest='DestID2Field',metavar='uint',type='int' 
628                  ,help='Field parameter value [default: %default]') 
629          parser.add_option('--SeqID2-field', dest='SeqID2Field',metavar='uint',type='int' 
630                  ,help='Field parameter value [default: %default]') 
631          parser.add_option('--DestID3-field', dest='DestID3Field',metavar='uint',type='int' 
632                  ,help='Field parameter value [default: %default]') 
633          parser.add_option('--SeqID3-field', dest='SeqID3Field',metavar='uint',type='int' 
634                  ,help='Field parameter value [default: %default]') 
635          parser.add_option('--DestID4-field', dest='DestID4Field',metavar='uint',type='int' 
636                  ,help='Field parameter value [default: %default]') 
637          parser.add_option('--SeqID4-field', dest='SeqID4Field',metavar='uint',type='int' 
638                  ,help='Field parameter value [default: %default]') 
 639   
640   
641  if __name__=='__main__': 
642   
643          from optparse import OptionParser 
644          parser = OptionParser(usage="%prog [options]", 
645                  version="%prog "+__version__) 
646   
647          parser.add_option('--doc-test',dest='doctest',default=False,action='store_true', 
648                  help='run the documentation tests') 
649          parser.add_option('--unit-test',dest='unittest',default=False,action='store_true', 
650                  help='run the unit tests') 
651          parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true', 
652                  help='Make the test output verbose') 
653   
654           
655           
656          typeChoices = ('binary','nmeapayload','nmea')  
657          parser.add_option('-t','--type',choices=typeChoices,type='choice',dest='ioType' 
658                  ,default='nmeapayload' 
659                  ,help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]') 
660   
661   
662          outputChoices = ('std','html','csv','sql' ) 
663          parser.add_option('-T','--output-type',choices=outputChoices,type='choice',dest='outputType' 
664                  ,default='std' 
665                  ,help='What kind of string to output ('+', '.join(outputChoices)+') [default: %default]') 
666   
667          parser.add_option('-o','--output',dest='outputFileName',default=None, 
668                            help='Name of the python file to write [default: stdout]') 
669   
670          parser.add_option('-f','--fields',dest='fieldList',default=None, action='append', 
671                            choices=fieldList, 
672                            help='Which fields to include in the output.  Currently only for csv output [default: all]') 
673   
674          parser.add_option('-p','--print-csv-field-list',dest='printCsvfieldList',default=False,action='store_true', 
675                            help='Print the field name for csv') 
676   
677          parser.add_option('-c','--sql-create',dest='sqlCreate',default=False,action='store_true', 
678                            help='Print out an sql create command for the table.') 
679   
680          parser.add_option('--latex-table',dest='latexDefinitionTable',default=False,action='store_true', 
681                            help='Print a LaTeX table of the type') 
682   
683          dbChoices = ('sqlite','postgres') 
684          parser.add_option('-D','--db-type',dest='dbType',default='postgres' 
685                            ,choices=dbChoices,type='choice' 
686                            ,help='What kind of database ('+', '.join(dbChoices)+') [default: %default]') 
687   
688          addMsgOptions(parser) 
689   
690          (options,args) = parser.parse_args() 
691          success=True 
692   
693          if options.doctest: 
694                  import os; print os.path.basename(sys.argv[0]), 'doctests ...', 
695                  sys.argv= [sys.argv[0]] 
696                  if options.verbose: sys.argv.append('-v') 
697                  import doctest 
698                  numfail,numtests=doctest.testmod() 
699                  if numfail==0: print 'ok' 
700                  else:  
701                          print 'FAILED' 
702                          success=False 
703   
704          if not success: sys.exit('Something Failed') 
705          del success  
706   
707          if options.unittest: 
708                  sys.argv = [sys.argv[0]] 
709                  if options.verbose: sys.argv.append('-v') 
710                  unittest.main() 
711   
712          outfile = sys.stdout 
713          if None!=options.outputFileName: 
714                  outfile = file(options.outputFileName,'w') 
715   
716   
717          if options.doEncode: 
718                   
719                  if None==options.RepeatIndicatorField: parser.error("missing value for RepeatIndicatorField") 
720                  if None==options.UserIDField: parser.error("missing value for UserIDField") 
721                  if None==options.DestID1Field: parser.error("missing value for DestID1Field") 
722                  if None==options.SeqID1Field: parser.error("missing value for SeqID1Field") 
723                  if None==options.DestID2Field: parser.error("missing value for DestID2Field") 
724                  if None==options.SeqID2Field: parser.error("missing value for SeqID2Field") 
725                  if None==options.DestID3Field: parser.error("missing value for DestID3Field") 
726                  if None==options.SeqID3Field: parser.error("missing value for SeqID3Field") 
727                  if None==options.DestID4Field: parser.error("missing value for DestID4Field") 
728                  if None==options.SeqID4Field: parser.error("missing value for SeqID4Field") 
729                  msgDict={ 
730                          'MessageID': '7', 
731                          'RepeatIndicator': options.RepeatIndicatorField, 
732                          'UserID': options.UserIDField, 
733                          'Spare': '0', 
734                          'DestID1': options.DestID1Field, 
735                          'SeqID1': options.SeqID1Field, 
736                          'DestID2': options.DestID2Field, 
737                          'SeqID2': options.SeqID2Field, 
738                          'DestID3': options.DestID3Field, 
739                          'SeqID3': options.SeqID3Field, 
740                          'DestID4': options.DestID4Field, 
741                          'SeqID4': options.SeqID4Field, 
742                  } 
743   
744                  bits = encode(msgDict) 
745                  if 'binary'==options.ioType: print str(bits) 
746                  elif 'nmeapayload'==options.ioType: 
747                           
748                          print "bitLen",len(bits) 
749                          bitLen=len(bits) 
750                          if bitLen%6!=0: 
751                              bits = bits + BitVector(size=(6 - (bitLen%6)))   
752                          print "result:",binary.bitvectoais6(bits)[0] 
753   
754   
755                   
756                  elif 'nmea'==options.ioType: sys.exit("FIX: need to implement this capability") 
757                  else: sys.exit('ERROR: unknown ioType.  Help!') 
758   
759   
760          if options.sqlCreate: 
761                  sqlCreateStr(outfile,options.fieldList,dbType=options.dbType) 
762   
763          if options.latexDefinitionTable: 
764                  latexDefinitionTable(outfile) 
765   
766          if options.printCsvfieldList: 
767                   
768                  if None == options.fieldList: options.fieldList = fieldList 
769                  import StringIO 
770                  buf = StringIO.StringIO() 
771                  for field in options.fieldList: 
772                          buf.write(field+',') 
773                  result = buf.getvalue() 
774                  if result[-1] == ',': print result[:-1] 
775                  else: print result 
776   
777          if options.doDecode: 
778                  for msg in args: 
779                          bv = None 
780   
781                          if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'): 
782                                   
783                                   
784                                  bv = binary.ais6tobitvec(msg.split(',')[5]) 
785                          else:  
786                                   
787                                  binaryMsg=True 
788                                  for c in msg: 
789                                          if c not in ('0','1'): 
790                                                  binaryMsg=False 
791                                                  break 
792                                  if binaryMsg: 
793                                          bv = BitVector(bitstring=msg) 
794                                  else:  
795                                          bv = binary.ais6tobitvec(msg) 
796   
797                          printFields(decode(bv) 
798                                      ,out=outfile 
799                                      ,format=options.outputType 
800                                      ,fieldList=options.fieldList 
801                                      ,dbType=options.dbType 
802                                      ) 
803