Skip to content

Instantly share code, notes, and snippets.

@allancoding
Last active October 6, 2023 00:12
Show Gist options
  • Save allancoding/0e5d40a0702d3d12af0c19f1facc77b1 to your computer and use it in GitHub Desktop.
Save allancoding/0e5d40a0702d3d12af0c19f1facc77b1 to your computer and use it in GitHub Desktop.
An advanced Post Processing script to show information on the LCD
# Cura PostProcessingPlugin
# Author: Allan Niles
# Date: Aug 23, 2023
# Modified: Oct 5, 2023
# Description: This plugin displays iknformation on the LCD. It can output the estimated time remaining and the completion percentage and the curent layer.
from ..Script import Script
from UM.Application import Application
import re
import datetime
class ShowAdvancedInformationOnLCD(Script):
def __init__(self):
super().__init__()
def getSettingDataString(self):
return """{
"name": "Show Advanced Information On LCD",
"key": "ShowAdvancedInformationOnLCD",
"metadata": {},
"version": 2,
"settings":
{
"show_display":
{
"label": "Enable Display LCD",
"description": "Enable to display progress on the LCD.",
"type": "bool",
"default_value": true
},
"time_remaining":
{
"label": "Time Remaining",
"description": "Select to write remaining time to the display. Select to write remaining time on the display using M117 status line message (almost all printers) or using M73 command (Prusa and Marlin 2 if enabled).",
"type": "bool",
"default_value": true,
"enabled": "show_display"
},
"time_structure":
{
"label": "Time Structure",
"description": "How should remaining time be shown on the display? 0h00m00s or 0:00:00",
"type": "enum",
"options": {
"hms":"0h00m00s",
":":"0:00:00"
},
"enabled": "show_display and time_remaining",
"default_value": "hms"
},
"show_layers":
{
"label": "Show layers left",
"description": "Show the layer number out of layers left to print. eg. 23/100",
"type": "bool",
"default_value": true,
"enabled": "show_display"
},
"startNum":
{
"label": "Initial layer number:",
"description": "Choose which number you prefer for the initial layer, 0 or 1",
"type": "int",
"default_value": 1,
"minimum_value": 0,
"maximum_value": 1,
"enabled": "show_layers and show_display"
},
"maxlayer":
{
"label": "Display max layer?:",
"description": "Display how many layers are in the entire print on status bar?",
"type": "bool",
"default_value": true,
"enabled": "show_layers and show_display"
},
"update_frequency":
{
"label": "Update frequency",
"description": "Update remaining time for every layer or periodically every minute or faster.",
"type": "enum",
"options": {"0":"Every layer","1":"Every second","15":"Every 15 seconds","30":"Every 30 seconds","60":"Every minute"},
"default_value": "0",
"enabled": "show_display and time_remaining"
},
"percentage":
{
"label": "Percentage",
"description": "When enabled, set the completion bar percentage on the LCD using Marlin's M73 command.",
"type": "bool",
"default_value": true
},
"time_remaining_method":
{
"label": "Time Reporting Method",
"description": "How should remaining time be shown on the display? It could use a generic message command (M117, almost all printers), or a specialised time remaining command (M73, Prusa and Marlin 2).",
"type": "enum",
"options": {
"m117":"M117 - All printers",
"m73":"M73 - Prusa, Marlin 2",
"m118":"M118 - Octoprint"
},
"enabled": "(show_display and (time_remaining or show_layers)) or percentage",
"default_value": "m117"
}
}
}"""
def getTimeValue(self, line):
list_split = re.split(":", line)
return float(list_split[1])
def outputTime(self, lines, line_index, time_left, output_type, extra, structure, time):
time_left = max(time_left, 0)
m, s = divmod(time_left, 60)
h, m = divmod(m, 60)
mins = int(60 * h + m + s / 30)
if structure == ":":
current_time_string = "{:d}:{:02d}:{:02d}".format(int(h), int(m), int(s))
else:
current_time_string = "{:d}h{:02d}m{:02d}s".format(int(h), int(m), int(s))
if output_type.startswith("M117 "):
if extra and not time:
lines.insert(line_index, output_type+extra)
elif time and extra:
lines.insert(line_index, output_type+"{} - ".format(current_time_string)+extra)
else:
lines.insert(line_index, output_type+"{}".format(current_time_string))
elif output_type.startswith("M118 A1 P0 action:notification "):
if extra and not time:
lines.insert(line_index, output_type+extra)
elif time and extra:
lines.insert(line_index, output_type+"{} - ".format(current_time_string)+extra)
else:
lines.insert(line_index, output_type+"{}".format(current_time_string))
elif output_type.startswith("M73 R"):
if extra and not time:
lines.insert(line_index, output_type+extra)
elif time and extra:
lines.insert(line_index, output_type+"{} - ".format(mins)+extra)
else:
lines.insert(line_index, "M73 R{}".format(mins))
def execute(self, data):
show_display = self.getSettingValueByKey("show_display")
output_time = self.getSettingValueByKey("time_remaining")
show_layers = self.getSettingValueByKey("show_layers")
output_time_method = self.getSettingValueByKey("time_remaining_method")
output_frequency = int(self.getSettingValueByKey("update_frequency"))
output_percentage = self.getSettingValueByKey("percentage")
max_layer_setting = self.getSettingValueByKey("maxlayer")
startNum = self.getSettingValueByKey("startNum")
time_structure = self.getSettingValueByKey("time_structure")
line_set = {}
if not output_time and not show_layers:
show_display = False
if show_display or output_percentage:
if show_display:
max_layer = 0
name = Application.getInstance().getPrintInformation().jobName
if output_time_method == "m117":
lcd_text = "M117 "
elif output_time_method == "m118":
lcd_text = "M118 A1 P0 action:notification "
else:
lcd_text = "M73 R"
lcd_text_old = lcd_text
show_time = True
if show_layers and not output_time:
show_time = False
output_frequency = 0
if max_layer_setting:
lcd_text = lcd_text + "Layer "
else:
lcd_text = lcd_text + "On Layer "
i = startNum
if not show_layers:
output_layer = False
else:
output_layer = ""
total_time = -1
previous_layer_end_percentage = 0
previous_layer_end_time = 0
for layer in data:
display_text = str(i)
layer_index = data.index(layer)
lines = layer.split("\n")
for line in lines:
if line.startswith(";LAYER_COUNT:"):
max_layer = line
max_layer = max_layer.split(":")[1]
if self.getSettingValueByKey("startNum") == 0:
max_layer = str(int(max_layer) - 1)
if line.startswith(";LAYER:"):
if show_layers:
if max_layer_setting:
if output_time:
display_text = display_text + "/" + max_layer
else:
display_text = display_text + " of " + max_layer
output_layer = display_text
i += 1
if (line.startswith(";TIME:") or line.startswith(";PRINT.TIME:")) and total_time == -1:
total_time = self.getTimeValue(line)
line_index = lines.index(line)
if show_display:
self.outputTime(lines, line_index, total_time, lcd_text_old, name, time_structure, False)
if output_percentage:
if output_time_method == "m118":
lines.insert(line_index, "M118 A1 P0 action:notification Data Left 0/100")
else:
lines.insert(line_index, "M73 P0")
elif line.startswith(";TIME_ELAPSED:"):
if line in line_set:
continue
line_set[line] = True
if total_time == -1:
continue
current_time = self.getTimeValue(line)
line_index = lines.index(line)
if show_display:
if output_frequency == 0:
self.outputTime(lines, line_index, total_time - current_time, lcd_text, output_layer, time_structure, show_time)
else:
layer_time_delta = int(current_time - previous_layer_end_time)
layer_step_delta = int((current_time - previous_layer_end_time) / output_frequency)
if layer_step_delta != 0:
step = line_index / layer_time_delta
lines_added = 1
for seconds in range(1, layer_time_delta + 1):
line_time = int(previous_layer_end_time + seconds)
if line_time % output_frequency == 0 or line_time == total_time:
time_line_index = int((seconds * step) + lines_added)
self.outputTime(lines, time_line_index, total_time - line_time, lcd_text, output_layer, time_structure, show_time)
lines_added = lines_added + 1
previous_layer_end_time = int(current_time)
if output_percentage:
layer_end_percentage = int((current_time / total_time) * 100)
layer_percentage_delta = layer_end_percentage - previous_layer_end_percentage
if layer_percentage_delta != 0:
step = line_index / layer_percentage_delta
for percentage in range(1, layer_percentage_delta + 1):
percentage_line_index = int((percentage * step) + percentage)
output = min(percentage + previous_layer_end_percentage, 100)
if output_time_method == "m118":
lines.insert(percentage_line_index, "M118 A1 P0 action:notification Data Left {}/100".format(output))
else:
lines.insert(percentage_line_index, "M73 P{}".format(output))
previous_layer_end_percentage = layer_end_percentage
data[layer_index] = "\n".join(lines)
return data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment