2017-06-28 03:23:30 +03:00
|
|
|
#!/usr/bin/env python2
|
2016-05-25 18:37:40 +03:00
|
|
|
# Main code for host side printer firmware
|
|
|
|
#
|
2020-09-17 04:42:24 +03:00
|
|
|
# Copyright (C) 2016-2020 Kevin O'Connor <kevin@koconnor.net>
|
2016-05-25 18:37:40 +03:00
|
|
|
#
|
|
|
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
2020-10-30 20:02:44 +03:00
|
|
|
import sys, os, gc, optparse, logging, time, collections, importlib
|
2021-01-08 20:07:45 +03:00
|
|
|
import util, reactor, queuelogger, msgproto
|
2020-06-19 13:18:58 +03:00
|
|
|
import gcode, configfile, pins, mcu, toolhead, webhooks
|
2016-05-25 18:37:40 +03:00
|
|
|
|
2017-02-12 06:21:55 +03:00
|
|
|
message_ready = "Printer is ready"
|
|
|
|
|
2016-11-30 22:30:45 +03:00
|
|
|
message_startup = """
|
2018-03-13 06:12:39 +03:00
|
|
|
Printer is not ready
|
2016-11-30 22:30:45 +03:00
|
|
|
The klippy host software is attempting to connect. Please
|
|
|
|
retry in a few moments.
|
|
|
|
"""
|
|
|
|
|
|
|
|
message_restart = """
|
2016-12-01 07:47:40 +03:00
|
|
|
Once the underlying issue is corrected, use the "RESTART"
|
|
|
|
command to reload the config and restart the host software.
|
2016-11-30 22:30:45 +03:00
|
|
|
Printer is halted
|
|
|
|
"""
|
|
|
|
|
2021-05-03 00:39:58 +03:00
|
|
|
message_protocol_error1 = """
|
2017-01-10 07:50:13 +03:00
|
|
|
This type of error is frequently caused by running an older
|
|
|
|
version of the firmware on the micro-controller (fix by
|
|
|
|
recompiling and flashing the firmware).
|
2021-05-03 00:39:58 +03:00
|
|
|
"""
|
|
|
|
message_protocol_error2 = """
|
2017-01-10 07:50:13 +03:00
|
|
|
Once the underlying issue is corrected, use the "RESTART"
|
|
|
|
command to reload the config and restart the host software.
|
|
|
|
Protocol error connecting to printer
|
|
|
|
"""
|
|
|
|
|
2016-11-30 22:30:45 +03:00
|
|
|
message_mcu_connect_error = """
|
2017-03-09 06:26:10 +03:00
|
|
|
Once the underlying issue is corrected, use the
|
|
|
|
"FIRMWARE_RESTART" command to reset the firmware, reload the
|
|
|
|
config, and restart the host software.
|
2016-11-30 22:30:45 +03:00
|
|
|
Error configuring printer
|
|
|
|
"""
|
|
|
|
|
|
|
|
message_shutdown = """
|
2017-04-13 21:53:41 +03:00
|
|
|
Once the underlying issue is corrected, use the
|
|
|
|
"FIRMWARE_RESTART" command to reset the firmware, reload the
|
|
|
|
config, and restart the host software.
|
2016-11-30 22:30:45 +03:00
|
|
|
Printer is shutdown
|
|
|
|
"""
|
|
|
|
|
2016-05-25 18:37:40 +03:00
|
|
|
class Printer:
|
2018-09-05 03:49:47 +03:00
|
|
|
config_error = configfile.error
|
2021-01-08 20:07:45 +03:00
|
|
|
command_error = gcode.CommandError
|
2020-09-16 19:15:19 +03:00
|
|
|
def __init__(self, main_reactor, bglogger, start_args):
|
2017-05-01 20:44:06 +03:00
|
|
|
self.bglogger = bglogger
|
2017-08-22 00:19:43 +03:00
|
|
|
self.start_args = start_args
|
2020-09-16 19:15:19 +03:00
|
|
|
self.reactor = main_reactor
|
2018-09-02 19:43:40 +03:00
|
|
|
self.reactor.register_callback(self._connect)
|
2016-11-30 22:30:45 +03:00
|
|
|
self.state_message = message_startup
|
2020-04-25 19:41:44 +03:00
|
|
|
self.in_shutdown_state = False
|
2016-12-01 07:47:40 +03:00
|
|
|
self.run_result = None
|
2018-10-07 19:22:10 +03:00
|
|
|
self.event_handlers = {}
|
2020-06-19 13:18:58 +03:00
|
|
|
self.objects = collections.OrderedDict()
|
2020-08-04 23:00:23 +03:00
|
|
|
# Init printer components that must be setup prior to config
|
2020-08-12 04:21:41 +03:00
|
|
|
for m in [gcode, webhooks]:
|
2020-08-04 23:00:23 +03:00
|
|
|
m.add_early_printer_objects(self)
|
2017-08-22 00:19:43 +03:00
|
|
|
def get_start_args(self):
|
|
|
|
return self.start_args
|
2018-01-20 06:22:17 +03:00
|
|
|
def get_reactor(self):
|
|
|
|
return self.reactor
|
|
|
|
def get_state_message(self):
|
2020-06-23 14:56:50 +03:00
|
|
|
if self.state_message == message_ready:
|
|
|
|
category = "ready"
|
|
|
|
elif self.state_message == message_startup:
|
|
|
|
category = "startup"
|
2020-08-16 21:08:38 +03:00
|
|
|
elif self.in_shutdown_state:
|
|
|
|
category = "shutdown"
|
2020-06-23 14:56:50 +03:00
|
|
|
else:
|
|
|
|
category = "error"
|
|
|
|
return self.state_message, category
|
2020-04-25 19:41:44 +03:00
|
|
|
def is_shutdown(self):
|
|
|
|
return self.in_shutdown_state
|
2018-06-16 22:15:17 +03:00
|
|
|
def _set_state(self, msg):
|
2019-01-11 20:36:09 +03:00
|
|
|
if self.state_message in (message_ready, message_startup):
|
|
|
|
self.state_message = msg
|
2018-06-16 22:15:17 +03:00
|
|
|
if (msg != message_ready
|
|
|
|
and self.start_args.get('debuginput') is not None):
|
|
|
|
self.request_exit('error_exit')
|
2018-01-20 06:22:17 +03:00
|
|
|
def add_object(self, name, obj):
|
2021-03-05 21:59:20 +03:00
|
|
|
if name in self.objects:
|
2018-01-20 06:22:17 +03:00
|
|
|
raise self.config_error(
|
|
|
|
"Printer object '%s' already created" % (name,))
|
|
|
|
self.objects[name] = obj
|
2018-09-05 03:49:47 +03:00
|
|
|
def lookup_object(self, name, default=configfile.sentinel):
|
2018-01-20 06:22:17 +03:00
|
|
|
if name in self.objects:
|
|
|
|
return self.objects[name]
|
2018-09-05 03:49:47 +03:00
|
|
|
if default is configfile.sentinel:
|
2018-01-20 06:22:17 +03:00
|
|
|
raise self.config_error("Unknown config object '%s'" % (name,))
|
|
|
|
return default
|
2018-09-02 19:51:37 +03:00
|
|
|
def lookup_objects(self, module=None):
|
|
|
|
if module is None:
|
|
|
|
return list(self.objects.items())
|
|
|
|
prefix = module + ' '
|
|
|
|
objs = [(n, self.objects[n])
|
|
|
|
for n in self.objects if n.startswith(prefix)]
|
|
|
|
if module in self.objects:
|
|
|
|
return [(module, self.objects[module])] + objs
|
2018-01-20 06:22:17 +03:00
|
|
|
return objs
|
2020-05-05 21:10:30 +03:00
|
|
|
def load_object(self, config, section, default=configfile.sentinel):
|
2018-01-20 05:25:58 +03:00
|
|
|
if section in self.objects:
|
2018-06-14 19:00:55 +03:00
|
|
|
return self.objects[section]
|
2018-02-03 20:53:11 +03:00
|
|
|
module_parts = section.split()
|
|
|
|
module_name = module_parts[0]
|
2018-01-20 05:25:58 +03:00
|
|
|
py_name = os.path.join(os.path.dirname(__file__),
|
|
|
|
'extras', module_name + '.py')
|
2018-06-27 20:01:48 +03:00
|
|
|
py_dirname = os.path.join(os.path.dirname(__file__),
|
|
|
|
'extras', module_name, '__init__.py')
|
|
|
|
if not os.path.exists(py_name) and not os.path.exists(py_dirname):
|
2020-05-05 21:10:30 +03:00
|
|
|
if default is not configfile.sentinel:
|
|
|
|
return default
|
|
|
|
raise self.config_error("Unable to load module '%s'" % (section,))
|
2018-01-20 05:25:58 +03:00
|
|
|
mod = importlib.import_module('extras.' + module_name)
|
2018-02-03 20:53:11 +03:00
|
|
|
init_func = 'load_config'
|
|
|
|
if len(module_parts) > 1:
|
|
|
|
init_func = 'load_config_prefix'
|
|
|
|
init_func = getattr(mod, init_func, None)
|
2020-05-05 21:10:30 +03:00
|
|
|
if init_func is None:
|
|
|
|
if default is not configfile.sentinel:
|
|
|
|
return default
|
|
|
|
raise self.config_error("Unable to load module '%s'" % (section,))
|
|
|
|
self.objects[section] = init_func(config.getsection(section))
|
|
|
|
return self.objects[section]
|
2018-02-03 20:17:42 +03:00
|
|
|
def _read_config(self):
|
2018-09-05 03:49:47 +03:00
|
|
|
self.objects['configfile'] = pconfig = configfile.PrinterConfig(self)
|
|
|
|
config = pconfig.read_main_config()
|
2017-05-01 20:44:06 +03:00
|
|
|
if self.bglogger is not None:
|
2018-09-05 03:49:47 +03:00
|
|
|
pconfig.log_config(config)
|
2017-04-29 20:57:02 +03:00
|
|
|
# Create printer components
|
2020-04-25 20:27:41 +03:00
|
|
|
for m in [pins, mcu]:
|
2018-07-13 05:26:32 +03:00
|
|
|
m.add_printer_objects(config)
|
2018-09-05 03:49:47 +03:00
|
|
|
for section_config in config.get_prefix_sections(''):
|
2020-05-05 21:10:30 +03:00
|
|
|
self.load_object(config, section_config.get_name(), None)
|
2018-07-13 05:15:45 +03:00
|
|
|
for m in [toolhead]:
|
2018-07-13 05:26:32 +03:00
|
|
|
m.add_printer_objects(config)
|
2017-03-13 05:43:05 +03:00
|
|
|
# Validate that there are no undefined parameters in the config file
|
2018-09-05 03:49:47 +03:00
|
|
|
pconfig.check_unused_options(config)
|
2021-05-03 00:39:58 +03:00
|
|
|
def _get_versions(self):
|
|
|
|
try:
|
|
|
|
parts = ["%s=%s" % (n.split()[-1], m.get_status()['mcu_version'])
|
|
|
|
for n, m in self.lookup_objects('mcu')]
|
|
|
|
parts.insert(0, "host=%s" % (self.start_args['software_version'],))
|
|
|
|
return "\nKnown versions: %s\n" % (", ".join(parts),)
|
|
|
|
except:
|
|
|
|
logging.exception("Error in _get_versions()")
|
|
|
|
return ""
|
2017-08-26 07:13:36 +03:00
|
|
|
def _connect(self, eventtime):
|
2016-11-30 22:30:45 +03:00
|
|
|
try:
|
2018-02-03 20:17:42 +03:00
|
|
|
self._read_config()
|
2019-11-05 07:00:00 +03:00
|
|
|
self.send_event("klippy:mcu_identify")
|
2019-01-08 19:09:55 +03:00
|
|
|
for cb in self.event_handlers.get("klippy:connect", []):
|
2018-01-20 06:49:27 +03:00
|
|
|
if self.state_message is not message_startup:
|
2018-10-18 19:49:26 +03:00
|
|
|
return
|
2019-01-08 19:09:55 +03:00
|
|
|
cb()
|
2017-09-06 21:51:47 +03:00
|
|
|
except (self.config_error, pins.error) as e:
|
2016-11-30 22:57:18 +03:00
|
|
|
logging.exception("Config error")
|
2021-06-11 04:30:09 +03:00
|
|
|
self._set_state("%s\n%s" % (str(e), message_restart))
|
2019-01-08 21:46:26 +03:00
|
|
|
return
|
2017-06-10 06:32:49 +03:00
|
|
|
except msgproto.error as e:
|
2017-01-10 07:50:13 +03:00
|
|
|
logging.exception("Protocol error")
|
2021-06-11 04:30:09 +03:00
|
|
|
self._set_state("%s\n%s%s%s" % (str(e), message_protocol_error1,
|
2021-05-03 00:39:58 +03:00
|
|
|
self._get_versions(),
|
|
|
|
message_protocol_error2))
|
2020-03-22 20:20:07 +03:00
|
|
|
util.dump_mcu_build()
|
2019-01-08 21:46:26 +03:00
|
|
|
return
|
2017-06-10 06:32:49 +03:00
|
|
|
except mcu.error as e:
|
2016-11-30 22:30:45 +03:00
|
|
|
logging.exception("MCU error during connect")
|
2018-06-16 22:15:17 +03:00
|
|
|
self._set_state("%s%s" % (str(e), message_mcu_connect_error))
|
2020-03-22 20:20:07 +03:00
|
|
|
util.dump_mcu_build()
|
2019-01-08 21:46:26 +03:00
|
|
|
return
|
2019-04-05 01:37:20 +03:00
|
|
|
except Exception as e:
|
2016-11-30 22:30:45 +03:00
|
|
|
logging.exception("Unhandled exception during connect")
|
2020-09-17 08:59:18 +03:00
|
|
|
self._set_state("Internal error during connect: %s\n%s"
|
|
|
|
% (str(e), message_restart,))
|
2019-01-08 21:46:26 +03:00
|
|
|
return
|
2019-01-08 18:55:18 +03:00
|
|
|
try:
|
|
|
|
self._set_state(message_ready)
|
|
|
|
for cb in self.event_handlers.get("klippy:ready", []):
|
|
|
|
if self.state_message is not message_ready:
|
|
|
|
return
|
|
|
|
cb()
|
2019-04-05 01:37:20 +03:00
|
|
|
except Exception as e:
|
2019-01-08 18:55:18 +03:00
|
|
|
logging.exception("Unhandled exception during ready callback")
|
2020-09-17 08:59:18 +03:00
|
|
|
self.invoke_shutdown("Internal error during ready callback: %s"
|
|
|
|
% (str(e),))
|
2016-11-28 21:14:56 +03:00
|
|
|
def run(self):
|
2017-02-06 21:31:34 +03:00
|
|
|
systime = time.time()
|
|
|
|
monotime = self.reactor.monotonic()
|
2017-09-27 18:43:14 +03:00
|
|
|
logging.info("Start printer at %s (%.1f %.1f)",
|
|
|
|
time.asctime(time.localtime(systime)), systime, monotime)
|
2018-09-13 02:11:20 +03:00
|
|
|
# Enter main reactor loop
|
|
|
|
try:
|
|
|
|
self.reactor.run()
|
|
|
|
except:
|
2020-09-06 19:45:27 +03:00
|
|
|
msg = "Unhandled exception during run"
|
|
|
|
logging.exception(msg)
|
|
|
|
# Exception from a reactor callback - try to shutdown
|
|
|
|
try:
|
|
|
|
self.reactor.register_callback((lambda e:
|
|
|
|
self.invoke_shutdown(msg)))
|
|
|
|
self.reactor.run()
|
|
|
|
except:
|
|
|
|
logging.exception("Repeat unhandled exception during run")
|
|
|
|
# Another exception - try to exit
|
|
|
|
self.run_result = "error_exit"
|
2018-09-13 02:11:20 +03:00
|
|
|
# Check restart flags
|
|
|
|
run_result = self.run_result
|
|
|
|
try:
|
|
|
|
if run_result == 'firmware_restart':
|
|
|
|
for n, m in self.lookup_objects(module='mcu'):
|
|
|
|
m.microcontroller_restart()
|
2019-01-08 18:55:18 +03:00
|
|
|
self.send_event("klippy:disconnect")
|
2018-09-13 02:11:20 +03:00
|
|
|
except:
|
|
|
|
logging.exception("Unhandled exception during post run")
|
|
|
|
return run_result
|
2020-05-05 20:57:07 +03:00
|
|
|
def set_rollover_info(self, name, info, log=True):
|
|
|
|
if log:
|
|
|
|
logging.info(info)
|
|
|
|
if self.bglogger is not None:
|
|
|
|
self.bglogger.set_rollover_info(name, info)
|
2017-12-04 02:13:47 +03:00
|
|
|
def invoke_shutdown(self, msg):
|
2020-04-25 19:41:44 +03:00
|
|
|
if self.in_shutdown_state:
|
2017-10-12 22:15:14 +03:00
|
|
|
return
|
2020-03-24 15:37:36 +03:00
|
|
|
logging.error("Transition to shutdown state: %s", msg)
|
2020-04-25 19:41:44 +03:00
|
|
|
self.in_shutdown_state = True
|
2018-06-16 22:15:17 +03:00
|
|
|
self._set_state("%s%s" % (msg, message_shutdown))
|
2019-01-08 17:15:40 +03:00
|
|
|
for cb in self.event_handlers.get("klippy:shutdown", []):
|
|
|
|
try:
|
|
|
|
cb()
|
|
|
|
except:
|
|
|
|
logging.exception("Exception during shutdown handler")
|
2020-09-17 08:59:18 +03:00
|
|
|
logging.info("Reactor garbage collection: %s",
|
|
|
|
self.reactor.get_gc_stats())
|
2017-10-12 22:15:14 +03:00
|
|
|
def invoke_async_shutdown(self, msg):
|
2018-09-02 19:43:40 +03:00
|
|
|
self.reactor.register_async_callback(
|
|
|
|
(lambda e: self.invoke_shutdown(msg)))
|
2018-10-07 19:22:10 +03:00
|
|
|
def register_event_handler(self, event, callback):
|
|
|
|
self.event_handlers.setdefault(event, []).append(callback)
|
|
|
|
def send_event(self, event, *params):
|
|
|
|
return [cb(*params) for cb in self.event_handlers.get(event, [])]
|
2018-06-16 22:15:17 +03:00
|
|
|
def request_exit(self, result):
|
2019-06-28 01:32:25 +03:00
|
|
|
if self.run_result is None:
|
|
|
|
self.run_result = result
|
2016-12-01 07:47:40 +03:00
|
|
|
self.reactor.end()
|
2016-05-25 18:37:40 +03:00
|
|
|
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# Startup
|
|
|
|
######################################################################
|
|
|
|
|
2021-10-02 03:57:26 +03:00
|
|
|
def import_test():
|
|
|
|
# Import all optional modules (used as a build test)
|
|
|
|
dname = os.path.dirname(__file__)
|
|
|
|
for mname in ['extras', 'kinematics']:
|
|
|
|
for fname in os.listdir(os.path.join(dname, mname)):
|
|
|
|
if fname.endswith('.py') and fname != '__init__.py':
|
|
|
|
module_name = fname[:-3]
|
|
|
|
else:
|
|
|
|
iname = os.path.join(dname, mname, fname, '__init__.py')
|
|
|
|
if not os.path.exists(iname):
|
|
|
|
continue
|
|
|
|
module_name = fname
|
|
|
|
importlib.import_module(mname + '.' + module_name)
|
|
|
|
sys.exit(0)
|
|
|
|
|
2017-08-14 18:46:35 +03:00
|
|
|
def arg_dictionary(option, opt_str, value, parser):
|
|
|
|
key, fname = "dictionary", value
|
|
|
|
if '=' in value:
|
|
|
|
mcu_name, fname = value.split('=', 1)
|
|
|
|
key = "dictionary_" + mcu_name
|
|
|
|
if parser.values.dictionary is None:
|
|
|
|
parser.values.dictionary = {}
|
|
|
|
parser.values.dictionary[key] = fname
|
|
|
|
|
2016-05-25 18:37:40 +03:00
|
|
|
def main():
|
|
|
|
usage = "%prog [options] <config file>"
|
|
|
|
opts = optparse.OptionParser(usage)
|
2017-08-22 00:19:43 +03:00
|
|
|
opts.add_option("-i", "--debuginput", dest="debuginput",
|
2016-05-25 18:37:40 +03:00
|
|
|
help="read commands from file instead of from tty port")
|
2019-02-27 21:18:43 +03:00
|
|
|
opts.add_option("-I", "--input-tty", dest="inputtty",
|
|
|
|
default='/tmp/printer',
|
2016-11-21 04:40:31 +03:00
|
|
|
help="input tty name (default is /tmp/printer)")
|
2020-08-11 23:26:07 +03:00
|
|
|
opts.add_option("-a", "--api-server", dest="apiserver",
|
|
|
|
help="api server unix domain socket filename")
|
2016-05-25 18:37:40 +03:00
|
|
|
opts.add_option("-l", "--logfile", dest="logfile",
|
|
|
|
help="write log to file instead of stderr")
|
|
|
|
opts.add_option("-v", action="store_true", dest="verbose",
|
|
|
|
help="enable debug messages")
|
2017-08-22 00:19:43 +03:00
|
|
|
opts.add_option("-o", "--debugoutput", dest="debugoutput",
|
|
|
|
help="write output to file instead of to serial port")
|
2017-08-14 18:46:35 +03:00
|
|
|
opts.add_option("-d", "--dictionary", dest="dictionary", type="string",
|
|
|
|
action="callback", callback=arg_dictionary,
|
2016-05-25 18:37:40 +03:00
|
|
|
help="file to read for mcu protocol dictionary")
|
2021-10-02 03:57:26 +03:00
|
|
|
opts.add_option("--import-test", action="store_true",
|
|
|
|
help="perform an import module test")
|
2016-05-25 18:37:40 +03:00
|
|
|
options, args = opts.parse_args()
|
2021-10-02 03:57:26 +03:00
|
|
|
if options.import_test:
|
|
|
|
import_test()
|
2016-05-25 18:37:40 +03:00
|
|
|
if len(args) != 1:
|
|
|
|
opts.error("Incorrect number of arguments")
|
2020-08-11 23:26:07 +03:00
|
|
|
start_args = {'config_file': args[0], 'apiserver': options.apiserver,
|
|
|
|
'start_reason': 'startup'}
|
2016-05-25 18:37:40 +03:00
|
|
|
|
|
|
|
debuglevel = logging.INFO
|
|
|
|
if options.verbose:
|
|
|
|
debuglevel = logging.DEBUG
|
2017-08-22 00:19:43 +03:00
|
|
|
if options.debuginput:
|
|
|
|
start_args['debuginput'] = options.debuginput
|
|
|
|
debuginput = open(options.debuginput, 'rb')
|
2020-08-04 22:47:25 +03:00
|
|
|
start_args['gcode_fd'] = debuginput.fileno()
|
2016-11-21 04:40:31 +03:00
|
|
|
else:
|
2020-08-04 22:47:25 +03:00
|
|
|
start_args['gcode_fd'] = util.create_pty(options.inputtty)
|
2017-08-22 00:19:43 +03:00
|
|
|
if options.debugoutput:
|
|
|
|
start_args['debugoutput'] = options.debugoutput
|
2017-08-14 18:46:35 +03:00
|
|
|
start_args.update(options.dictionary)
|
2020-08-04 22:47:25 +03:00
|
|
|
bglogger = None
|
2016-05-25 18:37:40 +03:00
|
|
|
if options.logfile:
|
2020-06-19 13:18:58 +03:00
|
|
|
start_args['log_file'] = options.logfile
|
2016-11-12 04:22:39 +03:00
|
|
|
bglogger = queuelogger.setup_bg_logging(options.logfile, debuglevel)
|
2016-05-25 18:37:40 +03:00
|
|
|
else:
|
|
|
|
logging.basicConfig(level=debuglevel)
|
|
|
|
logging.info("Starting Klippy...")
|
2017-08-22 00:19:43 +03:00
|
|
|
start_args['software_version'] = util.get_git_version()
|
2020-06-19 13:18:58 +03:00
|
|
|
start_args['cpu_info'] = util.get_cpu_info()
|
2017-05-01 20:44:06 +03:00
|
|
|
if bglogger is not None:
|
2018-04-03 19:13:06 +03:00
|
|
|
versions = "\n".join([
|
|
|
|
"Args: %s" % (sys.argv,),
|
|
|
|
"Git version: %s" % (repr(start_args['software_version']),),
|
2020-06-19 13:18:58 +03:00
|
|
|
"CPU: %s" % (start_args['cpu_info'],),
|
2018-04-03 19:13:06 +03:00
|
|
|
"Python: %s" % (repr(sys.version),)])
|
|
|
|
logging.info(versions)
|
2019-09-02 01:09:20 +03:00
|
|
|
elif not options.debugoutput:
|
|
|
|
logging.warning("No log file specified!"
|
|
|
|
" Severe timing issues may result!")
|
2020-09-17 05:23:44 +03:00
|
|
|
gc.disable()
|
2016-05-25 18:37:40 +03:00
|
|
|
|
2017-08-22 00:19:43 +03:00
|
|
|
# Start Printer() class
|
2016-12-01 07:47:40 +03:00
|
|
|
while 1:
|
2018-04-03 19:13:06 +03:00
|
|
|
if bglogger is not None:
|
|
|
|
bglogger.clear_rollover_info()
|
|
|
|
bglogger.set_rollover_info('versions', versions)
|
2020-09-17 04:42:24 +03:00
|
|
|
gc.collect()
|
2020-09-17 05:23:44 +03:00
|
|
|
main_reactor = reactor.Reactor(gc_checking=True)
|
2020-09-16 19:15:19 +03:00
|
|
|
printer = Printer(main_reactor, bglogger, start_args)
|
2016-12-01 07:47:40 +03:00
|
|
|
res = printer.run()
|
2018-06-16 22:15:17 +03:00
|
|
|
if res in ['exit', 'error_exit']:
|
2017-08-22 00:19:43 +03:00
|
|
|
break
|
|
|
|
time.sleep(1.)
|
2020-09-16 19:15:19 +03:00
|
|
|
main_reactor.finalize()
|
2020-09-17 04:42:24 +03:00
|
|
|
main_reactor = printer = None
|
2017-08-22 00:19:43 +03:00
|
|
|
logging.info("Restarting printer")
|
|
|
|
start_args['start_reason'] = res
|
2016-05-25 18:37:40 +03:00
|
|
|
|
2016-11-12 04:22:39 +03:00
|
|
|
if bglogger is not None:
|
|
|
|
bglogger.stop()
|
|
|
|
|
2018-06-16 22:15:17 +03:00
|
|
|
if res == 'error_exit':
|
|
|
|
sys.exit(-1)
|
|
|
|
|
2016-05-25 18:37:40 +03:00
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|