job_status: rework time calculation

New 'Auto' setting that selects the best guess
added an slicer time compensation if you find that your slicer always under/over estimates by some amount
Split in days if the time is more than 24h
This commit is contained in:
Alfredo Monclus 2022-03-10 11:43:53 -03:00 committed by GitHub
parent 7a4613bfe4
commit b1dd83d955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 35 deletions

View File

@ -333,9 +333,14 @@ class KlippyGtk:
def formatTimeString(self, seconds):
time = int(seconds)
text = ""
if int(time/86400) != 0:
text += str(int(time/86400))+"d "
if int(time/3600) != 0:
text += str(int(time/3600))+"h "
text += str(int(time/60) % 60)+"m "+str(time % 60)+"s"
text += str(int(time/3600) % 24)+"h "
if int(time/60) != 0:
text += str(int(time/60) % 60)+"m "
else:
text = str(time % 60)+"s"
return text
def formatTemperatureString(self, temp, target):

View File

@ -124,8 +124,8 @@ class KlipperScreenConfig:
{"print_estimate_method": {
"section": "main", "name": _("Estimated Time Method"), "type": "dropdown",
"value": "file", "options": [
{"name": _("File") + " " + _("(default)"), "value": "file"},
{"name": _("Duration Only"), "value": "duration"},
{"name": _("Auto") + " " + _("(default)"), "value": "auto"},
{"name": _("File"), "value": "file"},
{"name": _("Filament Used"), "value": "filament"},
{"name": _("Slicer"), "value": "slicer"}]}},
{"screen_blanking": {
@ -153,6 +153,9 @@ class KlipperScreenConfig:
"value": "False", "callback": screen.restart_warning}},
{"use_dpms": {"section": "main", "name": _("Screen DPMS"), "type": "binary",
"value": "True", "callback": screen.set_dpms}},
{"print_estimate_compensation": {
"section": "main", "name": _("Slicer Time correction (%)"), "type": "scale", "value": "100",
"range": [50, 150], "step": 1}},
# {"": {"section": "main", "name": _(""), "type": ""}}
]

View File

