2020-07-31 22:23:03 +03:00
|
|
|
# Virtual SDCard print stat tracking
|
|
|
|
#
|
|
|
|
# Copyright (C) 2020 Eric Callahan <arksine.code@gmail.com>
|
|
|
|
#
|
|
|
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
|
|
|
|
|
|
|
class PrintStats:
|
|
|
|
def __init__(self, config):
|
|
|
|
printer = config.get_printer()
|
2020-08-17 07:05:41 +03:00
|
|
|
self.gcode_move = printer.load_object(config, 'gcode_move')
|
2020-07-31 22:23:03 +03:00
|
|
|
self.reactor = printer.get_reactor()
|
|
|
|
self.reset()
|
2022-10-05 22:02:28 +03:00
|
|
|
# Register commands
|
|
|
|
self.gcode = printer.lookup_object('gcode')
|
|
|
|
self.gcode.register_command(
|
|
|
|
"SET_PRINT_STATS_INFO", self.cmd_SET_PRINT_STATS_INFO,
|
|
|
|
desc=self.cmd_SET_PRINT_STATS_INFO_help)
|
2020-07-31 22:23:03 +03:00
|
|
|
def _update_filament_usage(self, eventtime):
|
2020-08-05 18:43:45 +03:00
|
|
|
gc_status = self.gcode_move.get_status(eventtime)
|
2020-08-15 23:07:07 +03:00
|
|
|
cur_epos = gc_status['position'].e
|
2020-07-31 22:23:03 +03:00
|
|
|
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
|
2020-08-05 18:43:45 +03:00
|
|
|
gc_status = self.gcode_move.get_status(curtime)
|
2020-08-15 23:07:07 +03:00
|
|
|
self.last_epos = gc_status['position'].e
|
2020-08-03 19:21:56 +03:00
|
|
|
self.state = "printing"
|
|
|
|
self.error_message = ""
|
2020-07-31 22:23:03 +03:00
|
|
|
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)
|
2020-08-03 19:21:56 +03:00
|
|
|
if self.state != "error":
|
|
|
|
self.state = "paused"
|
|
|
|
def note_complete(self):
|
2021-06-14 22:09:55 +03:00
|
|
|
self._note_finish("complete")
|
|
|
|
def note_error(self, message):
|
|
|
|
self._note_finish("error", message)
|
|
|
|
def note_cancel(self):
|
|
|
|
self._note_finish("cancelled")
|
|
|
|
def _note_finish(self, state, error_message = ""):
|
2021-11-20 23:25:49 +03:00
|
|
|
if self.print_start_time is None:
|
|
|
|
return
|
2021-06-14 22:09:55 +03:00
|
|
|
self.state = state
|
|
|
|
self.error_message = error_message
|
2020-08-03 19:21:56 +03:00
|
|
|
eventtime = self.reactor.monotonic()
|
|
|
|
self.total_duration = eventtime - self.print_start_time
|
2020-11-12 15:06:02 +03:00
|
|
|
if self.filament_used < 0.0000001:
|
|
|
|
# No positive extusion detected during print
|
|
|
|
self.init_duration = self.total_duration - \
|
|
|
|
self.prev_pause_duration
|
2020-08-03 19:21:56 +03:00
|
|
|
self.print_start_time = None
|
2022-10-05 22:02:28 +03:00
|
|
|
cmd_SET_PRINT_STATS_INFO_help = "Pass slicer info like layer act and " \
|
|
|
|
"total to klipper"
|
|
|
|
def cmd_SET_PRINT_STATS_INFO(self, gcmd):
|
|
|
|
total_layer = gcmd.get_int("TOTAL_LAYER", self.info_total_layer, \
|
|
|
|
minval=0)
|
|
|
|
current_layer = gcmd.get_int("CURRENT_LAYER", self.info_current_layer, \
|
|
|
|
minval=0)
|
|
|
|
if total_layer == 0:
|
|
|
|
self.info_total_layer = None
|
|
|
|
self.info_current_layer = None
|
|
|
|
elif total_layer != self.info_total_layer:
|
|
|
|
self.info_total_layer = total_layer
|
|
|
|
self.info_current_layer = 0
|
|
|
|
|
|
|
|
if self.info_total_layer is not None and \
|
|
|
|
current_layer is not None and \
|
|
|
|
current_layer != self.info_current_layer:
|
|
|
|
self.info_current_layer = min(current_layer, self.info_total_layer)
|
2020-07-31 22:23:03 +03:00
|
|
|
def reset(self):
|
2020-08-03 19:21:56 +03:00
|
|
|
self.filename = self.error_message = ""
|
|
|
|
self.state = "standby"
|
2020-07-31 22:23:03 +03:00
|
|
|
self.prev_pause_duration = self.last_epos = 0.
|
2020-08-03 19:21:56 +03:00
|
|
|
self.filament_used = self.total_duration = 0.
|
2020-07-31 22:23:03 +03:00
|
|
|
self.print_start_time = self.last_pause_time = None
|
2020-11-12 15:06:02 +03:00
|
|
|
self.init_duration = 0.
|
2022-10-05 22:02:28 +03:00
|
|
|
self.info_total_layer = None
|
|
|
|
self.info_current_layer = None
|
2020-07-31 22:23:03 +03:00
|
|
|
def get_status(self, eventtime):
|
|
|
|
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)
|
2020-08-03 19:21:56 +03:00
|
|
|
self.total_duration = eventtime - self.print_start_time
|
2020-11-12 15:06:02 +03:00
|
|
|
if self.filament_used < 0.0000001:
|
|
|
|
# Track duration prior to extrusion
|
|
|
|
self.init_duration = self.total_duration - time_paused
|
|
|
|
print_duration = self.total_duration - self.init_duration - time_paused
|
2020-07-31 22:23:03 +03:00
|
|
|
return {
|
|
|
|
'filename': self.filename,
|
2020-08-03 19:21:56 +03:00
|
|
|
'total_duration': self.total_duration,
|
2020-11-12 15:06:02 +03:00
|
|
|
'print_duration': print_duration,
|
2020-08-03 19:21:56 +03:00
|
|
|
'filament_used': self.filament_used,
|
|
|
|
'state': self.state,
|
2022-10-05 22:02:28 +03:00
|
|
|
'message': self.error_message,
|
|
|
|
'info': {'total_layer': self.info_total_layer,
|
|
|
|
'current_layer': self.info_current_layer}
|
2020-07-31 22:23:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
def load_config(config):
|
|
|
|
return PrintStats(config)
|