diff --git a/klippy/configfile.py b/klippy/configfile.py index e3800c7a0..ee1221143 100644 --- a/klippy/configfile.py +++ b/klippy/configfile.py @@ -266,6 +266,8 @@ def __init__(self, printer): self.status_save_pending = {} self.status_settings = {} self.status_warnings = [] + self.unused_sections = [] + self.unused_options = [] self.save_config_pending = False gcode = self.printer.lookup_object("gcode") gcode.register_command( @@ -426,7 +428,7 @@ def read_main_config(self): cfg = self._build_config_wrapper(regular_data + autosave_data, filename) return cfg - def check_unused_options(self, config): + def check_unused_options(self, config, error_on_unused): fileconfig = config.fileconfig objects = dict(self.printer.lookup_objects()) # Determine all the fields that have been accessed @@ -439,16 +441,22 @@ def check_unused_options(self, config): for section_name in fileconfig.sections(): section = section_name.lower() if section not in valid_sections and section not in objects: - raise error( - "Section '%s' is not a valid config section" % (section,) - ) + if error_on_unused: + raise error( + "Section '%s' is not a valid config section" % (section,) + ) + else: + self.unused_sections.append(section) for option in fileconfig.options(section_name): option = option.lower() if (section, option) not in access_tracking: - raise error( - "Option '%s' is not valid in section '%s'" - % (option, section) - ) + if error_on_unused: + raise error( + "Option '%s' is not valid in section '%s'" + % (option, section) + ) + else: + self.unused_options.append((section, option)) # Setup get_status() self._build_status(config) @@ -483,7 +491,20 @@ def _build_status(self, config): res["section"] = section res["option"] = option self.status_warnings.append(res) - + for section, option in self.unused_options: + res = {"type": "unused_option"} + res["message"] = "Option '%s' in section '%s' is invalid" % ( + option, + section, + ) + res["section"] = section + res["option"] = option + self.status_warnings.append(res) + for section in self.unused_sections: + res = {"type": "unused_section"} + res["message"] = "Section '%s' is invalid" % (section,) + res["section"] = section + self.status_warnings.append(res) def get_status(self, eventtime): return { "config": self.status_raw_config, diff --git a/klippy/extras/bed_mesh.py b/klippy/extras/bed_mesh.py index 23e4ea4aa..4fd36bc9d 100644 --- a/klippy/extras/bed_mesh.py +++ b/klippy/extras/bed_mesh.py @@ -161,7 +161,9 @@ def __init__(self, config): def handle_connect(self): self.toolhead = self.printer.lookup_object("toolhead") - self.bmc.print_generated_points(logging.info) + self.debug_options = self.printer.lookup_object("debug_options") + if self.debug_options.log_bed_mesh_at_startup: + self.bmc.print_generated_points(logging.info) def set_mesh(self, mesh): if mesh is not None and self.fade_end != self.FADE_DISABLE: diff --git a/klippy/extras/debug_options.py b/klippy/extras/debug_options.py new file mode 100644 index 000000000..8c600b467 --- /dev/null +++ b/klippy/extras/debug_options.py @@ -0,0 +1,16 @@ +class DebugOptions: + def __init__(self, config): + self.log_statistics = config.getboolean("log_statistics", True) + self.log_config_file_at_startup = config.getboolean( + "log_config_file_at_startup", True + ) + self.log_bed_mesh_at_startup = config.getboolean( + "log_bed_mesh_at_startup", True + ) + self.log_shutdown_info = config.getboolean("log_shutdown_info", True) + self.error_on_unused_config_options = config.getboolean( + "error_on_unused_config_options", True + ) + +def load_config(config): + return DebugOptions(config) diff --git a/klippy/extras/statistics.py b/klippy/extras/statistics.py index 2fd18dc19..cd035497c 100644 --- a/klippy/extras/statistics.py +++ b/klippy/extras/statistics.py @@ -61,6 +61,7 @@ def get_status(self, eventtime): class PrinterStats: def __init__(self, config): self.printer = config.get_printer() + self.debug_options = self.printer.lookup_object("debug_options") reactor = self.printer.get_reactor() self.stats_timer = reactor.register_timer(self.generate_stats) self.stats_cb = [] @@ -78,7 +79,7 @@ def handle_ready(self): def generate_stats(self, eventtime): stats = [cb(eventtime) for cb in self.stats_cb] - if max([s[0] for s in stats]): + if max([s[0] for s in stats]) and self.debug_options.log_statistics: logging.info( "Stats %.1f: %s", eventtime, " ".join([s[1] for s in stats]) ) diff --git a/klippy/klippy.py b/klippy/klippy.py index 01f3d5450..af673dc4f 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -154,7 +154,11 @@ def load_object(self, config, section, default=configfile.sentinel): def _read_config(self): self.objects["configfile"] = pconfig = configfile.PrinterConfig(self) config = pconfig.read_main_config() - if self.bglogger is not None: + debug_options = self.load_object(config, "debug_options") + if ( + self.bglogger is not None + and debug_options.log_config_file_at_startup + ): pconfig.log_config(config) # Create printer components for m in [pins, mcu]: @@ -164,7 +168,8 @@ def _read_config(self): for m in [toolhead]: m.add_printer_objects(config) # Validate that there are no undefined parameters in the config file - pconfig.check_unused_options(config) + error_on_unused = debug_options.error_on_unused_config_options + pconfig.check_unused_options(config, error_on_unused) def _build_protocol_error_message(self, e): host_version = self.start_args["software_version"] @@ -428,6 +433,7 @@ def main(): bglogger = queuelogger.setup_bg_logging(options.logfile, debuglevel) else: logging.getLogger().setLevel(debuglevel) + logging.info("=======================") logging.info("Starting Klippy...") git_info = util.get_git_version() git_vers = git_info["version"] diff --git a/klippy/mcu.py b/klippy/mcu.py index 4ea583921..b5d3915f8 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -18,6 +18,7 @@ class error(Exception): # Command transmit helper classes ###################################################################### + # Class to retry sending of a query command until a given response is received class RetryAsyncCommand: TIMEOUT_TIME = 5.0 @@ -744,6 +745,7 @@ class MCU: def __init__(self, config, clocksync): self._printer = printer = config.get_printer() + self.debug_options = printer.lookup_object("debug_options") self._clocksync = clocksync self._reactor = printer.get_reactor() self._name = config.get_name() @@ -833,14 +835,15 @@ def _handle_shutdown(self, params): if clock is not None: self._shutdown_clock = self.clock32_to_clock64(clock) self._shutdown_msg = msg = params["static_string_id"] - logging.info( - "MCU '%s' %s: %s\n%s\n%s", - self._name, - params["#name"], - self._shutdown_msg, - self._clocksync.dump_debug(), - self._serial.dump_debug(), - ) + if self.debug_options.log_shutdown_info: + logging.info( + "MCU '%s' %s: %s\n%s\n%s", + self._name, + params["#name"], + self._shutdown_msg, + self._clocksync.dump_debug(), + self._serial.dump_debug(), + ) prefix = "MCU '%s' shutdown: " % (self._name,) if params["#name"] == "is_shutdown": prefix = "Previous MCU '%s' shutdown: " % (self._name,) diff --git a/klippy/toolhead.py b/klippy/toolhead.py index 58f4c2368..7f38a6969 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -11,6 +11,7 @@ # mm/second), _v2 is velocity squared (mm^2/s^2), _t is time (in # seconds), _r is ratio (scalar between 0.0 and 1.0) + # Class to track each move request class Move: def __init__(self, toolhead, start_pos, end_pos, speed): @@ -128,6 +129,7 @@ def set_junction(self, start_v2, cruise_v2, end_v2): LOOKAHEAD_FLUSH_TIME = 0.250 + # Class to track a list of pending move requests and to facilitate # "look-ahead" across moves to reduce acceleration between moves. class MoveQueue: diff --git a/test/klippy/no_stat_logging.cfg b/test/klippy/no_stat_logging.cfg new file mode 100644 index 000000000..6c6ab0a7f --- /dev/null +++ b/test/klippy/no_stat_logging.cfg @@ -0,0 +1,79 @@ + +[statistics] +log_stats: False + +[stepper_x] +step_pin: PF0 +dir_pin: PF1 +enable_pin: !PD7 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PE5 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_y] +step_pin: PF6 +dir_pin: !PF7 +enable_pin: !PF2 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PJ1 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_z] +step_pin: PL3 +dir_pin: PL1 +enable_pin: !PK0 +microsteps: 16 +rotation_distance: 8 +endstop_pin: probe:z_virtual_endstop +position_max: 200 + +[extruder] +step_pin: PA4 +dir_pin: PA6 +enable_pin: !PA2 +microsteps: 16 +rotation_distance: 33.5 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: PB4 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK5 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 250 + +[heater_bed] +heater_pin: PH5 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK6 +control: watermark +min_temp: 0 +max_temp: 130 + +[probe] +pin: PH6 +z_offset: 1.15 +drop_first_result: true + +[bed_mesh] +mesh_min: 10,10 +mesh_max: 180,180 + +[mcu] +serial: /dev/ttyACM0 + +[printer] +kinematics: cartesian +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 5 +max_z_accel: 100 diff --git a/test/klippy/no_stat_logging.test b/test/klippy/no_stat_logging.test new file mode 100644 index 000000000..9152cd88c --- /dev/null +++ b/test/klippy/no_stat_logging.test @@ -0,0 +1,12 @@ +CONFIG no_stat_logging.cfg +DICTIONARY atmega2560.dict + +# Start by homing the printer. +G28 + +G1 F6000 + +# Z / X / Y moves +G1 Z1 +G1 X1 +G1 Y1