@ -130,14 +130,21 @@ class JobStatusPanel(ScreenPanel):
self.labels['elapsed'].get_style_context().add_class("printing-info")
self.labels['duration'] = Gtk.Label(label="0s")
self.labels['duration'].get_style_context().add_class("printing-info")
self.labels['est_time'] = Gtk.Label(label="/ 0s")
self.labels['total'] = Gtk.Label(label=_("Total:"))
self.labels['total'].get_style_context().add_class("printing-info")
self.labels['est_time'] = Gtk.Label(label="0s")
self.labels['est_time'].get_style_context().add_class("printing-info")
it_box = Gtk.Box(spacing=0)
it_box.add(clock)
it_box.add(self.labels['elapsed'])
it_box.add(self.labels['duration'])
it_box.add(self.labels['est_time'])
self.labels['it_box'] = it_box
timegrid = Gtk.Grid()
it1_box = Gtk.Box(spacing=0)
it1_box.add(self.labels['elapsed'])
it1_box.add(self.labels['duration'])
it2_box = Gtk.Box(spacing=0)
it2_box.add(self.labels['total'])
it2_box.add(self.labels['est_time'])
timegrid.attach(clock, 0, 0, 1, 2)
timegrid.attach(it1_box, 1, 0, 1, 1)
timegrid.attach(it2_box, 1, 1, 1, 1)
self.labels['timegrid'] = timegrid
position = self._gtk.Image("move.svg", None, .6, .6)
self.labels['pos_x'] = Gtk.Label(label="X: 0")
@ -241,7 +248,7 @@ class JobStatusPanel(ScreenPanel):
self.labels['i2_box'].add(self.labels['temp_grid'])
self.labels['i2_box'].add(self.labels['pos_box'])
self.labels['i2_box'].add(self.labels['sfe_grid'])
self.labels['i2_box'].add(self.labels['it_box'])
self.labels['i2_box'].add(self.labels['timegrid'])
self.labels['i2_box'].add(self.labels['itl_box'])
@ -412,29 +419,57 @@ class JobStatusPanel(ScreenPanel):
self.update_percent_complete()
self.update_text("duration", str(self._gtk.formatTimeString(ps['print_duration'])))
self.update_text("time_left", self.calculate_time_left(ps['print_duration'], ps['filament_used']))
timeleft_type = self._config.get_config()['main'].get('print_estimate_method', 'file')
if timeleft_type != self.timeleft_type:
if self.timeleft_type == "duration":
self.labels['it_box'].add(self.labels['est_time'])
elif timeleft_type == "duration":
self.labels['it_box'].remove(self.labels['est_time'])
self.timeleft_type = timeleft_type
def calculate_time_left(self, duration=0, filament_used=0):
total_duration = None
if self.progress < 1:
slicer_time = filament_time = file_time = None
timeleft_type = self._config.get_config()['main'].get('print_estimate_method', 'auto')
slicer_correction = (self._config.get_config()['main'].getint('print_estimate_compensation', 100) / 100)
# speed_factor compensation based on empirical testing
spdcomp = math.sqrt(self.speed / 100)
if timeleft_type in ['filament', 'file', 'slicer']:
duration = ps['print_duration']
if timeleft_type == "filament":
estimated_filament = (self.file_metadata['filament_total'] if "filament_total" in self.file_metadata
else 1)
total_duration = duration / (max(ps['filament_used'], 0.0001) / max(estimated_filament, 0.0001))
elif timeleft_type == "file":
total_duration = duration / max(self.progress, 0.0001)
elif timeleft_type == "slicer":
total_duration = (self.file_metadata['estimated_time'] if "estimated_time" in self.file_metadata
else duration)
time_left = max(total_duration - duration, 0)
self.update_text("time_left", str(self._gtk.formatTimeString(time_left)))
self.update_text("est_time", "/ %s" % str(self._gtk.formatTimeString(total_duration)))
if "estimated_time" in self.file_metadata:
if self.file_metadata['estimated_time'] > 0:
slicer_time = (self.file_metadata['estimated_time'] * slicer_correction) / spdcomp
if slicer_time < duration:
slicer_time = None
if "filament_total" in self.file_metadata:
if self.file_metadata['filament_total'] > 0 and filament_used > 0:
if self.file_metadata['filament_total'] > filament_used:
filament_time = duration / (filament_used / self.file_metadata['filament_total'])
if filament_time < duration:
filament_time = None
if self.progress > 0:
file_time = duration / self.progress
if timeleft_type == "file" and file_time is not None:
total_duration = file_time
elif timeleft_type == "filament" and filament_time is not None:
total_duration = filament_time
elif slicer_time is not None:
if timeleft_type == "slicer":
total_duration = slicer_time
else:
if filament_time is not None and self.progress > 0.14:
# Weighted arithmetic mean (Slicer is the most accurate)
total_duration = (slicer_time * 3 + filament_time + file_time) / 5
else:
# At the begining file and filament are innacurate
total_duration = slicer_time
elif file_time is not None:
if filament_time is not None:
total_duration = (filament_time + file_time) / 2
else:
total_duration = file_time
if total_duration is None:
return "-"
self.update_text("est_time", str(self._gtk.formatTimeString(total_duration)))
return str(self._gtk.formatTimeString((total_duration - duration)))
def state_check(self):
ps = self._printer.get_stat("print_stats")
@ -541,7 +576,7 @@ class JobStatusPanel(ScreenPanel):
self.file_metadata = self._files.get_file_info(self.filename)
logging.info("Update Metadata. File: %s Size: %s" % (self.filename, self.file_metadata['size']))
if "estimated_time" in self.file_metadata and self.timeleft_type == "slicer":
self.update_text("est_time", "/ %s" %
self.update_text("est_time",
str(self._gtk.formatTimeString(self.file_metadata['estimated_time'])))
if "thumbnails" in self.file_metadata:
tmp = self.file_metadata['thumbnails'].copy()
@ -578,7 +613,7 @@ class JobStatusPanel(ScreenPanel):
self.labels[label].set_text(text)
def update_progress(self):
self.labels['progress_text'].set_text("%s%%" % (str(min(int(round(self.progress, 2)*100), 100))))
self.labels['progress_text'].set_text("%s%%" % (str(min(int(self.progress*100), 100))))
def update_message(self):
msg = self._printer.get_stat("display_status", "message")