implement JSON to C++ header dump tool

This commit is contained in:
Samuel Sadok
2018-04-24 18:08:07 -07:00
parent c24ae83638
commit b2fed7c64c
4 changed files with 102 additions and 1 deletions
+5 -1
View File
@@ -53,7 +53,7 @@ def find_all(path, serial_number,
except UnicodeDecodeError:
printer("device responded on endpoint 0 with something that is not ASCII")
return
printer("JSON: " + json_string)
printer("JSON: " + json_string.replace('{"name"', '\n{"name"'))
printer("JSON checksum: 0x{:02X} 0x{:02X}".format(json_crc16 & 0xff, (json_crc16 >> 8) & 0xff))
try:
json_data = json.loads(json_string)
@@ -62,6 +62,10 @@ def find_all(path, serial_number,
return
json_data = {"name": "odrive", "members": json_data}
obj = odrive.remote_object.RemoteObject(json_data, None, channel, printer)
obj.__dict__['_json_data'] = json_data['members']
obj.__dict__['_json_crc'] = json_crc16
device_serial_number = format(obj.serial_number, 'x').upper() if hasattr(obj, 'serial_number') else "[unknown serial number]"
if serial_number != None and device_serial_number != serial_number:
printer("Ignoring device with serial number {}".format(device_serial_number))
+49
View File
@@ -0,0 +1,49 @@
import jinja2
import os
import json
def get_flat_endpoint_list(json, prefix):
flat_list = []
for item in json:
item = item.copy()
if 'type' in item:
if item['type'] in {'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'}:
item['type'] += '_t'
is_property = True
elif item['type'] in {'bool', 'float'}:
is_property = True
else:
is_property = False
if is_property:
item['name'] = prefix + item['name']
flat_list.append(item)
if 'members' in item:
flat_list = flat_list + get_flat_endpoint_list(item['members'], prefix + item['name'] + '.')
return flat_list
def generate_header(odrv, template_file, output_file):
json_data = odrv._json_data
json_crc = odrv._json_crc
endpoints = get_flat_endpoint_list(json_data, '')
env = jinja2.Environment(
#loader = jinja2.FileSystemLoader("/Data/Projects/")
#trim_blocks=True,
#lstrip_blocks=True
)
# Expose helper functions to jinja template code
#env.filters["delimit"] = camel_case_to_words
# Load and render template
template = env.from_string(template_file.read())
output = template.render(
json_crc=json_crc,
endpoints=endpoints,
output_name=os.path.basename(output_file.name)
)
# Output
output_file.write(output)
+34
View File
@@ -0,0 +1,34 @@
/*
* This file was autogenerated using the "odrivetool process-template" feature.
*
* The file matches a specific firmware version. If you add/remove/rename any
* properties exposed by the ODrive, this file needs to be regenerated, otherwise
* the ODrive will ignore all commands.
*/
#ifndef __ODRIVE_ENDPOINTS_HPP
#define __ODRIVE_ENDPOINTS_HPP
{% macro enum_name(endpoint) %}{{ endpoint.name | replace('.', '__') | upper }}{% endmacro %}
namespace odrive {
static constexpr const uint16_t json_crc = 0x{{ "%0x" | format(json_crc) }};
enum { {% for endpoint in endpoints %}
{{enum_name(endpoint)}} = {{endpoint.id}},
{%- endfor %}
};
template<int I>
struct endpoint_type;
{% for endpoint in endpoints -%}
template<> struct endpoint_type<{{enum_name(endpoint)}}> { typedef {{endpoint.type}} type; };
{% endfor %}
template<int I>
using endpoint_type_t = typename endpoint_type<I>::type;
}
#endif __ODRIVE_ENDPOINTS_HPP
+14
View File
@@ -6,6 +6,7 @@ ODrive command line utility
from __future__ import print_function
import sys
import argparse
import os
import odrive.discovery
from odrive.utils import Logger, Event
@@ -19,6 +20,7 @@ def print(*args, **kwargs):
file = kwargs.get('file', sys.stdout)
file.flush() if file is not None else sys.stdout.flush()
script_path=os.path.dirname(os.path.realpath(__file__))
## Parse arguments ##
parser = argparse.ArgumentParser(description='ODrive command line utility\n'
@@ -36,6 +38,13 @@ shell_parser.add_argument("--no-ipython", action="store_true",
dfu_parser = subparsers.add_parser('dfu', help="Upgrade the ODrive device firmware")
dfu_parser.add_argument('file', metavar='HEX', help='The .hex file to be flashed. Make sure your firmware board version matches the actual board version.')
template_processor_parser = subparsers.add_parser('process-template', help="Process a jinja2 template, passing the ODrive's JSON data as data input")
template_processor_parser.add_argument("-t", "--template", type=argparse.FileType('r'),
help="the code template")
template_processor_parser.add_argument("-o", "--output", type=argparse.FileType('w'), default='-',
help="path of the generated output")
template_processor_parser.set_defaults(template = os.path.join(script_path, 'odrive_header_template.h.in'))
subparsers.add_parser('liveplotter', help="Upgrade the ODrive's Firmware")
subparsers.add_parser('drv-status', help="Show status of the on-board DRV8301 chips (for debugging only)")
subparsers.add_parser('rate-test', help="Estimate the average transmission bandwidth over USB")
@@ -138,6 +147,11 @@ try:
elif args.command == 'udev-setup':
from odrive.utils import setup_udev_rules
setup_udev_rules(logger)
elif args.command == 'process-template':
from odrive.template_processor import generate_header
my_odrive = odrive.discovery.find_any(path=args.path, serial_number=args.serial_number)
generate_header(my_odrive, args.template, args.output)
else:
raise Exception("unknown command: " + args.command)