text: #!/usr/bin/env python
  
  """Autogenerated python functions to serialize/deserialize binary messages.
  
  Generated by: ../../scripts/aisxmlbinmsg2py.py
  
  Need to then wrap these functions with the outer AIS packet and then
  convert the whole binary blob to a NMEA string.  Those functions are
  not currently provided in this file.
  
  serialize: python to ais binary
  deserialize: ais binary to python
  
  The generated code uses translators.py, binary.py, and aisstring.py
  which should be packaged with the resulting files.
  
  
   TODO(schwehr):FIX: put in a description of the message here with fields and types.
  """
  import doctest
  import sys
  from decimal import Decimal
  import unittest
  
  from aisutils.BitVector import BitVector
  
  from aisutils import aisstring
  from aisutils import binary
  from aisutils import sqlhelp
  from aisutils import uscg
  
  # FIX: check to see if these will be needed
  TrueBV  = BitVector(bitstring="1")
  "Why always rebuild the True bit?  This should speed things up a bunch"
  FalseBV = BitVector(bitstring="0")
  "Why always rebuild the False bit?  This should speed things up a bunch"
  
  
  fieldList = (
      'time_month',
      'time_day',
      'time_hour',
      'time_min',
      'lockid',
      'pos_longitude',
      'pos_latitude',
      'reserved',
      'lockschedules',
  )
  
  fieldListPostgres = (
      'time_month',
      'time_day',
      'time_hour',
      'time_min',
      'lockid',
      'pos',    # PostGIS data type
      'reserved',
      'lockschedules',
  )
  
  toPgFields = {
      'pos_longitude':'pos',
      'pos_latitude':'pos',
  }
  """
  Go to the Postgis field names from the straight field name
  """
  
  fromPgFields = {
      'pos':('pos_longitude','pos_latitude',),
  }
  """
  Go from the Postgis field names to the straight field name
  """
  
  pgTypes = {
      'pos':'POINT',
  }
  """
  Lookup table for each postgis field name to get its type.
  """
  
  def encode(params, validate=False):
      '''Create a sls_lockorder binary message payload to pack into an AIS Msg sls_lockorder.
  
      Fields in params:
        - time_month(uint): Time tag of measurement  month 1..12
        - time_day(uint): Time tag of measurement  day of the month 1..31
        - time_hour(uint): Time tag of measurement  UTC hours 0..23
        - time_min(uint): Time tag of measurement  minutes
        - lockid(aisstr6): Character identifier of the station
        - pos_longitude(decimal): Location of measurement  East West location
        - pos_latitude(decimal): Location of measurement  North South location
        - reserved(uint): Reserved bits for future use (field automatically set to "0")
        - lockschedules(binary): up to 6 lock schedule reports
      @param params: Dictionary of field names/values.  Throws a ValueError exception if required is missing
      @param validate: Set to true to cause checking to occur.  Runs slower.  FIX: not implemented.
      @rtype: BitVector
      @return: encoded binary message (for binary messages, this needs to be wrapped in a msg 8
      @note: The returned bits may not be 6 bit aligned.  It is up to you to pad out the bits.
      '''
  
      bvList = []
      bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_month']),4))
      bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_day']),5))
      bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_hour']),5))
      bvList.append(binary.setBitVectorSize(BitVector(intVal=params['time_min']),6))
      if 'lockid' in params:
          bvList.append(aisstring.encode(params['lockid'],42))
      else:
          bvList.append(aisstring.encode('@@@@@@@',42))
      if 'pos_longitude' in params:
          bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_longitude'])*Decimal('60000')),25))
      else:
          bvList.append(binary.bvFromSignedInt(10860000,25))
      if 'pos_latitude' in params:
          bvList.append(binary.bvFromSignedInt(int(Decimal(params['pos_latitude'])*Decimal('60000')),24))
      else:
          bvList.append(binary.bvFromSignedInt(5460000,24))
      bvList.append(binary.setBitVectorSize(BitVector(intVal=0),19))
      bvList.append(params['lockschedules'])
  
      return binary.joinBV(bvList)
  
  def decode(bv, validate=False):
      '''Unpack a sls_lockorder message.
  
      Fields in params:
        - time_month(uint): Time tag of measurement  month 1..12
        - time_day(uint): Time tag of measurement  day of the month 1..31
        - time_hour(uint): Time tag of measurement  UTC hours 0..23
        - time_min(uint): Time tag of measurement  minutes
        - lockid(aisstr6): Character identifier of the station
        - pos_longitude(decimal): Location of measurement  East West location
        - pos_latitude(decimal): Location of measurement  North South location
        - reserved(uint): Reserved bits for future use (field automatically set to "0")
        - lockschedules(binary): up to 6 lock schedule reports
      @type bv: BitVector
      @param bv: Bits defining a message
      @param validate: Set to true to cause checking to occur.  Runs slower.  FIX: not implemented.
      @rtype: dict
      @return: params
      '''
  
      #Would be nice to check the bit count here..
      #if validate:
      #    assert (len(bv)==FIX: SOME NUMBER)
      r = {}
      r['time_month']=int(bv[0:4])
      r['time_day']=int(bv[4:9])
      r['time_hour']=int(bv[9:14])
      r['time_min']=int(bv[14:20])
      r['lockid']=aisstring.decode(bv[20:62])
      r['pos_longitude']=Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
      r['pos_latitude']=Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
      r['reserved']=0
      r['lockschedules']=bv[130:]
      return r
  
  def decodetime_month(bv, validate=False):
      return int(bv[0:4])
  
  def decodetime_day(bv, validate=False):
      return int(bv[4:9])
  
  def decodetime_hour(bv, validate=False):
      return int(bv[9:14])
  
  def decodetime_min(bv, validate=False):
      return int(bv[14:20])
  
  def decodelockid(bv, validate=False):
      return aisstring.decode(bv[20:62])
  
  def decodepos_longitude(bv, validate=False):
      return Decimal(binary.signedIntFromBV(bv[62:87]))/Decimal('60000')
  
  def decodepos_latitude(bv, validate=False):
      return Decimal(binary.signedIntFromBV(bv[87:111]))/Decimal('60000')
  
  def decodereserved(bv, validate=False):
      return 0
  
  def decodelockschedules(bv, validate=False):
      return bv[130:]
  
  
  def printHtml(params, out=sys.stdout):
          out.write("<h3>sls_lockorder</h3>\n")
          out.write("<table border=\"1\">\n")
          out.write("<tr bgcolor=\"orange\">\n")
          out.write("<th align=\"left\">Field Name</th>\n")
          out.write("<th align=\"left\">Type</th>\n")
          out.write("<th align=\"left\">Value</th>\n")
          out.write("<th align=\"left\">Value in Lookup Table</th>\n")
          out.write("<th align=\"left\">Units</th>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>time_month</td>\n")
          out.write("<td>uint</td>\n")
          if 'time_month' in params:
              out.write("    <td>"+str(params['time_month'])+"</td>\n")
              out.write("    <td>"+str(params['time_month'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>time_day</td>\n")
          out.write("<td>uint</td>\n")
          if 'time_day' in params:
              out.write("    <td>"+str(params['time_day'])+"</td>\n")
              out.write("    <td>"+str(params['time_day'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>time_hour</td>\n")
          out.write("<td>uint</td>\n")
          if 'time_hour' in params:
              out.write("    <td>"+str(params['time_hour'])+"</td>\n")
              out.write("    <td>"+str(params['time_hour'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>time_min</td>\n")
          out.write("<td>uint</td>\n")
          if 'time_min' in params:
              out.write("    <td>"+str(params['time_min'])+"</td>\n")
              out.write("    <td>"+str(params['time_min'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>lockid</td>\n")
          out.write("<td>aisstr6</td>\n")
          if 'lockid' in params:
              out.write("    <td>"+str(params['lockid'])+"</td>\n")
              out.write("    <td>"+str(params['lockid'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>pos_longitude</td>\n")
          out.write("<td>decimal</td>\n")
          if 'pos_longitude' in params:
              out.write("    <td>"+str(params['pos_longitude'])+"</td>\n")
              out.write("    <td>"+str(params['pos_longitude'])+"</td>\n")
          out.write("<td>degrees</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>pos_latitude</td>\n")
          out.write("<td>decimal</td>\n")
          if 'pos_latitude' in params:
              out.write("    <td>"+str(params['pos_latitude'])+"</td>\n")
              out.write("    <td>"+str(params['pos_latitude'])+"</td>\n")
          out.write("<td>degrees</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>reserved</td>\n")
          out.write("<td>uint</td>\n")
          if 'reserved' in params:
              out.write("    <td>"+str(params['reserved'])+"</td>\n")
              out.write("    <td>"+str(params['reserved'])+"</td>\n")
          out.write("</tr>\n")
          out.write("\n")
          out.write("<tr>\n")
          out.write("<td>lockschedules</td>\n")
          out.write("<td>binary</td>\n")
          if 'lockschedules' in params:
              out.write("    <td>"+str(params['lockschedules'])+"</td>\n")
              out.write("    <td>"+str(params['lockschedules'])+"</td>\n")
          out.write("</tr>\n")
          out.write("</table>\n")
  
  
  def printKml(params, out=sys.stdout):
      """KML (Keyhole Markup Language) for Google Earth, but without the header/footer"""
      out.write("    <Placemark>\n")
      out.write("        <name>"+str(params['lockid'])+"</name>\n")
      out.write("        <description>\n")
      import StringIO
      buf = StringIO.StringIO()
      printHtml(params,buf)
      import cgi
      out.write(cgi.escape(buf.getvalue()))
      out.write("        </description>\n")
      out.write("        <styleUrl>#m_ylw-pushpin_copy0</styleUrl>\n")
      out.write("        <Point>\n")
      out.write("            <coordinates>")
      out.write(str(params['pos_longitude']))
      out.write(',')
      out.write(str(params['pos_latitude']))
      out.write(",0</coordinates>\n")
      out.write("        </Point>\n")
      out.write("    </Placemark>\n")
  
  def printFields(params, out=sys.stdout, format='std', fieldList=None, dbType='postgres'):
      '''Print a sls_lockorder message to stdout.
  
      Fields in params:
        - time_month(uint): Time tag of measurement  month 1..12
        - time_day(uint): Time tag of measurement  day of the month 1..31
        - time_hour(uint): Time tag of measurement  UTC hours 0..23
        - time_min(uint): Time tag of measurement  minutes
        - lockid(aisstr6): Character identifier of the station
        - pos_longitude(decimal): Location of measurement  East West location
        - pos_latitude(decimal): Location of measurement  North South location
        - reserved(uint): Reserved bits for future use (field automatically set to "0")
        - lockschedules(binary): up to 6 lock schedule reports
      @param params: Dictionary of field names/values.
      @param out: File like object to write to.
      @rtype: stdout
      @return: text to out
      '''
  
      if 'std'==format:
          out.write("sls_lockorder:\n")
          if 'time_month' in params: out.write("    time_month:     "+str(params['time_month'])+"\n")
          if 'time_day' in params: out.write("    time_day:       "+str(params['time_day'])+"\n")
          if 'time_hour' in params: out.write("    time_hour:      "+str(params['time_hour'])+"\n")
          if 'time_min' in params: out.write("    time_min:       "+str(params['time_min'])+"\n")
          if 'lockid' in params: out.write("    lockid:         "+str(params['lockid'])+"\n")
          if 'pos_longitude' in params: out.write("    pos_longitude:  "+str(params['pos_longitude'])+"\n")
          if 'pos_latitude' in params: out.write("    pos_latitude:   "+str(params['pos_latitude'])+"\n")
          if 'reserved' in params: out.write("    reserved:       "+str(params['reserved'])+"\n")
          if 'lockschedules' in params: out.write("    lockschedules:  "+str(params['lockschedules'])+"\n")
          elif 'csv'==format:
                  if None == options.fieldList:
                          options.fieldList = fieldList
                  needComma = False;
                  for field in fieldList:
                          if needComma: out.write(',')
                          needComma = True
                          if field in params:
                                  out.write(str(params[field]))
                          # else: leave it empty
                  out.write("\n")
      elif 'html'==format:
          printHtml(params,out)
      elif 'sql'==format:
                  sqlInsertStr(params,out,dbType=dbType)
      elif 'kml'==format:
          printKml(params,out)
      elif 'kml-full'==format:
          out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
          out.write("<kml xmlns=\"http://earth.google.com/kml/2.1\">\n")
          out.write("<Document>\n")
          out.write("    <name>sls_lockorder</name>\n")
          printKml(params,out)
          out.write("</Document>\n")
          out.write("</kml>\n")
      else:
          print "ERROR: unknown format:",format
          assert False
  
      return # Nothing to return
  
  ######################################################################
  # SQL SUPPORT
  ######################################################################
  
  dbTableName='sls_lockorder'
  'Database table name'
  
  def sqlCreateStr(outfile=sys.stdout, fields=None, extraFields=None
                  ,addCoastGuardFields=True
                  ,dbType='postgres'
                  ):
          """
          Return the SQL CREATE command for this message type
          @param outfile: file like object to print to.
          @param fields: which fields to put in the create.  Defaults to all.
          @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
          @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
          @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
          @type addCoastGuardFields: bool
          @return: sql create string
          @rtype: str
  
          @see: sqlCreate
          """
          # FIX: should this sqlCreate be the same as in LaTeX (createFuncName) rather than hard coded?
          outfile.write(str(sqlCreate(fields,extraFields,addCoastGuardFields,dbType=dbType)))
  
  def sqlCreate(fields=None, extraFields=None, addCoastGuardFields=True, dbType='postgres'):
      """Return the sqlhelp object to create the table.
  
      @param fields: which fields to put in the create.  Defaults to all.
      @param extraFields: A sequence of tuples containing (name,sql type) for additional fields
      @param addCoastGuardFields: Add the extra fields that come after the NMEA check some from the USCG N-AIS format
      @type addCoastGuardFields: bool
      @param dbType: Which flavor of database we are using so that the create is tailored ('sqlite' or 'postgres')
      @return: An object that can be used to generate a return
      @rtype: sqlhelp.create
      """
      if fields is None:
          fields = fieldList
      c = sqlhelp.create('sls_lockorder',dbType=dbType)
      c.addPrimaryKey()
      if 'time_month' in fields: c.addInt ('time_month')
      if 'time_day' in fields: c.addInt ('time_day')
      if 'time_hour' in fields: c.addInt ('time_hour')
      if 'time_min' in fields: c.addInt ('time_min')
      if 'lockid' in fields: c.addVarChar('lockid',7)
      if dbType != 'postgres':
          if 'pos_longitude' in fields: c.addDecimal('pos_longitude',7,4)
      if dbType != 'postgres':
          if 'pos_latitude' in fields: c.addDecimal('pos_latitude',7,4)
      if 'reserved' in fields: c.addInt ('reserved')
      if 'lockschedules' in fields: c.addBitVarying('lockschedules',1024)
  
      if addCoastGuardFields:
          # c.addInt('cg_s_rssi')  # Relative signal strength indicator
          # c.addInt('cg_d_strength')  # dBm receive strength
          # c.addVarChar('cg_x',10)  # Idonno
          c.addInt('cg_t_arrival')  # Receive timestamp from the AIS equipment 'T'
          c.addInt('cg_s_slotnum')  # Slot received in
          c.addVarChar('cg_r',15)  # Receiver station ID  -  should usually be an MMSI, but sometimes is a string
          c.addInt('cg_sec')  # UTC seconds since the epoch
  
          c.addTimestamp('cg_timestamp') # UTC decoded cg_sec - not actually in the data stream
  
      if dbType == 'postgres':
          #--- EPSG 4326 : WGS 84
          #INSERT INTO "spatial_ref_sys" ("srid","auth_name","auth_srid","srtext","proj4text") VALUES (4326,'EPSG',4326,'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ');
          c.addPostGIS('pos','POINT',2,SRID=4326);
  
      return c
  
  def sqlInsertStr(params, outfile=sys.stdout, extraParams=None, dbType='postgres'):
          """
          Return the SQL INSERT command for this message type
          @param params: dictionary of values keyed by field name
          @param outfile: file like object to print to.
          @param extraParams: A sequence of tuples containing (name,sql type) for additional fields
          @return: sql create string
          @rtype: str
  
          @see: sqlCreate
          """
          outfile.write(str(sqlInsert(params,extraParams,dbType=dbType)))
  
  
  def sqlInsert(params,extraParams=None,dbType='postgres'):
          """
          Give the SQL INSERT statement
          @param params: dict keyed by field name of values
          @param extraParams: any extra fields that you have created beyond the normal ais message fields
          @rtype: sqlhelp.insert
          @return: insert class instance
           TODO(schwehr):allow optional type checking of params?
          @warning: this will take invalid keys happily and do what???
          """
  
          i = sqlhelp.insert('sls_lockorder',dbType=dbType)
  
          if dbType=='postgres':
                  finished = []
                  for key in params:
                          if key in finished:
                                  continue
  
                          if key not in toPgFields and key not in fromPgFields:
                                  if type(params[key])==Decimal: i.add(key,float(params[key]))
                                  else: i.add(key,params[key])
                          else:
                                  if key in fromPgFields:
                                          val = params[key]
                                          # Had better be a WKT type like POINT(-88.1 30.321)
                                          i.addPostGIS(key,val)
                                          finished.append(key)
                                  else:
                                          # Need to construct the type.
                                          pgName = toPgFields[key]
                                          #valStr='GeomFromText(\''+pgTypes[pgName]+'('
                                          valStr=pgTypes[pgName]+'('
                                          vals = []
                                          for nonPgKey in fromPgFields[pgName]:
                                                  vals.append(str(params[nonPgKey]))
                                                  finished.append(nonPgKey)
                                          valStr+=' '.join(vals)+')'
                                          i.addPostGIS(pgName,valStr)
          else:
                  for key in params:
                          if type(params[key])==Decimal: i.add(key,float(params[key]))
                          else: i.add(key,params[key])
  
          if None != extraParams:
                  for key in extraParams:
                          i.add(key,extraParams[key])
  
          return i
  
  ######################################################################
  # LATEX SUPPORT
  ######################################################################
  
  def latexDefinitionTable(outfile=sys.stdout
                  ):
          """
          Return the LaTeX definition table for this message type
          @param outfile: file like object to print to.
          @type outfile: file obj
          @return: LaTeX table string via the outfile
          @rtype: str
  
          """
          o = outfile
  
          o.write("""
  \\begin{table}%[htb]
  \\centering
  \\begin{tabular}{|l|c|l|}
  \\hline
  Parameter & Number of bits & Description
  \\\\  \\hline\\hline
  time\_month & 4 & Time tag of measurement  month 1..12 \\\\ \hline
  time\_day & 5 & Time tag of measurement  day of the month 1..31 \\\\ \hline
  time\_hour & 5 & Time tag of measurement  UTC hours 0..23 \\\\ \hline
  time\_min & 6 & Time tag of measurement  minutes \\\\ \hline
  lockid & 42 & Character identifier of the station \\\\ \hline
  pos\_longitude & 25 & Location of measurement  East West location \\\\ \hline
  pos\_latitude & 24 & Location of measurement  North South location \\\\ \hline
  reserved & 19 & Reserved bits for future use \\\\ \hline
  lockschedules & -1 & up to 6 lock schedule reports\\\\ \\hline \\hline
  Total bits & 129 & Appears to take 1 slot with 39 pad bits to fill the last slot \\\\ \\hline
  \\end{tabular}
  \\caption{AIS message number 8: St Lawrance Seaway wind information}
  \\label{tab:sls_lockorder}
  \\end{table}
  """)
  
  ######################################################################
  # Text Definition
  ######################################################################
  
  def textDefinitionTable(outfile=sys.stdout ,delim='    '):
      """Return the text definition table for this message type
  
      @param outfile: file like object to print to.
      @type outfile: file obj
      @return: text table string via the outfile
      @rtype: str
  
      """
      o = outfile
      o.write('Parameter'+delim+'Number of bits'+delim+"""Description
  time_month"""+delim+'4'+delim+"""Time tag of measurement  month 1..12
  time_day"""+delim+'5'+delim+"""Time tag of measurement  day of the month 1..31
  time_hour"""+delim+'5'+delim+"""Time tag of measurement  UTC hours 0..23
  time_min"""+delim+'6'+delim+"""Time tag of measurement  minutes
  lockid"""+delim+'42'+delim+"""Character identifier of the station
  pos_longitude"""+delim+'25'+delim+"""Location of measurement  East West location
  pos_latitude"""+delim+'24'+delim+"""Location of measurement  North South location
  reserved"""+delim+'19'+delim+"""Reserved bits for future use
  lockschedules"""+delim+'-1'+delim+"""up to 6 lock schedule reports
  Total bits"""+delim+"""129"""+delim+"""Appears to take 1 slot with 39 pad bits to fill the last slot""")
  
  
  ######################################################################
  # UNIT TESTING
  ######################################################################
  def testParams():
      '''Return a params file base on the testvalue tags.
      @rtype: dict
      @return: params based on testvalue tags
      '''
      params = {}
      params['time_month'] = 2
      params['time_day'] = 28
      params['time_hour'] = 23
      params['time_min'] = 45
      params['lockid'] = 'A345678'
      params['pos_longitude'] = Decimal('-122.16328')
      params['pos_latitude'] = Decimal('37.42446')
      params['reserved'] = 0
      params['lockschedules'] = BitVector(bitstring='0001010101010000')
  
      return params
  
  class Testsls_lockorder(unittest.TestCase):
      '''Use testvalue tag text from each type to build test case the sls_lockorder message'''
      def testEncodeDecode(self):
  
          params = testParams()
          bits   = encode(params)
          r      = decode(bits)
  
          # Check that each parameter came through ok.
          self.failUnlessEqual(r['time_month'],params['time_month'])
          self.failUnlessEqual(r['time_day'],params['time_day'])
          self.failUnlessEqual(r['time_hour'],params['time_hour'])
          self.failUnlessEqual(r['time_min'],params['time_min'])
          self.failUnlessEqual(r['lockid'],params['lockid'])
          self.failUnlessAlmostEqual(r['pos_longitude'],params['pos_longitude'],4)
          self.failUnlessAlmostEqual(r['pos_latitude'],params['pos_latitude'],4)
          self.failUnlessEqual(r['reserved'],params['reserved'])
          self.failUnlessEqual(r['lockschedules'],params['lockschedules'])
  
  def addMsgOptions(parser):
      parser.add_option('-d','--decode',dest='doDecode',default=False,action='store_true',
                  help='decode a "sls_lockorder" AIS message')
      parser.add_option('-e','--encode',dest='doEncode',default=False,action='store_true',
                  help='encode a "sls_lockorder" AIS message')
      parser.add_option('--time_month-field', dest='time_monthField',metavar='uint',type='int'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--time_day-field', dest='time_dayField',metavar='uint',type='int'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--time_hour-field', dest='time_hourField',metavar='uint',type='int'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--time_min-field', dest='time_minField',metavar='uint',type='int'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--lockid-field', dest='lockidField',default='@@@@@@@',metavar='aisstr6',type='string'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--pos_longitude-field', dest='pos_longitudeField',default=Decimal('181'),metavar='decimal',type='string'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--pos_latitude-field', dest='pos_latitudeField',default=Decimal('91'),metavar='decimal',type='string'
          ,help='Field parameter value [default: %default]')
      parser.add_option('--lockschedules-field', dest='lockschedulesField',metavar='binary',type='string'
          ,help='Field parameter value [default: %default]')
  
  def main():
      from optparse import OptionParser
      parser = OptionParser(usage="%prog [options]")
  
      parser.add_option('--doc-test',dest='doctest',default=False,action='store_true',
          help='run the documentation tests')
      parser.add_option('--unit-test',dest='unittest',default=False,action='store_true',
          help='run the unit tests')
      parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
          help='Make the test output verbose')
  
      # FIX: remove nmea from binary messages.  No way to build the whole packet?
      # FIX: or build the surrounding msg 8 for a broadcast?
      typeChoices = ('binary','nmeapayload','nmea') # FIX: what about a USCG type message?
      parser.add_option('-t', '--type', choices=typeChoices, type='choice',
          dest='ioType', default='nmeapayload',
          help='What kind of string to write for encoding ('+', '.join(typeChoices)+') [default: %default]')
  
  
      outputChoices = ('std','html','csv','sql' , 'kml','kml-full')
      parser.add_option('-T', '--output-type', choices=outputChoices,
          type='choice', dest='outputType', default='std',
          help='What kind of string to output ('+', '.join(outputChoices)+') '
          '[default: %default]')
  
      parser.add_option('-o','--output',dest='outputFileName',default=None,
          help='Name of the python file to write [default: stdout]')
  
      parser.add_option('-f', '--fields', dest='fieldList', default=None,
          action='append', choices=fieldList,
          help='Which fields to include in the output.  Currently only for csv '
          'output [default: all]')
  
      parser.add_option('-p', '--print-csv-field-list', dest='printCsvfieldList',
          default=False,action='store_true',
          help='Print the field name for csv')
  
      parser.add_option('-c', '--sql-create', dest='sqlCreate', default=False,
          action='store_true',
          help='Print out an sql create command for the table.')
  
      parser.add_option('--latex-table', dest='latexDefinitionTable',
          default=False,action='store_true',
          help='Print a LaTeX table of the type')
  
      parser.add_option('--text-table', dest='textDefinitionTable', default=False,
          action='store_true',
          help='Print delimited table of the type (for Word table importing)')
  
      parser.add_option('--delimt-text-table', dest='delimTextDefinitionTable',
          default='    ',
          help='Delimiter for text table [default: \'%default\'] '
          '(for Word table importing)')
  
      dbChoices = ('sqlite','postgres')
      parser.add_option('-D', '--db-type', dest='dbType', default='postgres',
          choices=dbChoices,type='choice',
          help='What kind of database ('+', '.join(dbChoices)+') '
          '[default: %default]')
  
      addMsgOptions(parser)
  
      (options,args) = parser.parse_args()
      success = True
  
      if options.doctest:
              import os; print os.path.basename(sys.argv[0]), 'doctests ...',
              sys.argv = [sys.argv[0]]
              if options.verbose:
                sys.argv.append('-v')
  
              numfail, numtests = doctest.testmod()
              if not numfail:
                  print 'ok'
              else:
                  print 'FAILED'
                  success = False
  
      if not success: sys.exit('Something Failed')
      del success # Hide success from epydoc
  
      if options.unittest:
              sys.argv = [sys.argv[0]]
              if options.verbose: sys.argv.append('-v')
              unittest.main()
  
      outfile = sys.stdout
      if None!=options.outputFileName:
              outfile = file(options.outputFileName,'w')
  
  
      if options.doEncode:
          # Make sure all non required options are specified.
          if None==options.time_monthField: parser.error("missing value for time_monthField")
          if None==options.time_dayField: parser.error("missing value for time_dayField")
          if None==options.time_hourField: parser.error("missing value for time_hourField")
          if None==options.time_minField: parser.error("missing value for time_minField")
          if None==options.lockidField: parser.error("missing value for lockidField")
          if None==options.pos_longitudeField: parser.error("missing value for pos_longitudeField")
          if None==options.pos_latitudeField: parser.error("missing value for pos_latitudeField")
          if None==options.lockschedulesField: parser.error("missing value for lockschedulesField")
      msgDict = {
          'time_month': options.time_monthField,
          'time_day': options.time_dayField,
          'time_hour': options.time_hourField,
          'time_min': options.time_minField,
          'lockid': options.lockidField,
          'pos_longitude': options.pos_longitudeField,
          'pos_latitude': options.pos_latitudeField,
          'reserved': '0',
          'lockschedules': options.lockschedulesField,
      }
  
      bits = encode(msgDict)
      if 'binary' == options.ioType:
          print str(bits)
      elif 'nmeapayload'==options.ioType:
          # FIX: figure out if this might be necessary at compile time
          bitLen=len(bits)
          if bitLen % 6 != 0:
              bits = bits + BitVector(size=(6 - (bitLen%6)))  # Pad out to multiple of 6
          print binary.bitvectoais6(bits)[0]
  
      # FIX: Do not emit this option for the binary message payloads.  Does not make sense.
      elif 'nmea' == options.ioType:
          nmea = uscg.create_nmea(bits)
          print nmea
      else:
          sys.exit('ERROR: unknown ioType.  Help!')
  
  
          if options.sqlCreate:
                  sqlCreateStr(outfile,options.fieldList,dbType=options.dbType)
  
          if options.latexDefinitionTable:
                  latexDefinitionTable(outfile)
  
          # For conversion to word tables
          if options.textDefinitionTable:
                  textDefinitionTable(outfile,options.delimTextDefinitionTable)
  
          if options.printCsvfieldList:
                  # Make a csv separated list of fields that will be displayed for csv
                  if None == options.fieldList: options.fieldList = fieldList
                  import StringIO
                  buf = StringIO.StringIO()
                  for field in options.fieldList:
                          buf.write(field+',')
                  result = buf.getvalue()
                  if result[-1] == ',': print result[:-1]
                  else: print result
  
          if options.doDecode:
                  if len(args)==0: args = sys.stdin
                  for msg in args:
                          bv = None
  
                          if msg[0] in ('$','!') and msg[3:6] in ('VDM','VDO'):
                                  # Found nmea
                                  # FIX: do checksum
                                  bv = binary.ais6tobitvec(msg.split(',')[5])
                          else: # either binary or nmeapayload... expect mostly nmeapayloads
                                  # assumes that an all 0 and 1 string can not be a nmeapayload
                                  binaryMsg=True
                                  for c in msg:
                                          if c not in ('0','1'):
                                                  binaryMsg=False
                                                  break
                                  if binaryMsg:
                                          bv = BitVector(bitstring=msg)
                                  else: # nmeapayload
                                          bv = binary.ais6tobitvec(msg)
  
                          printFields(decode(bv)
                                      ,out=outfile
                                      ,format=options.outputType
                                      ,fieldList=options.fieldList
                                      ,dbType=options.dbType
                                      )
  
  ############################################################
  if __name__=='__main__':
      main()
  