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 <kevin@koconnor.net>
This commit is contained in:
parent
a6055ce069
commit
fbd7cc243b
|
@ -47,7 +47,7 @@ class GCodeParser:
|
||||||
def build_handlers(self):
|
def build_handlers(self):
|
||||||
handlers = ['G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
handlers = ['G1', 'G4', 'G20', 'G21', 'G28', 'G90', 'G91', 'G92',
|
||||||
'M18', 'M82', 'M83', 'M105', 'M110', 'M114', 'M206',
|
'M18', 'M82', 'M83', 'M105', 'M110', 'M114', 'M206',
|
||||||
'HELP', 'QUERY_ENDSTOPS']
|
'HELP', 'QUERY_ENDSTOPS', 'RESTART']
|
||||||
if self.heater_nozzle is not None:
|
if self.heater_nozzle is not None:
|
||||||
handlers.extend(['M104', 'M109', 'PID_TUNE'])
|
handlers.extend(['M104', 'M109', 'PID_TUNE'])
|
||||||
if self.heater_bed is not None:
|
if self.heater_bed is not None:
|
||||||
|
@ -62,10 +62,6 @@ class GCodeParser:
|
||||||
for h, f in self.gcode_handlers.items():
|
for h, f in self.gcode_handlers.items():
|
||||||
aliases = getattr(self, 'cmd_'+h+'_aliases', [])
|
aliases = getattr(self, 'cmd_'+h+'_aliases', [])
|
||||||
self.gcode_handlers.update(dict([(a, f) for a in 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):
|
def stats(self, eventtime):
|
||||||
return "gcodein=%d" % (self.bytes_read,)
|
return "gcodein=%d" % (self.bytes_read,)
|
||||||
def set_printer_ready(self, is_ready):
|
def set_printer_ready(self, is_ready):
|
||||||
|
@ -75,7 +71,7 @@ class GCodeParser:
|
||||||
self.build_handlers()
|
self.build_handlers()
|
||||||
if is_ready and self.is_fileinput and self.fd_handle is None:
|
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)
|
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:
|
if self.toolhead is not None:
|
||||||
self.toolhead.motor_off()
|
self.toolhead.motor_off()
|
||||||
if self.heater_nozzle is not None:
|
if self.heater_nozzle is not None:
|
||||||
|
@ -140,7 +136,8 @@ class GCodeParser:
|
||||||
self.input_commands = lines
|
self.input_commands = lines
|
||||||
self.process_commands(eventtime)
|
self.process_commands(eventtime)
|
||||||
if not data and self.is_fileinput:
|
if not data and self.is_fileinput:
|
||||||
self.finish()
|
self.motor_heater_off()
|
||||||
|
self.printer.request_exit_eof()
|
||||||
# Response handling
|
# Response handling
|
||||||
def ack(self, msg=None):
|
def ack(self, msg=None):
|
||||||
if not self.need_ack or self.is_fileinput:
|
if not self.need_ack or self.is_fileinput:
|
||||||
|
@ -370,6 +367,11 @@ class GCodeParser:
|
||||||
temp = float(params.get('S', '60'))
|
temp = float(params.get('S', '60'))
|
||||||
heater.start_auto_tune(temp)
|
heater.start_auto_tune(temp)
|
||||||
self.bg_temp(heater)
|
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):
|
def cmd_HELP(self, params):
|
||||||
cmdhelp = ["// Available extended commands:"]
|
cmdhelp = ["// Available extended commands:"]
|
||||||
for cmd in self.gcode_handlers:
|
for cmd in self.gcode_handlers:
|
||||||
|
|
|
@ -14,9 +14,8 @@ Printer is not ready
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message_restart = """
|
message_restart = """
|
||||||
This is an unrecoverable error. Please correct the
|
Once the underlying issue is corrected, use the "RESTART"
|
||||||
underlying issue and then manually restart the klippy host
|
command to reload the config and restart the host software.
|
||||||
software.
|
|
||||||
Printer is halted
|
Printer is halted
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -85,6 +84,7 @@ class Printer:
|
||||||
self.need_dump_debug = False
|
self.need_dump_debug = False
|
||||||
self.state_message = message_startup
|
self.state_message = message_startup
|
||||||
self.debugoutput = self.dictionary = None
|
self.debugoutput = self.dictionary = None
|
||||||
|
self.run_result = None
|
||||||
self.fileconfig = None
|
self.fileconfig = None
|
||||||
self.mcu = None
|
self.mcu = None
|
||||||
self.objects = {}
|
self.objects = {}
|
||||||
|
@ -172,10 +172,7 @@ class Printer:
|
||||||
except:
|
except:
|
||||||
logging.exception("Unhandled exception during run")
|
logging.exception("Unhandled exception during run")
|
||||||
return
|
return
|
||||||
# If gcode exits, then exit the MCU
|
return self.run_result
|
||||||
self.stats(time.time())
|
|
||||||
self.mcu.disconnect()
|
|
||||||
self.stats(time.time())
|
|
||||||
def get_state_message(self):
|
def get_state_message(self):
|
||||||
return self.state_message
|
return self.state_message
|
||||||
def note_shutdown(self, msg):
|
def note_shutdown(self, msg):
|
||||||
|
@ -187,7 +184,17 @@ class Printer:
|
||||||
def note_mcu_error(self, msg):
|
def note_mcu_error(self, msg):
|
||||||
self.state_message = "%s%s" % (msg, message_restart)
|
self.state_message = "%s%s" % (msg, message_restart)
|
||||||
self.gcode.set_printer_ready(False)
|
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...")
|
logging.info("Starting Klippy...")
|
||||||
|
|
||||||
# Start firmware
|
# Start firmware
|
||||||
printer = Printer(conffile, input_fd, is_fileinput=debuginput is not None)
|
while 1:
|
||||||
if debugoutput:
|
is_fileinput = debuginput is not None
|
||||||
proto_dict = read_dictionary(options.read_dictionary)
|
printer = Printer(conffile, input_fd, is_fileinput)
|
||||||
printer.set_fileoutput(debugoutput, proto_dict)
|
if debugoutput:
|
||||||
printer.run()
|
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:
|
if bglogger is not None:
|
||||||
bglogger.stop()
|
bglogger.stop()
|
||||||
|
|
Loading…
Reference in New Issue