00001
00002
00003 '''
00004 parse a MAVLink protocol XML file and generate a python implementation
00005
00006 Copyright Andrew Tridgell 2011
00007 Released under GNU GPL version 3 or later
00008
00009 '''
00010 import sys, textwrap, os, copy
00011 from . import mavparse
00012
00013
00014 schemaFile = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mavschema.xsd")
00015
00016
00017 DEFAULT_WIRE_PROTOCOL = mavparse.PROTOCOL_1_0
00018 DEFAULT_LANGUAGE = 'Python'
00019 DEFAULT_ERROR_LIMIT = 200
00020 DEFAULT_VALIDATE = True
00021
00022
00023 supportedLanguages = ["C", "CS", "JavaScript", "Python", "WLua", "ObjC", "Swift", "Java"]
00024
00025
00026 def mavgen(opts, args) :
00027 """Generate mavlink message formatters and parsers (C and Python ) using options
00028 and args where args are a list of xml files. This function allows python
00029 scripts under Windows to control mavgen using the same interface as
00030 shell scripts under Unix"""
00031
00032 xml = []
00033
00034
00035 if opts.validate:
00036 try:
00037 from lib.genxmlif import GenXmlIfError
00038 from lib.minixsv import pyxsval
00039 except:
00040 print("WARNING: Unable to load XML validator libraries. XML validation will not be performed")
00041 opts.validate = False
00042
00043 def mavgen_validate(fname, schema, errorLimitNumber) :
00044 """Uses minixsv to validate an XML file with a given XSD schema file. We define mavgen_validate
00045 here because it relies on the XML libs that were loaded in mavgen(), so it can't be called standalone"""
00046
00047 domTreeWrapper = pyxsval.parseAndValidate(fname, xsdFile=schema, errorLimit=errorLimitNumber)
00048
00049
00050 for fname in args:
00051 if opts.validate:
00052 print("Validating %s" % fname)
00053 mavgen_validate(fname, schemaFile, opts.error_limit);
00054 else:
00055 print("Validation skipped for %s." % fname)
00056
00057 print("Parsing %s" % fname)
00058 xml.append(mavparse.MAVXML(fname, opts.wire_protocol))
00059
00060
00061 for x in xml[:]:
00062 for i in x.include:
00063 fname = os.path.join(os.path.dirname(x.filename), i)
00064
00065
00066 if opts.validate:
00067 print("Validating %s" % fname)
00068 mavgen_validate(fname, schemaFile, opts.error_limit);
00069 else:
00070 print("Validation skipped for %s." % fname)
00071
00072
00073 print("Parsing %s" % fname)
00074 xml.append(mavparse.MAVXML(fname, opts.wire_protocol))
00075
00076
00077 x.message_crcs.update(xml[-1].message_crcs)
00078 x.message_lengths.update(xml[-1].message_lengths)
00079 x.message_min_lengths.update(xml[-1].message_min_lengths)
00080 x.message_flags.update(xml[-1].message_flags)
00081 x.message_target_system_ofs.update(xml[-1].message_target_system_ofs)
00082 x.message_target_component_ofs.update(xml[-1].message_target_component_ofs)
00083 x.message_names.update(xml[-1].message_names)
00084 x.largest_payload = max(x.largest_payload, xml[-1].largest_payload)
00085
00086
00087 largest_payload = 0
00088 for x in xml:
00089 if x.largest_payload > largest_payload:
00090 largest_payload = x.largest_payload
00091 for x in xml:
00092 x.largest_payload = largest_payload
00093
00094 if mavparse.check_duplicates(xml):
00095 sys.exit(1)
00096
00097 print("Found %u MAVLink message types in %u XML files" % (
00098 mavparse.total_msgs(xml), len(xml)))
00099
00100
00101 opts.language = opts.language.lower()
00102 if opts.language == 'python':
00103 from . import mavgen_python
00104 mavgen_python.generate(opts.output, xml)
00105 elif opts.language == 'c':
00106 from . import mavgen_c
00107 mavgen_c.generate(opts.output, xml)
00108 elif opts.language == 'wlua':
00109 from . import mavgen_wlua
00110 mavgen_wlua.generate(opts.output, xml)
00111 elif opts.language == 'cs':
00112 from . import mavgen_cs
00113 mavgen_cs.generate(opts.output, xml)
00114 elif opts.language == 'javascript':
00115 from . import mavgen_javascript
00116 mavgen_javascript.generate(opts.output, xml)
00117 elif opts.language == 'objc':
00118 from . import mavgen_objc
00119 mavgen_objc.generate(opts.output, xml)
00120 elif opts.language == 'swift':
00121 from . import mavgen_swift
00122 mavgen_swift.generate(opts.output, xml)
00123 elif opts.language == 'java':
00124 from . import mavgen_java
00125 mavgen_java.generate(opts.output, xml)
00126 else:
00127 print("Unsupported language %s" % opts.language)
00128
00129
00130
00131 class Opts:
00132 def __init__(self, output, wire_protocol=DEFAULT_WIRE_PROTOCOL, language=DEFAULT_LANGUAGE, validate=DEFAULT_VALIDATE, error_limit=DEFAULT_ERROR_LIMIT):
00133 self.wire_protocol = wire_protocol
00134 self.error_limit = error_limit
00135 self.language = language
00136 self.output = output
00137 self.validate = validate
00138
00139 def mavgen_python_dialect(dialect, wire_protocol):
00140 '''generate the python code on the fly for a MAVLink dialect'''
00141 dialects = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'dialects')
00142 mdef = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'message_definitions')
00143 if wire_protocol == mavparse.PROTOCOL_0_9:
00144 py = os.path.join(dialects, 'v09', dialect + '.py')
00145 xml = os.path.join(dialects, 'v09', dialect + '.xml')
00146 if not os.path.exists(xml):
00147 xml = os.path.join(mdef, 'v0.9', dialect + '.xml')
00148 elif wire_protocol == mavparse.PROTOCOL_1_0:
00149 py = os.path.join(dialects, 'v10', dialect + '.py')
00150 xml = os.path.join(dialects, 'v10', dialect + '.xml')
00151 if not os.path.exists(xml):
00152 xml = os.path.join(mdef, 'v1.0', dialect + '.xml')
00153 else:
00154 py = os.path.join(dialects, 'v20', dialect + '.py')
00155 xml = os.path.join(dialects, 'v20', dialect + '.xml')
00156 if not os.path.exists(xml):
00157 xml = os.path.join(mdef, 'v1.0', dialect + '.xml')
00158 opts = Opts(py, wire_protocol)
00159
00160
00161 try:
00162 import StringIO as io
00163 except ImportError:
00164 import io
00165
00166
00167 stdout_saved = sys.stdout
00168 sys.stdout = io.StringIO()
00169 try:
00170 xml = os.path.relpath(xml)
00171 mavgen( opts, [xml] )
00172 except Exception:
00173 sys.stdout = stdout_saved
00174 raise
00175 sys.stdout = stdout_saved
00176
00177 if __name__ == "__main__":
00178 raise DeprecationWarning("Executable was moved to pymavlink.tools.mavgen")