From 6ccac4583be8a27ec36a39a9315b60979beed4d0 Mon Sep 17 00:00:00 2001 From: Chad Condon Date: Sat, 27 Jul 2024 12:52:51 -0700 Subject: [PATCH] Implement show_macros_in_webui --- autospeed/dummy_macros.cfg | 27 +++++++++++++++ autospeed/main.py | 71 +++++++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 24 deletions(-) create mode 100644 autospeed/dummy_macros.cfg diff --git a/autospeed/dummy_macros.cfg b/autospeed/dummy_macros.cfg new file mode 100644 index 0000000..13bc31d --- /dev/null +++ b/autospeed/dummy_macros.cfg @@ -0,0 +1,27 @@ +# This file is used when the `show_macros_in_webui` option is enabled. It wraps +# the native Python commands in macros so that they will show up in web UIs +# like Mainsail and Fluidd. + +[gcode_macro AUTO_SPEED] +gcode: _AUTO_SPEED {rawparams} + +[gcode_macro AUTO_SPEED_VELOCITY] +gcode: _AUTO_SPEED_VELOCITY {rawparams} + +[gcode_macro AUTO_SPEED_ACCEL] +gcode: _AUTO_SPEED_ACCEL {rawparams} + +[gcode_macro AUTO_SPEED_VALIDATE] +gcode: _AUTO_SPEED_VALIDATE {rawparams} + +[gcode_macro AUTO_SPEED_GRAPH] +gcode: _AUTO_SPEED_GRAPH + +[gcode_macro X_ENDSTOP_ACCURACY] +gcode: _X_ENDSTOP_ACCURACY {rawparams} + +[gcode_macro Y_ENDSTOP_ACCURACY] +gcode: _Y_ENDSTOP_ACCURACY {rawparams} + +[gcode_macro Z_ENDSTOP_ACCURACY] +gcode: _Z_ENDSTOP_ACCURACY {rawparams} diff --git a/autospeed/main.py b/autospeed/main.py index 61132cd..f5f667b 100644 --- a/autospeed/main.py +++ b/autospeed/main.py @@ -52,6 +52,8 @@ def __init__(self, config): self.validate_iterations = config.getint( 'validate_iterations', default=50, minval=1) results_default = os.path.expanduser('~') + show_macros = config.getboolean('show_macros_in_webui', default=False) + for path in ( # Could be problematic if neither of these paths work os.path.dirname(self.printer.start_args['log_file']), os.path.expanduser('~/printer_data/config'), @@ -64,30 +66,51 @@ def __init__(self, config): self.printer.register_event_handler("klippy:connect", self.handle_connect) self.printer.register_event_handler("homing:home_rails_end", self.handle_home_rails_end) - self.gcode.register_command('AUTO_SPEED', - self.cmd_AUTO_SPEED, - desc=self.cmd_AUTO_SPEED_help) - self.gcode.register_command('AUTO_SPEED_VELOCITY', - self.cmd_AUTO_SPEED_VELOCITY, - desc=self.cmd_AUTO_SPEED_VELOCITY_help) - self.gcode.register_command('AUTO_SPEED_ACCEL', - self.cmd_AUTO_SPEED_ACCEL, - desc=self.cmd_AUTO_SPEED_ACCEL_help) - self.gcode.register_command('AUTO_SPEED_VALIDATE', - self.cmd_AUTO_SPEED_VALIDATE, - desc=self.cmd_AUTO_SPEED_VALIDATE_help) - self.gcode.register_command('AUTO_SPEED_GRAPH', - self.cmd_AUTO_SPEED_GRAPH, - desc=self.cmd_AUTO_SPEED_GRAPH_help) - self.gcode.register_command('X_ENDSTOP_ACCURACY', - self.cmd_X_ENDSTOP_ACCURACY, - desc=self.cmd_AUTO_SPEED_GRAPH_help) - self.gcode.register_command('Y_ENDSTOP_ACCURACY', - self.cmd_Y_ENDSTOP_ACCURACY, - desc=self.cmd_AUTO_SPEED_GRAPH_help) - self.gcode.register_command('Z_ENDSTOP_ACCURACY', - self.cmd_Z_ENDSTOP_ACCURACY, - desc=self.cmd_AUTO_SPEED_GRAPH_help) + measurement_commands = [ + ('AUTO_SPEED', self.cmd_AUTO_SPEED, self.cmd_AUTO_SPEED_help), + ('AUTO_SPEED_VELOCITY', self.cmd_AUTO_SPEED_VELOCITY, self.cmd_AUTO_SPEED_VELOCITY_help), + ('AUTO_SPEED_ACCEL', self.cmd_AUTO_SPEED_ACCEL, self.cmd_AUTO_SPEED_ACCEL_help), + ('AUTO_SPEED_VALIDATE', self.cmd_AUTO_SPEED_VALIDATE, self.cmd_AUTO_SPEED_VALIDATE_help), + ('AUTO_SPEED_GRAPH', self.cmd_AUTO_SPEED_GRAPH, self.cmd_AUTO_SPEED_GRAPH_help), + ('X_ENDSTOP_ACCURACY', self.cmd_X_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help), + ('Y_ENDSTOP_ACCURACY', self.cmd_Y_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help), + ('Z_ENDSTOP_ACCURACY', self.cmd_Z_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help), + ] + command_descriptions = {name: desc for name, _, desc in measurement_commands} + gcode = self.printer.lookup_object('gcode') + for name, command, description in measurement_commands: + gcode.register_command(f'_{name}' if show_macros else name, command, desc=description) + + # Load the dummy macros with their description in order to show them in the web interfaces + if show_macros: + pconfig = self.printer.lookup_object('configfile') + dirname = os.path.dirname(os.path.realpath(__file__)) + filename = os.path.join(dirname, 'dummy_macros.cfg') + try: + dummy_macros_cfg = pconfig.read_config(filename) + except Exception as err: + raise config.error(f'Cannot load AutoSpeed dummy macro {filename}') from err + + for gcode_macro in dummy_macros_cfg.get_prefix_sections('gcode_macro '): + gcode_macro_name = gcode_macro.get_name() + + # Replace the dummy description by the one here (to avoid code duplication and define it in only one place) + command = gcode_macro_name.split(' ', 1)[1] + description = command_descriptions.get(command, 'AutoSpeed macro') + gcode_macro.fileconfig.set(gcode_macro_name, 'description', description) + + # Add the section to the Klipper configuration object with all its options + if not config.fileconfig.has_section(gcode_macro_name.lower()): + config.fileconfig.add_section(gcode_macro_name.lower()) + for option in gcode_macro.fileconfig.options(gcode_macro_name): + value = gcode_macro.fileconfig.get(gcode_macro_name, option) + config.fileconfig.set(gcode_macro_name.lower(), option, value) + + # Small trick to ensure the new injected sections are considered valid by Klipper config system + config.access_tracking[(gcode_macro_name.lower(), option.lower())] = 1 + + # Finally, load the section within the printer objects + self.printer.load_object(config, gcode_macro_name.lower()) self.level = None