Package ais :: Module aisfield
[hide private]
[frames] | no frames]

Source Code for Module ais.aisfield

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 5231 $'.split()[1] 
  4  __date__ = '$Date: 2006-12-20 06:54:50 -0700 (Wed, 20 Dec 2006) $'.split()[1] 
  5  __author__ = 'Kurt Schwehr' 
  6   
  7  __doc__=''' 
  8  Create a basic field for an ais message 
  9   
 10  Here is one of the simplest possible examples of an integer that goes 
 11  from 0 to 255: 
 12   
 13  FIX: how do I do epydoc indented text? 
 14   
 15  ./aisfield.py -n MyName -t uint -d "My unsigned integer field" 
 16   
 17  <field name="MyName" numberofbits="8" type="uint"> 
 18  <description>My unsigned integer field</description> 
 19  </field> 
 20   
 21   
 22   
 23  @author: U{'''+__author__+'''<http://xenon.stanford.edu/~schwehr/>} 
 24  @version: ''' + __version__ +''' 
 25  @copyright: 2006 
 26  @var __date__: Date of last svn commit 
 27  @undocumented: __version__ __author__ __doc__ myparser 
 28  @since: 2006-Sep-21 
 29  @status: under development 
 30  @organization: U{CCOM<http://ccom.unh.edu/>} 
 31  @license: GPL 
 32  ''' 
 33   
 34  import sys 
 35   
 36  ###################################################################### 
 37  # Module Variables 
 38  ###################################################################### 
 39   
 40  typeBitsGuess = { 'bool':1,  
 41                    'uint':8, 'sint':8,  
 42                    'udecimal':8, 'sdecimal':8,  
 43                    'float':32, 'double':64,   # These are mandatory 
 44                    'aisstr6':6, 'ascii7':7,   # These are mandatory 
 45  } 
 46  ''' 
 47  Best initial guess for each type size.  The floating point and 
 48  string values must be these sizes. 
 49  ''' 
 50   
 51  typeChoices = ['bool','uint','sint','udecimal','sdecimal','float','double','aisstr6','ascii7'] 
 52  ''' 
 53  List of all the available types that may be used to fill an AIS message. 
 54  ''' 
 55   
 56  # FIX: should bool be in here? 
 57  numberTypes = ['uint','sint','udecimal','sdecimal','float','double'] 
 58  ''' 
 59  Subset of typeChoices that only has the numeric types 
 60  ''' 
 61   
 62  ###################################################################### 
