params: generate param metadata as MAVLink-compatible JSON component info (#15389)

This commit is contained in:
Hamish Willee
2020-08-03 12:00:37 +02:00
committed by GitHub
parent 6923d9eb64
commit 958d5a36ec
4 changed files with 170 additions and 10 deletions
+8 -1
View File
@@ -55,11 +55,18 @@ add_custom_target(metadata_parameters
--src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d` --src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d`
--inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml --inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml
--markdown ${PX4_BINARY_DIR}/docs/parameters.md --markdown ${PX4_BINARY_DIR}/docs/parameters.md
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/src/lib/parameters/px_process_params.py
--src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d`
--inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml
--json ${PX4_BINARY_DIR}/docs/parameters.json
COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/src/lib/parameters/px_process_params.py COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/src/lib/parameters/px_process_params.py
--src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d` --src-path `find ${PX4_SOURCE_DIR}/src -maxdepth 4 -type d`
--inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml --inject-xml ${PX4_SOURCE_DIR}/src/lib/parameters/parameters_injected.xml
--xml ${PX4_BINARY_DIR}/docs/parameters.xml --xml ${PX4_BINARY_DIR}/docs/parameters.xml
COMMENT "Generating full parameter metadata (markdown and xml)"
COMMENT "Generating full parameter metadata (markdown, xml, and json)"
USES_TERMINAL USES_TERMINAL
) )
+6 -2
View File
@@ -1,6 +1,6 @@
############################################################################ ############################################################################
# #
# Copyright (c) 2017 PX4 Development Team. All rights reserved. # Copyright (c) 2017 - 2020 PX4 Development Team. All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
@@ -87,11 +87,14 @@ add_custom_command(OUTPUT ${generated_serial_params_file}
) )
set(parameters_xml ${PX4_BINARY_DIR}/parameters.xml) set(parameters_xml ${PX4_BINARY_DIR}/parameters.xml)
set(parameters_json ${PX4_BINARY_DIR}/parameters.json)
file(GLOB_RECURSE param_src_files ${PX4_SOURCE_DIR}/src/*params.c) file(GLOB_RECURSE param_src_files ${PX4_SOURCE_DIR}/src/*params.c)
add_custom_command(OUTPUT ${parameters_xml} add_custom_command(OUTPUT ${parameters_xml} ${parameters_json}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/px_process_params.py COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/px_process_params.py
--src-path ${module_list} ${generated_params_dir} --src-path ${module_list} ${generated_params_dir}
--xml ${parameters_xml} --xml ${parameters_xml}
--json ${parameters_json}
--compress
--inject-xml ${CMAKE_CURRENT_SOURCE_DIR}/parameters_injected.xml --inject-xml ${CMAKE_CURRENT_SOURCE_DIR}/parameters_injected.xml
--overrides ${PARAM_DEFAULT_OVERRIDES} --overrides ${PARAM_DEFAULT_OVERRIDES}
--board ${PX4_BOARD} --board ${PX4_BOARD}
@@ -102,6 +105,7 @@ add_custom_command(OUTPUT ${parameters_xml}
parameters_injected.xml parameters_injected.xml
px4params/srcparser.py px4params/srcparser.py
px4params/srcscanner.py px4params/srcscanner.py
px4params/jsonout.py
px4params/xmlout.py px4params/xmlout.py
px_process_params.py px_process_params.py
parameters_injected.xml parameters_injected.xml
+112
View File
@@ -0,0 +1,112 @@
from xml.sax.saxutils import escape
import codecs
import json
import sys
class JsonOutput():
def __init__(self, groups, board, inject_xml_file_name):
all_json=dict()
all_json['version']=1
all_json['uid']=1 #COMPONENT_INFORMATION.comp_metadata_type
all_json['scope']="Firmware"
all_params=[]
all_json['parameters']=all_params
#xml_parameters = ET.Element("parameters")
#xml_version = ET.SubElement(xml_parameters, "version")
#xml_version.text = "3"
#xml_version = ET.SubElement(xml_parameters, "parameter_version_major")
#xml_version.text = "1"
#xml_version = ET.SubElement(xml_parameters, "parameter_version_minor")
#xml_version.text = "15"
schema_map = {
"short_desc": "shortDescription",
"long_desc": "longDescription",
"unit": "units",
"decimal": "decimalPlaces",
"min": "min",
"max": "max",
"increment": "increment",
"reboot_required": "rebootRequired"
}
allowed_types = { "Uint8", "Int8", "Uint16", "Int16", "Uint32", "Int32", "Float"}
last_param_name = ""
board_specific_param_set = False
for group in groups:
group_name=group.GetName()
for param in group.GetParams():
if (last_param_name == param.GetName() and not board_specific_param_set) or last_param_name != param.GetName():
curr_param=dict()
curr_param['name'] = param.GetName()
curr_param['defaultValue'] = param.GetDefault()
curr_param['type'] = param.GetType().capitalize()
if not curr_param['type'] in allowed_types:
print("Error: %s type not supported: curr_param['type']" % (curr_param['name'],curr_param['type']) )
sys.Exit(1)
curr_param['group'] = group_name
if (param.GetCategory()):
curr_param['category'] = param.GetCategory()
if (param.GetVolatile() == "true"):
curr_param['volatile'] = param.GetVolatile()
last_param_name = param.GetName()
for code in param.GetFieldCodes():
value = param.GetFieldValue(code)
if code == "board":
if value == board:
board_specific_param_set = True
# JSON schema has no field for board_specific schema. Ignore.
else:
#xml_group.remove(xml_param)
continue
else:
#map PX4 param field names to schema names
if code in schema_map:
curr_param[schema_map[code]] = value
else:
print('ERROR: Field not in json schema: %s' % code)
sys.exit(1)
if last_param_name != param.GetName():
board_specific_param_set = False
enum_codes=param.GetEnumCodes() or '' # Gets numerical values for parameter.
if enum_codes:
enum_codes=sorted(enum_codes,key=float)
codes_list=list()
for item in enum_codes:
code_dict=dict()
code_dict['value']=item
code_dict['description']=param.GetEnumValue(item)
codes_list.append(code_dict)
curr_param['values'] = codes_list
if len(param.GetBitmaskList()) > 0:
bitmasks_list=list()
for index in param.GetBitmaskList():
bitmask_dict=dict()
bitmask_dict['index']=index
bitmask_dict['description']=param.GetBitmaskBit(index)
bitmasks_list.append(bitmask_dict)
curr_param['bitmask'] = bitmasks_list
all_params.append(curr_param)
#Json string output.
self.output = json.dumps(all_json,indent=2)
def Save(self, filename):
with codecs.open(filename, 'w', 'utf-8') as f:
f.write(self.output)
+44 -7
View File
@@ -33,7 +33,7 @@
############################################################################ ############################################################################
# #
# PX4 paramers processor (main executable file) # PX4 paramaters processor (main executable file)
# #
# This tool scans the PX4 source code for declarations of tunable parameters # This tool scans the PX4 source code for declarations of tunable parameters
# and outputs the list in various formats. # and outputs the list in various formats.
@@ -47,12 +47,22 @@ from __future__ import print_function
import sys import sys
import os import os
import argparse import argparse
from px4params import srcscanner, srcparser, injectxmlparams, xmlout, markdownout from px4params import srcscanner, srcparser, injectxmlparams, xmlout, markdownout, jsonout
import gzip #to create .gz file
import re import re
import json import json
import codecs import codecs
def SaveCompressed(filename):
#create gz compressed version
gz_filename=filename+'.gz'
with gzip.open(gz_filename, 'wt') as f:
with open(filename, 'r') as content_file:
f.write(content_file.read())
def main(): def main():
# Parse command line arguments # Parse command line arguments
parser = argparse.ArgumentParser(description="Process parameter documentation.") parser = argparse.ArgumentParser(description="Process parameter documentation.")
@@ -84,9 +94,18 @@ def main():
metavar="FILENAME", metavar="FILENAME",
help="Create Markdown file" help="Create Markdown file"
" (default FILENAME: parameters.md)") " (default FILENAME: parameters.md)")
parser.add_argument("-j", "--json",
nargs='?',
const="parameters.json",
metavar="FILENAME",
help="Create Json file"
" (default FILENAME: parameters.json)")
parser.add_argument('-v', '--verbose', parser.add_argument('-v', '--verbose',
action='store_true', action='store_true',
help="verbose output") help="verbose output")
parser.add_argument('-c', '--compress',
action='store_true',
help="compress parameter file")
parser.add_argument("-o", "--overrides", parser.add_argument("-o", "--overrides",
default="{}", default="{}",
metavar="OVERRIDES", metavar="OVERRIDES",
@@ -95,7 +114,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
# Check for valid command # Check for valid command
if not (args.xml or args.markdown): if not (args.xml or args.markdown or args.json):
print("Error: You need to specify at least one output method!\n") print("Error: You need to specify at least one output method!\n")
parser.print_usage() parser.print_usage()
sys.exit(1) sys.exit(1)
@@ -134,21 +153,39 @@ def main():
param.default = val param.default = val
print("OVERRIDING {:s} to {:s}!!!!!".format(name, val)) print("OVERRIDING {:s} to {:s}!!!!!".format(name, val))
output_files = []
# Output to XML file # Output to XML file
if args.xml: if args.xml:
if args.verbose: if args.verbose:
print("Creating XML file " + args.xml) print("Creating XML file " + args.xml)
out = xmlout.XMLOutput(param_groups, args.board) out = xmlout.XMLOutput(param_groups, args.board)
out.Save(args.xml) out.Save(args.xml)
output_files.append(args.xml)
# Output to Markdown/HTML tables # Output to Markdown/HTML tables
if args.markdown: if args.markdown:
out = markdownout.MarkdownTablesOutput(param_groups) if args.verbose:
if args.markdown:
print("Creating markdown file " + args.markdown) print("Creating markdown file " + args.markdown)
out.Save(args.markdown) out = markdownout.MarkdownTablesOutput(param_groups)
out.Save(args.markdown)
output_files.append(args.markdown)
#print("All done!") # Output to JSON file
if args.json:
if args.verbose:
print("Creating Json file " + args.json)
cur_dir = os.path.dirname(os.path.realpath(__file__))
out = jsonout.JsonOutput(param_groups, args.board,
os.path.join(cur_dir, args.inject_xml))
out.Save(args.json)
output_files.append(args.json)
if args.compress:
for f in output_files:
if args.verbose:
print("Compressing file " + f)
SaveCompressed(f)
if __name__ == "__main__": if __name__ == "__main__":