mavgenerate.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #!/usr/bin/env python
  2. """\
  3. mavgenerate.py is a GUI front-end for mavgen, a python based MAVLink
  4. header generation tool.
  5. Notes:
  6. -----
  7. * 2012-7-16 -- dagoodman
  8. Working on Mac 10.6.8 darwin, with Python 2.7.1
  9. * 2012-7-17 -- dagoodman
  10. Only GUI code working on Mac 10.6.8 darwin, with Python 3.2.3
  11. Working on Windows 7 SP1, with Python 2.7.3 and 3.2.3
  12. Mavgen doesn't work with Python 3.x yet
  13. * 2012-9-25 -- dagoodman
  14. Passing error limit into mavgen to make output cleaner.
  15. Copyright 2012 David Goodman (dagoodman@soe.ucsc.edu)
  16. Released under GNU GPL version 3 or later
  17. """
  18. import os
  19. import re
  20. import sys
  21. # Python 2.x and 3.x compatibility
  22. if sys.version_info[0] == 3:
  23. from tkinter import *
  24. import tkinter.filedialog
  25. import tkinter.messagebox
  26. else:
  27. # Must be using Python 2.x, import and rename
  28. from Tkinter import *
  29. import tkFileDialog
  30. import tkMessageBox
  31. tkinter.filedialog = tkFileDialog
  32. del tkFileDialog
  33. tkinter.messagebox = tkMessageBox
  34. del tkMessageBox
  35. from pymavlink.generator import mavgen
  36. from pymavlink.generator import mavparse
  37. title = "MAVLink Generator"
  38. error_limit = 5
  39. class Application(Frame):
  40. def __init__(self, master=None):
  41. Frame.__init__(self, master)
  42. self.pack_propagate(0)
  43. self.grid( sticky=N+S+E+W)
  44. self.createWidgets()
  45. """\
  46. Creates the gui and all of its content.
  47. """
  48. def createWidgets(self):
  49. #----------------------------------------
  50. # Create the XML entry
  51. self.xml_value = StringVar()
  52. self.xml_label = Label( self, text="XML" )
  53. self.xml_label.grid(row=0, column = 0)
  54. self.xml_entry = Entry( self, width = 26, textvariable=self.xml_value )
  55. self.xml_entry.grid(row=0, column = 1)
  56. self.xml_button = Button (self, text="Browse", command=self.browseXMLFile)
  57. self.xml_button.grid(row=0, column = 2)
  58. #----------------------------------------
  59. # Create the Out entry
  60. self.out_value = StringVar()
  61. self.out_label = Label( self, text="Out" )
  62. self.out_label.grid(row=1,column = 0)
  63. self.out_entry = Entry( self, width = 26, textvariable=self.out_value )
  64. self.out_entry.grid(row=1, column = 1)
  65. self.out_button = Button (self, text="Browse", command=self.browseOutDirectory)
  66. self.out_button.grid(row=1, column = 2)
  67. #----------------------------------------
  68. # Create the Lang box
  69. self.language_value = StringVar()
  70. self.language_choices = mavgen.supportedLanguages
  71. self.language_label = Label( self, text="Language" )
  72. self.language_label.grid(row=2, column=0)
  73. self.language_menu = OptionMenu(self,self.language_value,*self.language_choices)
  74. self.language_value.set(mavgen.DEFAULT_LANGUAGE)
  75. self.language_menu.config(width=10)
  76. self.language_menu.grid(row=2, column=1,sticky=W)
  77. #----------------------------------------
  78. # Create the Protocol box
  79. self.protocol_value = StringVar()
  80. self.protocol_choices = [mavparse.PROTOCOL_1_0, mavparse.PROTOCOL_2_0]
  81. self.protocol_label = Label( self, text="Protocol")
  82. self.protocol_label.grid(row=3, column=0)
  83. self.protocol_menu = OptionMenu(self,self.protocol_value,*self.protocol_choices)
  84. self.protocol_value.set(mavgen.DEFAULT_WIRE_PROTOCOL)
  85. self.protocol_menu.config(width=10)
  86. self.protocol_menu.grid(row=3, column=1,sticky=W)
  87. #----------------------------------------
  88. # Create the Validate box
  89. self.validate_value = BooleanVar()
  90. self.validate_label = Label( self, text="Validate")
  91. self.validate_label.grid(row=4, column=0)
  92. self.validate_button = Checkbutton(self, variable=self.validate_value, onvalue=True, offvalue=False)
  93. self.validate_value.set(mavgen.DEFAULT_VALIDATE)
  94. self.validate_button.config(width=10)
  95. self.validate_button.grid(row=4, column=1,sticky=W)
  96. #----------------------------------------
  97. # Create the Validate Units box
  98. self.strict_units_value = BooleanVar()
  99. self.strict_units_label = Label( self, text="Validate Units")
  100. self.strict_units_label.grid(row=5, column=0)
  101. self.strict_units_button = Checkbutton(self, variable=self.strict_units_value, onvalue=True, offvalue=False)
  102. self.strict_units_value.set(mavgen.DEFAULT_STRICT_UNITS)
  103. self.strict_units_button.config(width=10)
  104. self.strict_units_button.grid(row=5, column=1,sticky=W)
  105. #----------------------------------------
  106. # Create the generate button
  107. self.generate_button = Button ( self, text="Generate", command=self.generateHeaders)
  108. self.generate_button.grid(row=6,column=1)
  109. """\
  110. Open a file selection window to choose the XML message definition.
  111. """
  112. def browseXMLFile(self):
  113. # TODO Allow specification of multiple XML definitions
  114. xml_file = tkinter.filedialog.askopenfilename(parent=self, title='Choose a definition file')
  115. if xml_file != None:
  116. self.xml_value.set(xml_file)
  117. """\
  118. Open a directory selection window to choose an output directory for
  119. headers.
  120. """
  121. def browseOutDirectory(self):
  122. mavlinkFolder = os.path.dirname(os.path.realpath(__file__))
  123. out_dir = tkinter.filedialog.askdirectory(parent=self,initialdir=mavlinkFolder,title='Please select an output directory')
  124. if out_dir != None:
  125. self.out_value.set(out_dir)
  126. """\
  127. Generates the header files and place them in the output directory.
  128. """
  129. def generateHeaders(self):
  130. # Verify settings
  131. rex = re.compile(".*\\.xml$", re.IGNORECASE)
  132. if not self.xml_value.get():
  133. tkinter.messagebox.showerror('Error Generating Headers','An XML message definition file must be specified.')
  134. return
  135. if not self.out_value.get():
  136. tkinter.messagebox.showerror('Error Generating Headers', 'An output directory must be specified.')
  137. return
  138. if os.path.isdir(self.out_value.get()):
  139. if not tkinter.messagebox.askokcancel('Overwrite Headers?','The output directory \'{0}\' already exists. Headers may be overwritten if they already exist.'.format(self.out_value.get())):
  140. return
  141. # Generate headers
  142. opts = mavgen.Opts(self.out_value.get(), wire_protocol=self.protocol_value.get(), language=self.language_value.get(), validate=self.validate_value.get(), error_limit=error_limit, strict_units=self.strict_units_value.get());
  143. args = [self.xml_value.get()]
  144. try:
  145. mavgen.mavgen(opts,args)
  146. tkinter.messagebox.showinfo('Successfully Generated Headers', 'Headers generated successfully.')
  147. except Exception as ex:
  148. exStr = formatErrorMessage(str(ex));
  149. tkinter.messagebox.showerror('Error Generating Headers','{0!s}'.format(exStr))
  150. return
  151. """\
  152. Format the mavgen exceptions by removing 'ERROR: '.
  153. """
  154. def formatErrorMessage(message):
  155. reObj = re.compile(r'^(ERROR):\s+',re.M);
  156. matches = re.findall(reObj, message);
  157. prefix = ("An error occurred in mavgen:" if len(matches) == 1 else "Errors occurred in mavgen:\n")
  158. message = re.sub(reObj, '\n', message);
  159. return prefix + message
  160. # End of Application class
  161. # ---------------------------------
  162. # ---------------------------------
  163. # Start
  164. if __name__ == '__main__':
  165. app = Application()
  166. app.master.title(title)
  167. app.mainloop()