GenericOutputController.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import TYPE_CHECKING
  4. from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
  5. from PyQt5.QtCore import QTimer
  6. if TYPE_CHECKING:
  7. from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
  8. from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
  9. from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
  10. class GenericOutputController(PrinterOutputController):
  11. def __init__(self, output_device):
  12. super().__init__(output_device)
  13. self._preheat_bed_timer = QTimer()
  14. self._preheat_bed_timer.setSingleShot(True)
  15. self._preheat_bed_timer.timeout.connect(self._onPreheatBedTimerFinished)
  16. self._preheat_printer = None
  17. self._preheat_hotends_timer = QTimer()
  18. self._preheat_hotends_timer.setSingleShot(True)
  19. self._preheat_hotends_timer.timeout.connect(self._onPreheatHotendsTimerFinished)
  20. self._preheat_hotends = set()
  21. self._output_device.printersChanged.connect(self._onPrintersChanged)
  22. self._active_printer = None
  23. def _onPrintersChanged(self):
  24. if self._active_printer:
  25. self._active_printer.stateChanged.disconnect(self._onPrinterStateChanged)
  26. self._active_printer.targetBedTemperatureChanged.disconnect(self._onTargetBedTemperatureChanged)
  27. for extruder in self._active_printer.extruders:
  28. extruder.targetHotendTemperatureChanged.disconnect(self._onTargetHotendTemperatureChanged)
  29. self._active_printer = self._output_device.activePrinter
  30. if self._active_printer:
  31. self._active_printer.stateChanged.connect(self._onPrinterStateChanged)
  32. self._active_printer.targetBedTemperatureChanged.connect(self._onTargetBedTemperatureChanged)
  33. for extruder in self._active_printer.extruders:
  34. extruder.targetHotendTemperatureChanged.connect(self._onTargetHotendTemperatureChanged)
  35. def _onPrinterStateChanged(self):
  36. if self._active_printer.state != "idle":
  37. if self._preheat_bed_timer.isActive():
  38. self._preheat_bed_timer.stop()
  39. self._preheat_printer.updateIsPreheating(False)
  40. if self._preheat_hotends_timer.isActive():
  41. self._preheat_hotends_timer.stop()
  42. for extruder in self._preheat_hotends:
  43. extruder.updateIsPreheating(False)
  44. self._preheat_hotends = set()
  45. def moveHead(self, printer: "PrinterOutputModel", x, y, z, speed):
  46. self._output_device.sendCommand("G91")
  47. self._output_device.sendCommand("G0 X%s Y%s Z%s F%s" % (x, y, z, speed))
  48. self._output_device.sendCommand("G90")
  49. def homeHead(self, printer):
  50. self._output_device.sendCommand("G28 X Y")
  51. def homeBed(self, printer):
  52. self._output_device.sendCommand("G28 Z")
  53. def sendRawCommand(self, printer: "PrinterOutputModel", command: str):
  54. self._output_device.sendCommand(command)
  55. def setJobState(self, job: "PrintJobOutputModel", state: str):
  56. if state == "pause":
  57. self._output_device.pausePrint()
  58. job.updateState("paused")
  59. elif state == "print":
  60. self._output_device.resumePrint()
  61. job.updateState("printing")
  62. elif state == "abort":
  63. self._output_device.cancelPrint()
  64. pass
  65. def setTargetBedTemperature(self, printer: "PrinterOutputModel", temperature: int):
  66. self._output_device.sendCommand("M140 S%s" % temperature)
  67. def _onTargetBedTemperatureChanged(self):
  68. if self._preheat_bed_timer.isActive() and self._preheat_printer.targetBedTemperature == 0:
  69. self._preheat_bed_timer.stop()
  70. self._preheat_printer.updateIsPreheating(False)
  71. def preheatBed(self, printer: "PrinterOutputModel", temperature, duration):
  72. try:
  73. temperature = round(temperature) # The API doesn't allow floating point.
  74. duration = round(duration)
  75. except ValueError:
  76. return # Got invalid values, can't pre-heat.
  77. self.setTargetBedTemperature(printer, temperature=temperature)
  78. self._preheat_bed_timer.setInterval(duration * 1000)
  79. self._preheat_bed_timer.start()
  80. self._preheat_printer = printer
  81. printer.updateIsPreheating(True)
  82. def cancelPreheatBed(self, printer: "PrinterOutputModel"):
  83. self.setTargetBedTemperature(printer, temperature=0)
  84. self._preheat_bed_timer.stop()
  85. printer.updateIsPreheating(False)
  86. def _onPreheatBedTimerFinished(self):
  87. self.setTargetBedTemperature(self._preheat_printer, 0)
  88. self._preheat_printer.updateIsPreheating(False)
  89. def setTargetHotendTemperature(self, printer: "PrinterOutputModel", position: int, temperature: int):
  90. self._output_device.sendCommand("M104 S%s T%s" % (temperature, position))
  91. def _onTargetHotendTemperatureChanged(self):
  92. if not self._preheat_hotends_timer.isActive():
  93. return
  94. for extruder in self._active_printer.extruders:
  95. if extruder in self._preheat_hotends and extruder.targetHotendTemperature == 0:
  96. extruder.updateIsPreheating(False)
  97. self._preheat_hotends.remove(extruder)
  98. if not self._preheat_hotends:
  99. self._preheat_hotends_timer.stop()
  100. def preheatHotend(self, extruder: "ExtruderOutputModel", temperature, duration):
  101. position = extruder.getPosition()
  102. number_of_extruders = len(extruder.getPrinter().extruders)
  103. if position >= number_of_extruders:
  104. return # Got invalid extruder nr, can't pre-heat.
  105. try:
  106. temperature = round(temperature) # The API doesn't allow floating point.
  107. duration = round(duration)
  108. except ValueError:
  109. return # Got invalid values, can't pre-heat.
  110. self.setTargetHotendTemperature(extruder.getPrinter(), position, temperature=temperature)
  111. self._preheat_hotends_timer.setInterval(duration * 1000)
  112. self._preheat_hotends_timer.start()
  113. self._preheat_hotends.add(extruder)
  114. extruder.updateIsPreheating(True)
  115. def cancelPreheatHotend(self, extruder: "ExtruderOutputModel"):
  116. self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), temperature=0)
  117. if extruder in self._preheat_hotends:
  118. extruder.updateIsPreheating(False)
  119. self._preheat_hotends.remove(extruder)
  120. if not self._preheat_hotends and self._preheat_hotends_timer.isActive():
  121. self._preheat_hotends_timer.stop()
  122. def _onPreheatHotendsTimerFinished(self):
  123. for extruder in self._preheat_hotends:
  124. self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), 0)
  125. self._preheat_hotends = set()
  126. # Cancel any ongoing preheating timers, without setting back the temperature to 0
  127. # This can be used eg at the start of a print
  128. def stopPreheatTimers(self):
  129. if self._preheat_hotends_timer.isActive():
  130. for extruder in self._preheat_hotends:
  131. extruder.updateIsPreheating(False)
  132. self._preheat_hotends = set()
  133. self._preheat_hotends_timer.stop()
  134. if self._preheat_bed_timer.isActive():
  135. self._preheat_printer.updateIsPreheating(False)
  136. self._preheat_bed_timer.stop()