From fbd7cc243ba49b7e8ab0b435e319cf133dea5224 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Wed, 30 Nov 2016 23:47:40 -0500 Subject: [PATCH] klippy: Add ability to restart the host software Add a "restart" gcode command that will cause the host "klippy" software to reload its config and restart. Signed-off-by: Kevin O'Connor --- klippy/gcode.py | 16 +++++++++------- klippy/klippy.py | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/klippy/gcode.py b/klippy/gcode.py index d2235979..0f4bc603 100644 --- a/klippy/gcode.py +++ b/klippy/gcode.py @@ -47,7 +47,7 @@ class GCodeParser: def build_handlers(self): handlers = ['G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92', 'M18', 'M82', 'M83', 'M105', 'M110', 'M114', 'M206', - 'HELP', 'QUERY_ENDSTOPS'] + 'HELP', 'QUERY_ENDSTOPS', 'RESTART'] if self.heater_nozzle is not None: handlers.extend(['M104', 'M109', 'PID_TUNE']) if self.heater_bed is not None: @@ -62,10 +62,6 @@ class GCodeParser: for h, f in self.gcode_handlers.items(): aliases = getattr(self, 'cmd_'+h+'_aliases', []) self.gcode_handlers.update(dict([(a, f) for a in aliases])) - def finish(self): - self.reactor.end() - self.toolhead.motor_off() - logging.debug('Completed translation by klippy') def stats(self, eventtime): return "gcodein=%d" % (self.bytes_read,) def set_printer_ready(self, is_ready): @@ -75,7 +71,7 @@ class GCodeParser: self.build_handlers() if is_ready and self.is_fileinput and self.fd_handle is None: self.fd_handle = self.reactor.register_fd(self.fd, self.process_data) - def note_mcu_error(self): + def motor_heater_off(self): if self.toolhead is not None: self.toolhead.motor_off() if self.heater_nozzle is not None: @@ -140,7 +136,8 @@ class GCodeParser: self.input_commands = lines self.process_commands(eventtime) if not data and self.is_fileinput: - self.finish() + self.motor_heater_off() + self.printer.request_exit_eof() # Response handling def ack(self, msg=None): if not self.need_ack or self.is_fileinput: @@ -370,6 +367,11 @@ class GCodeParser: temp = float(params.get('S', '60')) heater.start_auto_tune(temp) self.bg_temp(heater) + cmd_RESTART_when_not_ready = True + cmd_RESTART_help = "Reload config file and restart host software" + def cmd_RESTART(self, params): + self.printer.request_restart() + cmd_HELP_when_not_ready = True def cmd_HELP(self, params): cmdhelp = ["// Available extended commands:"] for cmd in self.gcode_handlers: diff --git a/klippy/klippy.py b/klippy/klippy.py index 25f6b99b..2787a6aa 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -14,9 +14,8 @@ Printer is not ready """ message_restart = """ -This is an unrecoverable error. Please correct the -underlying issue and then manually restart the klippy host -software. +Once the underlying issue is corrected, use the "RESTART" +command to reload the config and restart the host software. Printer is halted """ @@ -85,6 +84,7 @@ class Printer: self.need_dump_debug = False self.state_message = message_startup self.debugoutput = self.dictionary = None + self.run_result = None self.fileconfig = None self.mcu = None self.objects = {} @@ -172,10 +172,7 @@ class Printer: except: logging.exception("Unhandled exception during run") return - # If gcode exits, then exit the MCU - self.stats(time.time()) - self.mcu.disconnect() - self.stats(time.time()) + return self.run_result def get_state_message(self): return self.state_message def note_shutdown(self, msg): @@ -187,7 +184,17 @@ class Printer: def note_mcu_error(self, msg): self.state_message = "%s%s" % (msg, message_restart) self.gcode.set_printer_ready(False) - self.gcode.note_mcu_error() + self.gcode.motor_heater_off() + def disconnect(self): + if self.mcu is not None: + self.stats(time.time()) + self.mcu.disconnect() + def request_restart(self): + self.run_result = "restart" + self.reactor.end() + def request_exit_eof(self): + self.run_result = "exit_eof" + self.reactor.end() ###################################################################### @@ -239,11 +246,21 @@ def main(): logging.info("Starting Klippy...") # Start firmware - printer = Printer(conffile, input_fd, is_fileinput=debuginput is not None) - if debugoutput: - proto_dict = read_dictionary(options.read_dictionary) - printer.set_fileoutput(debugoutput, proto_dict) - printer.run() + while 1: + is_fileinput = debuginput is not None + printer = Printer(conffile, input_fd, is_fileinput) + if debugoutput: + proto_dict = read_dictionary(options.read_dictionary) + printer.set_fileoutput(debugoutput, proto_dict) + res = printer.run() + if res == 'restart': + printer.disconnect() + time.sleep(1.) + logging.info("Restarting printer") + continue + elif res == 'eof_stats': + printer.disconnect() + break if bglogger is not None: bglogger.stop()