diff --git a/klippy/gcode.py b/klippy/gcode.py index a60c1555..fafa9476 100644 --- a/klippy/gcode.py +++ b/klippy/gcode.py @@ -9,15 +9,15 @@ import homing, extruder # Parse out incoming GCode and find and translate head movements class GCodeParser: RETRY_TIME = 0.100 - def __init__(self, printer, fd, is_fileinput=False): + def __init__(self, printer, fd): self.printer = printer self.fd = fd - self.is_fileinput = is_fileinput # Input handling self.reactor = printer.reactor self.is_processing_data = False + self.is_fileinput = not not printer.get_start_args().get("debuginput") self.fd_handle = None - if not is_fileinput: + if not self.is_fileinput: self.fd_handle = self.reactor.register_fd(self.fd, self.process_data) self.partial_input = "" self.bytes_read = 0 @@ -140,8 +140,7 @@ class GCodeParser: if not data and self.is_fileinput: self.motor_heater_off() if self.toolhead is not None: - if not self.printer.mcu.is_fileoutput(): - self.toolhead.wait_moves() + self.toolhead.wait_moves() self.printer.request_exit('exit_eof') self.is_processing_data = False if self.fd_handle is None: @@ -392,8 +391,8 @@ class GCodeParser: cmd_M115_when_not_ready = True def cmd_M115(self, params): # Get Firmware Version and Capabilities - kw = {"FIRMWARE_NAME": "Klipper" - , "FIRMWARE_VERSION": self.printer.software_version} + software_version = self.printer.get_start_args().get('software_version') + kw = {"FIRMWARE_NAME": "Klipper", "FIRMWARE_VERSION": software_version} self.ack(" ".join(["%s:%s" % (k, v) for k, v in kw.items()])) def cmd_M140(self, params): # Set Bed Temperature diff --git a/klippy/heater.py b/klippy/heater.py index 1b644e72..be8d7252 100644 --- a/klippy/heater.py +++ b/klippy/heater.py @@ -112,8 +112,8 @@ class PrinterHeater: self.min_extrude_temp = config.getfloat( 'min_extrude_temp', 170., minval=self.min_temp, maxval=self.max_temp) self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.) - self.can_extrude = (self.min_extrude_temp <= 0. - or printer.mcu.is_fileoutput()) + is_fileoutput = printer.get_start_args().get('debugoutput') is not None + self.can_extrude = self.min_extrude_temp <= 0. or is_fileoutput self.lock = threading.Lock() self.last_temp = 0. self.last_temp_time = 0. diff --git a/klippy/klippy.py b/klippy/klippy.py index 7e9bf6d8..61168609 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -123,30 +123,25 @@ class ConfigLogger(): self.lines.append(data.strip()) class Printer: - def __init__(self, conffile, input_fd, startup_state - , is_fileinput=False, version="?", bglogger=None): - self.conffile = conffile - self.startup_state = startup_state - self.software_version = version + def __init__(self, input_fd, bglogger, start_args): self.bglogger = bglogger + self.start_args = start_args if bglogger is not None: bglogger.set_rollover_info("config", None) self.reactor = reactor.Reactor() self.objects = {} - self.gcode = gcode.GCodeParser(self, input_fd, is_fileinput) + self.gcode = gcode.GCodeParser(self, input_fd) self.stats_timer = self.reactor.register_timer(self.stats) self.connect_timer = self.reactor.register_timer( self.connect, self.reactor.NOW) self.all_config_options = {} 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 - def set_fileoutput(self, debugoutput, dictionary): - self.debugoutput = debugoutput - self.dictionary = dictionary + def get_start_args(self): + return self.start_args def stats(self, eventtime, force_output=False): if self.need_dump_debug: # Call dump_debug here so it is executed in the main thread @@ -168,15 +163,14 @@ class Printer: self.objects[name] = obj def load_config(self): self.fileconfig = ConfigParser.RawConfigParser() - res = self.fileconfig.read(self.conffile) + config_file = self.start_args['config_file'] + res = self.fileconfig.read(config_file) if not res: raise ConfigParser.Error("Unable to open config file %s" % ( - self.conffile,)) + config_file,)) if self.bglogger is not None: ConfigLogger(self.fileconfig, self.bglogger) self.mcu = mcu.MCU(self, ConfigWrapper(self, 'mcu')) - if self.debugoutput is not None: - self.mcu.connect_file(self.debugoutput, self.dictionary) # Create printer components config = ConfigWrapper(self, 'printer') for m in [extruder, fan, heater, toolhead]: @@ -197,7 +191,7 @@ class Printer: def connect(self, eventtime): try: self.load_config() - if self.debugoutput is None: + if self.start_args.get('debugoutput') is None: self.reactor.update_timer(self.stats_timer, self.reactor.NOW) self.mcu.connect() self.gcode.set_printer_ready(True) @@ -259,8 +253,6 @@ class Printer: self.mcu.disconnect() except: logging.exception("Unhandled exception during firmware_restart") - def get_startup_state(self): - return self.startup_state def request_exit(self, result="exit"): self.run_result = result self.reactor.end() @@ -270,18 +262,10 @@ class Printer: # Startup ###################################################################### -def read_dictionary(filename): - dfile = open(filename, 'rb') - dictionary = dfile.read() - dfile.close() - return dictionary - def main(): usage = "%prog [options] " opts = optparse.OptionParser(usage) - opts.add_option("-o", "--debugoutput", dest="outputfile", - help="write output to file instead of to serial port") - opts.add_option("-i", "--debuginput", dest="inputfile", + opts.add_option("-i", "--debuginput", dest="debuginput", help="read commands from file instead of from tty port") opts.add_option("-I", "--input-tty", dest="inputtty", default='/tmp/printer', help="input tty name (default is /tmp/printer)") @@ -289,63 +273,60 @@ def main(): help="write log to file instead of stderr") opts.add_option("-v", action="store_true", dest="verbose", help="enable debug messages") - opts.add_option("-d", dest="read_dictionary", + opts.add_option("-o", "--debugoutput", dest="debugoutput", + help="write output to file instead of to serial port") + opts.add_option("-d", "--dictionary", dest="dictionary", help="file to read for mcu protocol dictionary") options, args = opts.parse_args() if len(args) != 1: opts.error("Incorrect number of arguments") - conffile = args[0] + start_args = {'config_file': args[0], 'start_reason': 'startup'} - input_fd = debuginput = debugoutput = bglogger = None + input_fd = bglogger = None debuglevel = logging.INFO if options.verbose: debuglevel = logging.DEBUG - if options.inputfile: - debuginput = open(options.inputfile, 'rb') + if options.debuginput: + start_args['debuginput'] = options.debuginput + debuginput = open(options.debuginput, 'rb') input_fd = debuginput.fileno() else: input_fd = util.create_pty(options.inputtty) - if options.outputfile: - debugoutput = open(options.outputfile, 'wb') + if options.debugoutput: + start_args['debugoutput'] = options.debugoutput + start_args['dictionary'] = options.dictionary if options.logfile: bglogger = queuelogger.setup_bg_logging(options.logfile, debuglevel) else: logging.basicConfig(level=debuglevel) logging.info("Starting Klippy...") - software_version = util.get_git_version() + start_args['software_version'] = util.get_git_version() if bglogger is not None: lines = ["Args: %s" % (sys.argv,), - "Git version: %s" % (repr(software_version),), + "Git version: %s" % (repr(start_args['software_version']),), "CPU: %s" % (util.get_cpu_info(),), "Python: %s" % (repr(sys.version),)] lines = "\n".join(lines) logging.info(lines) bglogger.set_rollover_info('versions', lines) - # Start firmware - res = 'startup' + # Start Printer() class while 1: - is_fileinput = debuginput is not None - printer = Printer( - conffile, input_fd, res, is_fileinput, software_version, bglogger) - if debugoutput: - proto_dict = read_dictionary(options.read_dictionary) - printer.set_fileoutput(debugoutput, proto_dict) + printer = Printer(input_fd, bglogger, start_args) res = printer.run() if res == 'restart': printer.disconnect() - time.sleep(1.) - logging.info("Restarting printer") - continue elif res == 'firmware_restart': printer.firmware_restart() - time.sleep(1.) - logging.info("Restarting printer") - continue elif res == 'exit_eof': printer.disconnect() - break + break + else: + break + time.sleep(1.) + logging.info("Restarting printer") + start_args['start_reason'] = res if bglogger is not None: bglogger.stop() diff --git a/klippy/mcu.py b/klippy/mcu.py index f4e3e861..aa35f76d 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -390,7 +390,6 @@ class MCU: printer.reactor, self._serialport, baud) self.is_shutdown = False self._shutdown_msg = "" - self._is_fileoutput = False self._timeout_timer = printer.reactor.register_timer( self.timeout_handler) rmethods = {m: m for m in ['arduino', 'command', 'rpi_usb']} @@ -442,14 +441,17 @@ class MCU: self._printer.note_shutdown(self._shutdown_msg) # Connection phase def _check_restart(self, reason): - if self._printer.get_startup_state() == 'firmware_restart': + start_reason = self._printer.get_start_args().get("start_reason") + if start_reason == 'firmware_restart': return logging.info("Attempting automated firmware restart: %s" % (reason,)) self._printer.request_exit('firmware_restart') self._printer.reactor.pause(self._printer.reactor.monotonic() + 2.000) raise error("Attempt firmware restart failed") def connect(self): - if not self._is_fileoutput: + if self.is_fileoutput(): + self._connect_file() + else: if (self._restart_method == 'rpi_usb' and not os.path.exists(self._serialport)): # Try toggling usb power @@ -470,9 +472,16 @@ class MCU: self.register_msg(self.handle_mcu_stats, 'stats') self._build_config() self._send_config() - def connect_file(self, debugoutput, dictionary, pace=False): - self._is_fileoutput = True - self.serial.connect_file(debugoutput, dictionary) + def _connect_file(self, pace=False): + # In a debugging mode. Open debug output file and read data dictionary + out_fname = self._printer.get_start_args().get('debugoutput') + outfile = open(out_fname, 'wb') + dict_fname = self._printer.get_start_args().get('dictionary') + dfile = open(dict_fname, 'rb') + dict_data = dfile.read() + dfile.close() + self.serial.connect_file(outfile, dict_data) + # Handle pacing if not pace: def dummy_set_print_start_time(eventtime): pass @@ -527,7 +536,7 @@ class MCU: self.disconnect() serialhdl.arduino_reset(self._serialport, reactor) def is_fileoutput(self): - return self._is_fileoutput + return self._printer.get_start_args().get('debugoutput') is not None # Configuration phase def _add_custom(self): for line in self._custom.split('\n'): @@ -564,7 +573,7 @@ class MCU: self.add_config_cmd("finalize_config crc=%d" % (self._config_crc,)) def _send_config(self): msg = self.create_command("get_config") - if self._is_fileoutput: + if self.is_fileoutput(): config_params = { 'is_config': 0, 'move_count': 500, 'crc': self._config_crc} else: @@ -577,15 +586,17 @@ class MCU: logging.info("Sending printer configuration...") for c in self._config_cmds: self.send(self.create_command(c)) - if not self._is_fileoutput: + if not self.is_fileoutput(): config_params = self.serial.send_with_response(msg, 'config') if not config_params['is_config']: if self.is_shutdown: raise error("Firmware error during config: %s" % ( self._shutdown_msg,)) raise error("Unable to configure printer") - elif self._printer.get_startup_state() == 'firmware_restart': - raise error("Failed automated reset of micro-controller") + else: + start_reason = self._printer.get_start_args().get("start_reason") + if start_reason == 'firmware_restart': + raise error("Failed automated reset of micro-controller") if self._config_crc != config_params['crc']: self._check_restart("CRC mismatch") raise error("Printer CRC does not match config") diff --git a/klippy/stepper.py b/klippy/stepper.py index 1b2841f4..f5085bc0 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -91,7 +91,7 @@ class PrinterHomingStepper(PrinterStepper): logging.info("Endstop for %s is not accurate enough for stepper" " phase adjustment" % (name,)) self.homing_stepper_phases = None - if printer.mcu.is_fileoutput(): + if printer.get_start_args().get('debugoutput') is not None: self.homing_endstop_accuracy = self.homing_stepper_phases def enable_endstop_checking(self, move_time, step_time): mcu_time = self.mcu_endstop.print_to_mcu_time(move_time) diff --git a/klippy/toolhead.py b/klippy/toolhead.py index ab064cfe..edb8f851 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -359,6 +359,8 @@ class ToolHead: logging.debug('; Max time of %f' % (last_move_time,)) def wait_moves(self): self._flush_lookahead() + if self.printer.get_start_args().get('debugoutput') is not None: + return eventtime = self.reactor.monotonic() while self.print_time: eventtime = self.reactor.pause(eventtime + 0.100)