PrinterOutputModel.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject, QVariant, pyqtSlot
  4. from typing import Optional
  5. from UM.Math.Vector import Vector
  6. from cura.PrinterOutput.ConfigurationModel import ConfigurationModel
  7. from cura.PrinterOutput.ExtruderOutputModel import ExtruderOutputModel
  8. MYPY = False
  9. if MYPY:
  10. from cura.PrinterOutput.PrintJobOutputModel import PrintJobOutputModel
  11. from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
  12. class PrinterOutputModel(QObject):
  13. bedTemperatureChanged = pyqtSignal()
  14. targetBedTemperatureChanged = pyqtSignal()
  15. isPreheatingChanged = pyqtSignal()
  16. stateChanged = pyqtSignal()
  17. activePrintJobChanged = pyqtSignal()
  18. nameChanged = pyqtSignal()
  19. headPositionChanged = pyqtSignal()
  20. keyChanged = pyqtSignal()
  21. printerTypeChanged = pyqtSignal()
  22. buildplateChanged = pyqtSignal()
  23. cameraChanged = pyqtSignal()
  24. configurationChanged = pyqtSignal()
  25. def __init__(self, output_controller: "PrinterOutputController", number_of_extruders: int = 1, parent=None, firmware_version = ""):
  26. super().__init__(parent)
  27. self._bed_temperature = -1 # Use -1 for no heated bed.
  28. self._target_bed_temperature = 0
  29. self._name = ""
  30. self._key = "" # Unique identifier
  31. self._controller = output_controller
  32. self._extruders = [ExtruderOutputModel(printer = self, position = i) for i in range(number_of_extruders)]
  33. self._printer_configuration = ConfigurationModel() # Indicates the current configuration setup in this printer
  34. self._head_position = Vector(0, 0, 0)
  35. self._active_print_job = None # type: Optional[PrintJobOutputModel]
  36. self._firmware_version = firmware_version
  37. self._printer_state = "unknown"
  38. self._is_preheating = False
  39. self._printer_type = ""
  40. self._buildplate_name = None
  41. # Update the printer configuration every time any of the extruders changes its configuration
  42. for extruder in self._extruders:
  43. extruder.extruderConfigurationChanged.connect(self._updateExtruderConfiguration)
  44. self._camera = None
  45. @pyqtProperty(str, constant = True)
  46. def firmwareVersion(self):
  47. return self._firmware_version
  48. def setCamera(self, camera):
  49. if self._camera is not camera:
  50. self._camera = camera
  51. self.cameraChanged.emit()
  52. def updateIsPreheating(self, pre_heating):
  53. if self._is_preheating != pre_heating:
  54. self._is_preheating = pre_heating
  55. self.isPreheatingChanged.emit()
  56. @pyqtProperty(bool, notify=isPreheatingChanged)
  57. def isPreheating(self):
  58. return self._is_preheating
  59. @pyqtProperty(QObject, notify=cameraChanged)
  60. def camera(self):
  61. return self._camera
  62. @pyqtProperty(str, notify = printerTypeChanged)
  63. def type(self):
  64. return self._printer_type
  65. def updateType(self, printer_type):
  66. if self._printer_type != printer_type:
  67. self._printer_type = printer_type
  68. self._printer_configuration.printerType = self._printer_type
  69. self.printerTypeChanged.emit()
  70. self.configurationChanged.emit()
  71. @pyqtProperty(str, notify = buildplateChanged)
  72. def buildplate(self):
  73. return self._buildplate_name
  74. def updateBuildplateName(self, buildplate_name):
  75. if self._buildplate_name != buildplate_name:
  76. self._buildplate_name = buildplate_name
  77. self._printer_configuration.buildplateConfiguration = self._buildplate_name
  78. self.buildplateChanged.emit()
  79. self.configurationChanged.emit()
  80. @pyqtProperty(str, notify=keyChanged)
  81. def key(self):
  82. return self._key
  83. def updateKey(self, key: str):
  84. if self._key != key:
  85. self._key = key
  86. self.keyChanged.emit()
  87. @pyqtSlot()
  88. def homeHead(self):
  89. self._controller.homeHead(self)
  90. @pyqtSlot()
  91. def homeBed(self):
  92. self._controller.homeBed(self)
  93. @pyqtSlot(str)
  94. def sendRawCommand(self, command: str):
  95. self._controller.sendRawCommand(self, command)
  96. @pyqtProperty("QVariantList", constant = True)
  97. def extruders(self):
  98. return self._extruders
  99. @pyqtProperty(QVariant, notify = headPositionChanged)
  100. def headPosition(self):
  101. return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position_z}
  102. def updateHeadPosition(self, x, y, z):
  103. if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:
  104. self._head_position = Vector(x, y, z)
  105. self.headPositionChanged.emit()
  106. @pyqtProperty(float, float, float)
  107. @pyqtProperty(float, float, float, float)
  108. def setHeadPosition(self, x, y, z, speed = 3000):
  109. self.updateHeadPosition(x, y, z)
  110. self._controller.setHeadPosition(self, x, y, z, speed)
  111. @pyqtProperty(float)
  112. @pyqtProperty(float, float)
  113. def setHeadX(self, x, speed = 3000):
  114. self.updateHeadPosition(x, self._head_position.y, self._head_position.z)
  115. self._controller.setHeadPosition(self, x, self._head_position.y, self._head_position.z, speed)
  116. @pyqtProperty(float)
  117. @pyqtProperty(float, float)
  118. def setHeadY(self, y, speed = 3000):
  119. self.updateHeadPosition(self._head_position.x, y, self._head_position.z)
  120. self._controller.setHeadPosition(self, self._head_position.x, y, self._head_position.z, speed)
  121. @pyqtProperty(float)
  122. @pyqtProperty(float, float)
  123. def setHeadZ(self, z, speed = 3000):
  124. self.updateHeadPosition(self._head_position.x, self._head_position.y, z)
  125. self._controller.setHeadPosition(self, self._head_position.x, self._head_position.y, z, speed)
  126. @pyqtSlot(float, float, float)
  127. @pyqtSlot(float, float, float, float)
  128. def moveHead(self, x = 0, y = 0, z = 0, speed = 3000):
  129. self._controller.moveHead(self, x, y, z, speed)
  130. ## Pre-heats the heated bed of the printer.
  131. #
  132. # \param temperature The temperature to heat the bed to, in degrees
  133. # Celsius.
  134. # \param duration How long the bed should stay warm, in seconds.
  135. @pyqtSlot(float, float)
  136. def preheatBed(self, temperature, duration):
  137. self._controller.preheatBed(self, temperature, duration)
  138. @pyqtSlot()
  139. def cancelPreheatBed(self):
  140. self._controller.cancelPreheatBed(self)
  141. def getController(self):
  142. return self._controller
  143. @pyqtProperty(str, notify=nameChanged)
  144. def name(self):
  145. return self._name
  146. def setName(self, name):
  147. self._setName(name)
  148. self.updateName(name)
  149. def updateName(self, name):
  150. if self._name != name:
  151. self._name = name
  152. self.nameChanged.emit()
  153. ## Update the bed temperature. This only changes it locally.
  154. def updateBedTemperature(self, temperature):
  155. if self._bed_temperature != temperature:
  156. self._bed_temperature = temperature
  157. self.bedTemperatureChanged.emit()
  158. def updateTargetBedTemperature(self, temperature):
  159. if self._target_bed_temperature != temperature:
  160. self._target_bed_temperature = temperature
  161. self.targetBedTemperatureChanged.emit()
  162. ## Set the target bed temperature. This ensures that it's actually sent to the remote.
  163. @pyqtSlot(int)
  164. def setTargetBedTemperature(self, temperature):
  165. self._controller.setTargetBedTemperature(self, temperature)
  166. self.updateTargetBedTemperature(temperature)
  167. def updateActivePrintJob(self, print_job):
  168. if self._active_print_job != print_job:
  169. old_print_job = self._active_print_job
  170. if print_job is not None:
  171. print_job.updateAssignedPrinter(self)
  172. self._active_print_job = print_job
  173. if old_print_job is not None:
  174. old_print_job.updateAssignedPrinter(None)
  175. self.activePrintJobChanged.emit()
  176. def updateState(self, printer_state):
  177. if self._printer_state != printer_state:
  178. self._printer_state = printer_state
  179. self.stateChanged.emit()
  180. @pyqtProperty(QObject, notify = activePrintJobChanged)
  181. def activePrintJob(self):
  182. return self._active_print_job
  183. @pyqtProperty(str, notify=stateChanged)
  184. def state(self):
  185. return self._printer_state
  186. @pyqtProperty(int, notify = bedTemperatureChanged)
  187. def bedTemperature(self):
  188. return self._bed_temperature
  189. @pyqtProperty(int, notify=targetBedTemperatureChanged)
  190. def targetBedTemperature(self):
  191. return self._target_bed_temperature
  192. # Does the printer support pre-heating the bed at all
  193. @pyqtProperty(bool, constant=True)
  194. def canPreHeatBed(self):
  195. if self._controller:
  196. return self._controller.can_pre_heat_bed
  197. return False
  198. # Does the printer support pre-heating the bed at all
  199. @pyqtProperty(bool, constant=True)
  200. def canPreHeatHotends(self):
  201. if self._controller:
  202. return self._controller.can_pre_heat_hotends
  203. return False
  204. # Does the printer support sending raw G-code at all
  205. @pyqtProperty(bool, constant=True)
  206. def canSendRawGcode(self):
  207. if self._controller:
  208. return self._controller.can_send_raw_gcode
  209. return False
  210. # Does the printer support pause at all
  211. @pyqtProperty(bool, constant=True)
  212. def canPause(self):
  213. if self._controller:
  214. return self._controller.can_pause
  215. return False
  216. # Does the printer support abort at all
  217. @pyqtProperty(bool, constant=True)
  218. def canAbort(self):
  219. if self._controller:
  220. return self._controller.can_abort
  221. return False
  222. # Does the printer support manual control at all
  223. @pyqtProperty(bool, constant=True)
  224. def canControlManually(self):
  225. if self._controller:
  226. return self._controller.can_control_manually
  227. return False
  228. # Returns the configuration (material, variant and buildplate) of the current printer
  229. @pyqtProperty(QObject, notify = configurationChanged)
  230. def printerConfiguration(self):
  231. if self._printer_configuration.isValid():
  232. return self._printer_configuration
  233. return None
  234. def _updateExtruderConfiguration(self):
  235. self._printer_configuration.extruderConfigurations = [extruder.extruderConfiguration for extruder in self._extruders]
  236. self.configurationChanged.emit()