4 parse a MAVLink protocol XML file and generate a python implementation 6 Copyright Andrew Tridgell 2011 7 Released under GNU GPL version 3 or later 11 from __future__
import print_function
12 from future
import standard_library
13 standard_library.install_aliases()
14 from builtins
import object
18 from .
import mavparse
21 schemaFile = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"mavschema.xsd")
24 DEFAULT_WIRE_PROTOCOL = mavparse.PROTOCOL_1_0
25 DEFAULT_LANGUAGE =
'Python' 26 DEFAULT_ERROR_LIMIT = 200
27 DEFAULT_VALIDATE =
True 28 DEFAULT_STRICT_UNITS =
False 30 MAXIMUM_INCLUDE_FILE_NESTING = 5
33 supportedLanguages = [
"C",
"CS",
"JavaScript",
"Python",
"WLua",
"ObjC",
"Swift",
"Java",
"C++11"]
37 """Generate mavlink message formatters and parsers (C and Python ) using options 38 and args where args are a list of xml files. This function allows python 39 scripts under Windows to control mavgen using the same interface as 40 shell scripts under Unix""" 48 from lxml
import etree
49 with open(schemaFile,
'r') as f: 50 xmlschema_root = etree.parse(f) 51 if not opts.strict_units:
53 for elem
in xmlschema_root.iterfind(
'xs:attribute[@name="units"]', xmlschema_root.getroot().nsmap):
54 elem.set(
"type",
"xs:string")
55 xmlschema = etree.XMLSchema(xmlschema_root)
57 print(
"WARNING: Failed to import lxml module etree. Are lxml, libxml2 and libxslt installed? XML validation will not be performed", file=sys.stderr)
59 except etree.XMLSyntaxError
as err:
60 print(
"WARNING: XML Syntax Errors detected in %s XML schema file. XML validation will not be performed" % schemaFile, file=sys.stderr)
61 print(
str(err.error_log), file=sys.stderr)
64 print(
"WARNING: Unable to load XML validator libraries. XML validation will not be performed", file=sys.stderr)
67 def expand_includes():
68 """Expand includes in current list of all files, ignoring those already parsed.""" 71 fname = os.path.join(os.path.dirname(x.filename), i)
74 if fname
in all_files:
80 print(
"Validating %s" % fname)
81 if not mavgen_validate(fname):
84 print(
"Validation skipped for %s." % fname)
87 print(
"Parsing %s" % fname)
91 x.message_crcs.update(xml[-1].message_crcs)
92 x.message_lengths.update(xml[-1].message_lengths)
93 x.message_min_lengths.update(xml[-1].message_min_lengths)
94 x.message_flags.update(xml[-1].message_flags)
95 x.message_target_system_ofs.update(xml[-1].message_target_system_ofs)
96 x.message_target_component_ofs.update(xml[-1].message_target_component_ofs)
97 x.message_names.update(xml[-1].message_names)
98 x.largest_payload = max(x.largest_payload, xml[-1].largest_payload)
100 def mavgen_validate(xmlfile):
101 """Uses lxml to validate an XML file. We define mavgen_validate 102 here because it relies on the XML libs that were loaded in mavgen(), so it can't be called standalone""" 105 with open(xmlfile,
'r') as f: 106 xmldocument = etree.parse(f) 107 xmlschema.assertValid(xmldocument) 108 forbidden_names_re = re.compile("^(break$|case$|class$|catch$|const$|continue$|debugger$|default$|delete$|do$|else$|\ 109 export$|extends$|finally$|for$|function$|if$|import$|in$|instanceof$|let$|new$|\ 110 return$|super$|switch$|this$|throw$|try$|typeof$|var$|void$|while$|with$|yield$|\ 111 enum$|await$|implements$|package$|protected$|static$|interface$|private$|public$|\ 112 abstract$|boolean$|byte$|char$|double$|final$|float$|goto$|int$|long$|native$|\ 113 short$|synchronized$|transient$|volatile$).*", re.IGNORECASE)
114 for element
in xmldocument.iter(
'enum',
'entry',
'message',
'field'):
115 if forbidden_names_re.search(element.get(
'name')):
116 print(
"Validation error:", file=sys.stderr)
117 print(
"Element : %s at line : %s contains forbidden word" % (element.tag, element.sourceline), file=sys.stderr)
121 except etree.XMLSchemaError:
123 except etree.DocumentInvalid
as err:
124 sys.exit(
'ERROR: %s' %
str(err.error_log))
130 if fname
in all_files:
135 print(
"Validating %s" % fname)
136 if not mavgen_validate(fname):
139 print(
"Validation skipped for %s." % fname)
141 print(
"Parsing %s" % fname)
145 for i
in range(MAXIMUM_INCLUDE_FILE_NESTING):
146 len_allfiles = len(all_files)
148 if len(all_files) == len_allfiles:
153 largest_payload = max(x.largest_payload
for x
in xml)
if xml
else 0
155 x.largest_payload = largest_payload
157 if mavparse.check_duplicates(xml):
160 print(
"Found %u MAVLink message types in %u XML files" % (
161 mavparse.total_msgs(xml), len(xml)))
164 opts.language = opts.language.lower()
165 if opts.language ==
'python':
166 from .
import mavgen_python
167 mavgen_python.generate(opts.output, xml)
168 elif opts.language ==
'c':
169 from .
import mavgen_c
170 mavgen_c.generate(opts.output, xml)
171 elif opts.language ==
'wlua':
172 from .
import mavgen_wlua
173 mavgen_wlua.generate(opts.output, xml)
174 elif opts.language ==
'cs':
175 from .
import mavgen_cs
176 mavgen_cs.generate(opts.output, xml)
177 elif opts.language ==
'javascript':
178 from .
import mavgen_javascript
179 mavgen_javascript.generate(opts.output, xml)
180 elif opts.language ==
'objc':
181 from .
import mavgen_objc
182 mavgen_objc.generate(opts.output, xml)
183 elif opts.language ==
'swift':
184 from .
import mavgen_swift
185 mavgen_swift.generate(opts.output, xml)
186 elif opts.language ==
'java':
187 from .
import mavgen_java
188 mavgen_java.generate(opts.output, xml)
189 elif opts.language ==
'c++11':
190 from .
import mavgen_cpp11
191 mavgen_cpp11.generate(opts.output, xml)
193 print(
"Unsupported language %s" % opts.language)
200 def __init__(self, output, wire_protocol=DEFAULT_WIRE_PROTOCOL, language=DEFAULT_LANGUAGE, validate=DEFAULT_VALIDATE, error_limit=DEFAULT_ERROR_LIMIT, strict_units=DEFAULT_STRICT_UNITS):
210 '''generate the python code on the fly for a MAVLink dialect''' 211 dialects = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'..',
'dialects')
212 mdef = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'..',
'..',
'message_definitions')
213 if wire_protocol == mavparse.PROTOCOL_0_9:
214 py = os.path.join(dialects,
'v09', dialect +
'.py')
215 xml = os.path.join(dialects,
'v09', dialect +
'.xml')
216 if not os.path.exists(xml):
217 xml = os.path.join(mdef,
'v0.9', dialect +
'.xml')
218 elif wire_protocol == mavparse.PROTOCOL_1_0:
219 py = os.path.join(dialects,
'v10', dialect +
'.py')
220 xml = os.path.join(dialects,
'v10', dialect +
'.xml')
221 if not os.path.exists(xml):
222 xml = os.path.join(mdef,
'v1.0', dialect +
'.xml')
224 py = os.path.join(dialects,
'v20', dialect +
'.py')
225 xml = os.path.join(dialects,
'v20', dialect +
'.xml')
226 if not os.path.exists(xml):
227 xml = os.path.join(mdef,
'v1.0', dialect +
'.xml')
228 opts =
Opts(py, wire_protocol)
232 import StringIO
as io
237 stdout_saved = sys.stdout
238 sys.stdout = io.StringIO()
240 xml = os.path.relpath(xml)
241 if not mavgen(opts, [xml]):
242 sys.stdout = stdout_saved
245 sys.stdout = stdout_saved
247 sys.stdout = stdout_saved
250 if __name__ ==
"__main__":
251 raise DeprecationWarning(
"Executable was moved to pymavlink.tools.mavgen")
def mavgen_python_dialect(dialect, wire_protocol)
def __init__(self, output, wire_protocol=DEFAULT_WIRE_PROTOCOL, language=DEFAULT_LANGUAGE, validate=DEFAULT_VALIDATE, error_limit=DEFAULT_ERROR_LIMIT, strict_units=DEFAULT_STRICT_UNITS)