63 -def tag(outfile,tagName,value,indent=''):
64 ''' 65 Write out one complete tag 66 @param outfile: open file to write to 67 @param tagName: string containing the xml tag 68 @param value: what to put between the begin and end tag. Converts to a string 69 @param indent: how much to indent the tag 70 ''' 71 outfile.write(indent+'<'+tagName+'>'+str(value)+'</'+tagName+'>\n')
72 73 ######################################################################
74 -def getStubFieldDict():
75 ''' 76 Convenience for thos that just want to tweak one or two things 77 @return: example dictionary that can then be added to. 78 ''' 79 80 return {'maxRange': None, 'outputFile': None, 'lut': None, 81 'description': None, 'notes': None, 'required': None, 82 'minRange': None, 'numberOfBits': 1, 'units': None, 83 'scale': None, 'arrayLength': None, 'completeXml': False, 84 'decimalPlaces': None, 'unavailable': None, 85 'type': 'bool', 'name': None}
86 87 ######################################################################
88 -def makeField(options,out=sys.stdout):
89 ''' 90 Write out one field of xml. Here is a sample options dict 91 92 {'maxRange': None, 'outputFile': None, 'lut': None, 'description': None, 'notes': None, 'required': None, 'minRange': None, 'numberOfBits': 1, 'units': None, 'scale': None, 'arrayLength': None, 'completeXml': False, 'decimalPlaces': None, 'unavailable': None, 'type': 'bool', 'name': None} 93 94 @param options: dict of all the required fields 95 96 ''' 97 o = options 98 #out = sys.stdout 99 100 if o.completeXml: 101 out.write('<?xml version="1.0" encoding="utf-8"?>\n') 102 out.write('<ais-binary-messages version="1.0">\n') 103 out.write('<!-- FIX: add date -->\n') 104 out.write('<!-- FIX: add user -->\n') 105 out.write('<!-- Produced by aisfield.py -->\n') 106 out.write('<!-- Options: '+str(options)+' -->\n') 107 108 indent='\t' 109 out.write(indent+'<field name="'+o.name+'" ') 110 if options.arrayLength: out.write('arraylength="'+str(o.arrayLength)+'" ') 111 out.write('numberofbits="'+str(o.numberOfBits)+'" type="'+o.type+'">\n') 112 113 if True: 114 indent+='\t' 115 116 out.write(indent+'<description>'+o.description+'</description>\n') 117 if o.notes: 118 for note in o.notes: 119 out.write(indent+'<note>'+note+'</note>\n') 120 121 if o.minRange: out.write(indent+'<range min="'+str(o.minRange)+'" max="'+str(o.maxRange)+'">\n') 122 if o.unavailable: tag(out,'unavailable',o.unavailable,indent) 123 if o.scale: tag(out,'scale',o.scale,indent) 124 125 if o.decimalPlaces: tag(out,'decimalplaces',o.decimalPlaces,indent) 126 if o.units: tag(out,'units',o.units,indent) 127 128 if o.required: tag(out,'required',o.required,indent) 129 130 if o.lut: 131 out.write(indent+'<lookuptable>\n') 132 indent += '\t' 133 134 for i in range(len(o.lut)): 135 out.write(indent+'<entry key="'+str(i)+'">'+str(o.lut[i])+'</entry>\n') 136 indent=indent[:-1] 137 out.write(indent+'</lookuptable>\n') 138 139 indent=indent[:-1] 140 141 out.write(indent+'</field>\n') 142 143 if o.completeXml: 144 out.write('</ais-binary-messages>\n') 145 146 return
147 148 ######################################################################
149 -def validate(options,notify=True):
150 ''' 151 Check all of the options to make sure they work 152 @param options: dict with all option fields 153 @param notify: if true, emit error messages to stdout 154 @return: True if options all ok 155 ''' 156 o = options 157 ok=True 158 if not o.name: 159 ok=False 160 if notify: print 'Must specify the "name" of the variable' 161 # FIX: check the name field, maybe with a regex 162 163 if o.arrayLength and o.arrayLength<2: 164 ok=False 165 if notify: print 'Array length must be 2 or more' 166 167 if (not o.numberOfBits) or (o.numberOfBits<1) or (o.numberOfBits>64): 168 ok=False 169 if notify: print 'Invalid number of bits:',o.numberOfBits 170 171 if not o.description: 172 ok=False 173 if notify: print 'Must give a description' 174 175 if o.unavailable and (o.type in numberTypes): 176 try: 177 float(o.unavailable) 178 except ValueError: 179 ok=False 180 if notify: print 'unavailable must be an number' 181 182 # If unavailable and a string type , make sure that the string length fills the whole buffer 183 if o.scale: 184 try: 185 float(o.scale) 186 except ValueError: 187 ok=False 188 if notify: print 'Scale must be an number' 189 190 if o.lut and (o.type not in ['bool','uint']): #,'sint']): 191 ok=False 192 if notify: print 'Lookup tables must be an unsigned integer' 193 194 # If int and no scale, can't specify decimal places 195 196 return ok
197 198 199 200 ###################################################################### 201 if __name__=='__main__': 202 from optparse import OptionParser 203 myparser = OptionParser(usage="%prog [options]", 204 version="%prog "+__version__) 205 206 207 myparser.add_option('-o','--output',dest='outputFile',default=None, 208 help='Name of the xml file to write. Opens for appending [default: stdout]') 209 210 myparser.add_option('-c','--complete',dest='completeXml',default=False,action='store_true', 211 help='Write out a complete xml file for a message.' 212 +'Not really good for an ais message') 213 214 215 myparser.add_option('-n','--name',dest='name',default=None,type='string', 216 help='Name of the field [required]') 217 218 myparser.add_option('-a','--array-length',dest='arrayLength',type='int',default=None, 219 help='How many items to have or string length [default: not an array]') 220 221 myparser.add_option('-N','--number-of-bits',dest='numberOfBits',type='int',default=None, 222 help='Number of bits for each element in a field.' 223 +' ints and decimal can be in the range of 1..32. [default: best guess] ('+ 224 (''.join([choice+':'+str(typeBitsGuess[choice])+' ' for choice in typeBitsGuess])[:-1]) 225 +')') 226 227 myparser.add_option('-t','--type',dest='type', type='choice', default='bool', 228 choices=typeChoices, 229 help='What type of data will the option represent? "u" for unsigned, "s" for signed. ('+ 230 (''.join([choice +' ' for choice in typeChoices]))[:-1]+')' 231 ) 232 233 myparser.add_option('-d','--description',dest='description',default=None,type='string', 234 help='Description of the field [required]') 235 myparser.add_option('--note',dest='notes',action='append',type='string',default=None, 236 help='0 or more notes to attach to the field') 237 238 myparser.add_option('-r','--min-range',dest='minRange',default=None,type='float', 239 help='Minimum possible value for a field. [default: none]') 240 myparser.add_option('-R','--max-range',dest='maxRange',default=None,type='float', 241 help='Minimum possible value for a field. [default: none]') 242 243 244 myparser.add_option('-u','--unavailable',dest='unavailable',default=None,type='string', 245 help='Value to use for when none is known. [default: none]') 246 247 #myparser.add_option('-s','--scale',dest='scale',default=None,type='float', 248 # FIX: validate that the scale is actually a valid number 249 myparser.add_option('-s','--scale',dest='scale',default=None,type='string', 250 help='Value scale natural value to transmitted value. [default: none]') 251 252 myparser.add_option('-D','--decimal-places',dest='decimalPlaces',default=None,type='int', 253 help='Decimal places to keep after undoing scale. [default: none]') 254 255 myparser.add_option('-U','--units',dest='units',default=None,type='string', 256 help='What units are for the values. [default: none]') 257 258 myparser.add_option('--required',dest='required',default=None,type='float', 259 help='TRY NOT TO USE THIS ONE accept for dac, fid, and efid. ' 260 +'Specify manditory value if the field can not change. [default: none]') 261 262 myparser.add_option('-l','--lookup-table',dest='lut',default=None,action='append',type='string', 263 help='Specify multiple entries in a lookup table. Starts with 0.') 264 265 (options,args) = myparser.parse_args() 266 267 if not options.numberOfBits: 268 options.numberOfBits = typeBitsGuess[options.type] 269 270 # print options 271 272 if not validate(options): 273 sys.exit('ERROR: Options not ok.') 274 275 if options.outputFile: 276 makeField(options,file(options.outputFile,'a')) 277 else: 278 makeField(options) 279