DisplayProgressOnLCD.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # Cura PostProcessingPlugin
  2. # Author: Mathias Lyngklip Kjeldgaard, Alexander Gee
  3. # Date: July 31, 2019
  4. # Modified: May 22, 2020
  5. # Description: This plugin displays progress on the LCD. It can output the estimated time remaining and the completion percentage.
  6. from ..Script import Script
  7. import re
  8. import datetime
  9. class DisplayProgressOnLCD(Script):
  10. def __init__(self):
  11. super().__init__()
  12. def getSettingDataString(self):
  13. return """{
  14. "name": "Display Progress On LCD",
  15. "key": "DisplayProgressOnLCD",
  16. "metadata": {},
  17. "version": 2,
  18. "settings":
  19. {
  20. "time_remaining":
  21. {
  22. "label": "Time Remaining",
  23. "description": "When enabled, write Time Left: HHMMSS on the display using M117. This is updated every layer.",
  24. "type": "bool",
  25. "default_value": false
  26. },
  27. "percentage":
  28. {
  29. "label": "Percentage",
  30. "description": "When enabled, set the completion bar percentage on the LCD using Marlin's M73 command.",
  31. "type": "bool",
  32. "default_value": false
  33. }
  34. }
  35. }"""
  36. # Get the time value from a line as a float.
  37. # Example line ;TIME_ELAPSED:1234.6789 or ;TIME:1337
  38. def getTimeValue(self, line):
  39. list_split = re.split(":", line) # Split at ":" so we can get the numerical value
  40. return float(list_split[1]) # Convert the numerical portion to a float
  41. def outputTime(self, lines, line_index, time_left):
  42. # Do some math to get the time left in seconds into the right format. (HH,MM,SS)
  43. m, s = divmod(time_left, 60)
  44. h, m = divmod(m, 60)
  45. # Create the string
  46. current_time_string = "{:d}h{:02d}m{:02d}s".format(int(h), int(m), int(s))
  47. # And now insert that into the GCODE
  48. lines.insert(line_index, "M117 Time Left {}".format(current_time_string))
  49. def execute(self, data):
  50. output_time = self.getSettingValueByKey("time_remaining")
  51. output_percentage = self.getSettingValueByKey("percentage")
  52. line_set = {}
  53. if output_percentage or output_time:
  54. total_time = -1
  55. previous_layer_end_percentage = 0
  56. for layer in data:
  57. layer_index = data.index(layer)
  58. lines = layer.split("\n")
  59. for line in lines:
  60. if line.startswith(";TIME:") and total_time == -1:
  61. # This line represents the total time required to print the gcode
  62. total_time = self.getTimeValue(line)
  63. line_index = lines.index(line)
  64. if output_time:
  65. self.outputTime(lines, line_index, total_time)
  66. if output_percentage:
  67. # Emit 0 percent to sure Marlin knows we are overriding the completion percentage
  68. lines.insert(line_index, "M73 P0")
  69. elif line.startswith(";TIME_ELAPSED:"):
  70. # We've found one of the time elapsed values which are added at the end of layers
  71. # If we have seen this line before then skip processing it. We can see lines multiple times because we are adding
  72. # intermediate percentages before the line being processed. This can cause the current line to shift back and be
  73. # encountered more than once
  74. if line in line_set:
  75. continue
  76. line_set[line] = True
  77. # If total_time was not already found then noop
  78. if total_time == -1:
  79. continue
  80. current_time = self.getTimeValue(line)
  81. line_index = lines.index(line)
  82. if output_time:
  83. # Here we calculate remaining time
  84. self.outputTime(lines, line_index, total_time - current_time)
  85. if output_percentage:
  86. # Calculate percentage value this layer ends at
  87. layer_end_percentage = int((current_time / total_time) * 100)
  88. # Figure out how many percent of the total time is spent in this layer
  89. layer_percentage_delta = layer_end_percentage - previous_layer_end_percentage
  90. # If this layer represents less than 1 percent then we don't need to emit anything, continue to the next layer
  91. if layer_percentage_delta != 0:
  92. # Grab the index of the current line and figure out how many lines represent one percent
  93. step = line_index / layer_percentage_delta
  94. for percentage in range(1, layer_percentage_delta + 1):
  95. # We add the percentage value here as while processing prior lines we will have inserted
  96. # percentage lines before the current one. Failing to do this will upset the spacing
  97. percentage_line_index = int((percentage * step) + percentage)
  98. # Due to integer truncation of the total time value in the gcode the percentage we
  99. # calculate may slightly exceed 100, as that is not valid we cap the value here
  100. output = min(percentage + previous_layer_end_percentage, 100)
  101. # Now insert the sanitized percentage into the GCODE
  102. lines.insert(percentage_line_index, "M73 P{}".format(output))
  103. previous_layer_end_percentage = layer_end_percentage
  104. # Join up the lines for this layer again and store them in the data array
  105. data[layer_index] = "\n".join(lines)
  106. return data