mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-08-20 22:14:34 +08:00
implement JSON to C++ header dump tool
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user