diff --git a/klippy/extras/print_stats.py b/klippy/extras/print_stats.py new file mode 100644 index 00000000..9ff9ca1f --- /dev/null +++ b/klippy/extras/print_stats.py @@ -0,0 +1,64 @@ +# Virtual SDCard print stat tracking +# +# Copyright (C) 2020 Eric Callahan +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +class PrintStats: + def __init__(self, config): + printer = config.get_printer() + self.gcode = printer.lookup_object('gcode') + self.reactor = printer.get_reactor() + self.reset() + def _update_filament_usage(self, eventtime): + gc_status = self.gcode.get_status(eventtime) + cur_epos = gc_status['last_epos'] + self.filament_used += (cur_epos - self.last_epos) \ + / gc_status['extrude_factor'] + self.last_epos = cur_epos + def set_current_file(self, filename): + self.reset() + self.filename = filename + def note_start(self): + curtime = self.reactor.monotonic() + if self.print_start_time is None: + self.print_start_time = curtime + elif self.last_pause_time is not None: + # Update pause time duration + pause_duration = curtime - self.last_pause_time + self.prev_pause_duration += pause_duration + self.last_pause_time = None + # Reset last e-position + gc_status = self.gcode.get_status(curtime) + self.last_epos = gc_status['last_epos'] + def note_pause(self): + if self.last_pause_time is None: + curtime = self.reactor.monotonic() + self.last_pause_time = curtime + # update filament usage + self._update_filament_usage(curtime) + def reset(self): + self.filename = "" + self.prev_pause_duration = self.last_epos = 0. + self.filament_used = 0. + self.print_start_time = self.last_pause_time = None + def get_status(self, eventtime): + total_duration = 0. + time_paused = self.prev_pause_duration + if self.print_start_time is not None: + if self.last_pause_time is not None: + # Calculate the total time spent paused during the print + time_paused += eventtime - self.last_pause_time + else: + # Accumulate filament if not paused + self._update_filament_usage(eventtime) + total_duration = eventtime - self.print_start_time + return { + 'filename': self.filename, + 'total_duration': total_duration, + 'print_duration': total_duration - time_paused, + 'filament_used': self.filament_used + } + +def load_config(config): + return PrintStats(config) diff --git a/klippy/extras/virtual_sdcard.py b/klippy/extras/virtual_sdcard.py index b2381a06..a2de1327 100644 --- a/klippy/extras/virtual_sdcard.py +++ b/klippy/extras/virtual_sdcard.py @@ -16,6 +16,8 @@ class VirtualSD: self.sdcard_dirname = os.path.normpath(os.path.expanduser(sd)) self.current_file = None self.file_position = self.file_size = 0 + # Print Stat Tracking + self.print_stats = printer.load_object(config, 'print_stats') # Work timer self.reactor = printer.get_reactor() self.must_pause_work = self.cmd_from_sd = False @@ -99,6 +101,7 @@ class VirtualSD: self.current_file.close() self.current_file = None self.file_position = self.file_size = 0. + self.print_stats.reset() cmd_SDCARD_RESET_FILE_help = "Clears a loaded SD File. Stops the print "\ "if necessary" def cmd_SDCARD_RESET_FILE(self, gcmd): @@ -160,6 +163,7 @@ class VirtualSD: self.current_file = f self.file_position = 0 self.file_size = fsize + self.print_stats.set_current_file(filename) def cmd_M24(self, gcmd): # Start/resume SD print if self.work_timer is not None: @@ -193,6 +197,7 @@ class VirtualSD: logging.exception("virtual_sdcard seek") self.work_timer = None return self.reactor.NEVER + self.print_stats.note_start() gcode_mutex = self.gcode.get_mutex() partial_input = "" lines = [] @@ -235,6 +240,10 @@ class VirtualSD: logging.info("Exiting SD card print (position %d)", self.file_position) self.work_timer = None self.cmd_from_sd = False + if self.current_file is not None: + self.print_stats.note_pause() + else: + self._reset_file() return self.reactor.NEVER def load_config(config):