From c297b14e03bb74e2e3be6c524cb46ab412c99ad1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 22 Jun 2016 14:40:58 +0200 Subject: [PATCH] Added UMO checkup action CURA-1385 --- .../UMOCheckupMachineAction.py | 145 ++++++++++ .../UMOCheckupMachineAction.qml | 267 ++++++++++++++++++ plugins/UltimakerMachineActions/__init__.py | 3 +- 3 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 plugins/UltimakerMachineActions/UMOCheckupMachineAction.py create mode 100644 plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py new file mode 100644 index 0000000000..392f89682f --- /dev/null +++ b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py @@ -0,0 +1,145 @@ +from cura.MachineAction import MachineAction +from cura.PrinterOutputDevice import PrinterOutputDevice +from UM.Application import Application +from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty + +class UMOCheckupMachineAction(MachineAction): + def __init__(self): + super().__init__("UMOCheckup", "Checkup") + self._qml_url = "UMOCheckupMachineAction.qml" + self._hotend_target_temp = 180 + self._bed_target_temp = 60 + self._output_device = None + self._bed_test_completed = False + self._hotend_test_completed = False + + # Endstop tests + self._x_min_endstop_test_completed = False + self._y_min_endstop_test_completed = False + self._z_min_endstop_test_completed = False + + onBedTestCompleted = pyqtSignal() + onHotendTestCompleted = pyqtSignal() + + onXMinEndstopTestCompleted = pyqtSignal() + onYMinEndstopTestCompleted = pyqtSignal() + onZMinEndstopTestCompleted = pyqtSignal() + + bedTemperatureChanged = pyqtSignal() + hotendTemperatureChanged = pyqtSignal() + + def _getPrinterOutputDevices(self): + return [printer_output_device for printer_output_device in + Application.getInstance().getOutputDeviceManager().getOutputDevices() if + isinstance(printer_output_device, PrinterOutputDevice)] + + def _reset(self): + if self._output_device: + self._output_device.bedTemperatureChanged.disconnect(self.bedTemperatureChanged) + self._output_device.hotendTemperaturesChanged.disconnect(self.hotendTemperatureChanged) + self._output_device.bedTemperatureChanged.disconnect(self._onBedTemperatureChanged) + self._output_device.hotendTemperaturesChanged.disconnect(self._onHotendTemperatureChanged) + self._output_device.endstopStateChanged.disconnect(self._onEndstopStateChanged) + try: + self._output_device.stopPollEndstop() + except AttributeError: # Connection is probably not a USB connection. Something went pretty wrong if this happens. + pass + self._output_device = None + + # Ensure everything is reset (and right signals are emitted again) + self._bed_test_completed = False + self.onBedTestCompleted.emit() + self._hotend_test_completed = False + self.onHotendTestCompleted.emit() + + self._x_min_endstop_test_completed = False + self.onXMinEndstopTestCompleted.emit() + self._y_min_endstop_test_completed = False + self.onYMinEndstopTestCompleted.emit() + self._z_min_endstop_test_completed = False + self.onZMinEndstopTestCompleted.emit() + + @pyqtProperty(bool, notify = onBedTestCompleted) + def bedTestCompleted(self): + return self._bed_test_completed + + @pyqtProperty(bool, notify = onHotendTestCompleted) + def hotendTestCompleted(self): + return self._hotend_test_completed + + @pyqtProperty(bool, notify = onXMinEndstopTestCompleted) + def xMinEndstopTestCompleted(self): + return self._x_min_endstop_test_completed + + @pyqtProperty(bool, notify=onYMinEndstopTestCompleted) + def yMinEndstopTestCompleted(self): + return self._y_min_endstop_test_completed + + @pyqtProperty(bool, notify=onZMinEndstopTestCompleted) + def zMinEndstopTestCompleted(self): + return self._z_min_endstop_test_completed + + @pyqtProperty(float, notify = bedTemperatureChanged) + def bedTemperature(self): + if not self._output_device: + return 0 + return self._output_device.bedTemperature + + @pyqtProperty(float, notify=hotendTemperatureChanged) + def hotendTemperature(self): + if not self._output_device: + return 0 + return self._output_device.hotendTemperatures[0] + + def _onHotendTemperatureChanged(self): + if not self._output_device: + return + if not self._hotend_test_completed: + if self._output_device.hotendTemperatures[0] + 10 > self._hotend_target_temp and self._output_device.hotendTemperatures[0] - 10 < self._hotend_target_temp: + self._hotend_test_completed = True + self.onHotendTestCompleted.emit() + + def _onBedTemperatureChanged(self): + if not self._output_device: + return + if not self._bed_test_completed: + if self._output_device.bedTemperature + 5 > self._bed_target_temp and self._output_device.bedTemperature - 5 < self._bed_target_temp: + self._bed_test_completed = True + self.onBedTestCompleted.emit() + + def _onEndstopStateChanged(self, switch_type, state): + if state: + if switch_type == "x_min": + self._x_min_endstop_test_completed = True + self.onXMinEndstopTestCompleted.emit() + elif switch_type == "y_min": + self._y_min_endstop_test_completed = True + self.onYMinEndstopTestCompleted.emit() + elif switch_type == "z_min": + self._z_min_endstop_test_completed = True + self.onZMinEndstopTestCompleted.emit() + + @pyqtSlot() + def startCheck(self): + output_devices = self._getPrinterOutputDevices() + if output_devices: + self._output_device = output_devices[0] + try: + self._output_device.startPollEndstop() + self._output_device.bedTemperatureChanged.connect(self.bedTemperatureChanged) + self._output_device.hotendTemperaturesChanged.connect(self.hotendTemperatureChanged) + self._output_device.bedTemperatureChanged.connect(self._onBedTemperatureChanged) + self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged) + self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged) + except AttributeError: # Connection is probably not a USB connection. Something went pretty wrong if this happens. + pass + + @pyqtSlot() + def heatupHotend(self): + if self._output_device is not None: + self._output_device.setTargetHotendTemperature(0, self._hotend_target_temp) + + @pyqtSlot() + def heatupBed(self): + if self._output_device is not None: + self._output_device.setTargetBedTemperature(self._bed_target_temp) \ No newline at end of file diff --git a/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml new file mode 100644 index 0000000000..4b280b0e8e --- /dev/null +++ b/plugins/UltimakerMachineActions/UMOCheckupMachineAction.qml @@ -0,0 +1,267 @@ +import UM 1.2 as UM +import Cura 1.0 as Cura + +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.1 + +Cura.MachineAction +{ + Item + { + id: checkupMachineAction + anchors.fill: parent; + UM.I18nCatalog { id: catalog; name:"cura"} + Label + { + id: pageTitle + width: parent.width + text: catalog.i18nc("@title", "Check Printer") + wrapMode: Text.WordWrap + font.pointSize: 18; + } + + Label + { + id: pageDescription + anchors.top: pageTitle.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + width: parent.width + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","It's a good idea to do a few sanity checks on your Ultimaker. You can skip this step if you know your machine is functional"); + } + + Item + { + id: startStopButtons + anchors.top: pageDescription.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.horizontalCenter: parent.horizontalCenter + height: childrenRect.height + width: startCheckButton.width + skipCheckButton.width + UM.Theme.getSize("default_margin").height < checkupMachineAction.width ? startCheckButton.width + skipCheckButton.width + UM.Theme.getSize("default_margin").height : checkupMachineAction.width + Button + { + id: startCheckButton + anchors.top: parent.top + anchors.left: parent.left + text: catalog.i18nc("@action:button","Start Printer Check"); + onClicked: + { + checkupContent.visible = true + startCheckButton.enabled = false + manager.startCheck() + } + } + + Button + { + id: skipCheckButton + anchors.top: parent.width < checkupMachineAction.width ? parent.top : startCheckButton.bottom + anchors.topMargin: parent.width < checkupMachineAction.width ? 0 : UM.Theme.getSize("default_margin").height/2 + anchors.left: parent.width < checkupMachineAction.width ? startCheckButton.right : parent.left + anchors.leftMargin: parent.width < checkupMachineAction.width ? UM.Theme.getSize("default_margin").width : 0 + text: catalog.i18nc("@action:button", "Skip Printer Check"); + onClicked: manager.setFinished() + } + } + + Item + { + id: checkupContent + anchors.top: startStopButtons.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + visible: false + ////////////////////////////////////////////////////////// + Label + { + id: connectionLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: parent.top + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","Connection: ") + } + Label + { + id: connectionStatus + width: checkupMachineAction.rightRow + anchors.left: connectionLabel.right + anchors.top: parent.top + wrapMode: Text.WordWrap + text: Cura.USBPrinterManager.connectedPrinterList.rowCount() > 0 || base.addOriginalProgress.checkUp[0] ? catalog.i18nc("@info:status","Done"):catalog.i18nc("@info:status","Incomplete") + } + ////////////////////////////////////////////////////////// + Label + { + id: endstopXLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: connectionLabel.bottom + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","Min endstop X: ") + } + Label + { + id: endstopXStatus + width: checkupMachineAction.rightRow + anchors.left: endstopXLabel.right + anchors.top: connectionLabel.bottom + wrapMode: Text.WordWrap + text: manager.xMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked") + } + ////////////////////////////////////////////////////////////// + Label + { + id: endstopYLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: endstopXLabel.bottom + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","Min endstop Y: ") + } + Label + { + id: endstopYStatus + width: checkupMachineAction.rightRow + anchors.left: endstopYLabel.right + anchors.top: endstopXLabel.bottom + wrapMode: Text.WordWrap + text: manager.yMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked") + } + ///////////////////////////////////////////////////////////////////// + Label + { + id: endstopZLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: endstopYLabel.bottom + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","Min endstop Z: ") + } + Label + { + id: endstopZStatus + width: checkupMachineAction.rightRow + anchors.left: endstopZLabel.right + anchors.top: endstopYLabel.bottom + wrapMode: Text.WordWrap + text: manager.zMinEndstopTestCompleted ? catalog.i18nc("@info:status","Works") : catalog.i18nc("@info:status","Not checked") + } + //////////////////////////////////////////////////////////// + Label + { + id: nozzleTempLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: endstopZLabel.bottom + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","Nozzle temperature check: ") + } + Label + { + id: nozzleTempStatus + width: checkupMachineAction.rightRow * 0.4 + anchors.top: nozzleTempLabel.top + anchors.left: nozzleTempLabel.right + wrapMode: Text.WordWrap + text: catalog.i18nc("@info:status","Not checked") + } + Item + { + id: nozzleTempButton + width: checkupMachineAction.rightRow * 0.3 + height: nozzleTemp.height + anchors.top: nozzleTempLabel.top + anchors.left: bedTempStatus.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width/2 + Button + { + height: nozzleTemp.height - 2 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: catalog.i18nc("@action:button","Start Heating") + onClicked: + { + manager.heatupHotend() + nozzleTempStatus.text = catalog.i18nc("@info:progress","Checking") + } + } + } + Label + { + id: nozzleTemp + anchors.top: nozzleTempLabel.top + anchors.left: nozzleTempButton.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + width: checkupMachineAction.rightRow * 0.2 + wrapMode: Text.WordWrap + text: manager.hotendTemperature + "°C" + font.bold: true + } + ///////////////////////////////////////////////////////////////////////////// + Label + { + id: bedTempLabel + width: checkupMachineAction.leftRow + anchors.left: parent.left + anchors.top: nozzleTempLabel.bottom + wrapMode: Text.WordWrap + text: catalog.i18nc("@label","bed temperature check:") + } + + Label + { + id: bedTempStatus + width: checkupMachineAction.rightRow * 0.4 + anchors.top: bedTempLabel.top + anchors.left: bedTempLabel.right + wrapMode: Text.WordWrap + text: catalog.i18nc("@info:status","Not checked") + } + Item + { + id: bedTempButton + width: checkupMachineAction.rightRow * 0.3 + height: bedTemp.height + anchors.top: bedTempLabel.top + anchors.left: bedTempStatus.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width/2 + Button + { + height: bedTemp.height - 2 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: catalog.i18nc("@action:button","Start Heating") + onClicked: + { + manager.heatupBed() + bedTempStatus.text = catalog.i18nc("@info:progress","Checking") + } + } + } + Label + { + id: bedTemp + width: checkupMachineAction.rightRow * 0.2 + anchors.top: bedTempLabel.top + anchors.left: bedTempButton.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + wrapMode: Text.WordWrap + text: manager.bedTemperature + "°C" + font.bold: true + } + Label + { + id: resultText + visible: false + anchors.top: bedTemp.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.left: parent.left + width: parent.width + wrapMode: Text.WordWrap + text: catalog.i18nc("@label", "Everything is in order! You're done with your CheckUp.") + } + } + } +} \ No newline at end of file diff --git a/plugins/UltimakerMachineActions/__init__.py b/plugins/UltimakerMachineActions/__init__.py index 08d6db5076..4536ad7623 100644 --- a/plugins/UltimakerMachineActions/__init__.py +++ b/plugins/UltimakerMachineActions/__init__.py @@ -3,6 +3,7 @@ from . import BedLevelMachineAction from . import UpgradeFirmwareMachineAction +from . import UMOCheckupMachineAction from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -19,4 +20,4 @@ def getMetaData(): } def register(app): - return { "machine_action": BedLevelMachineAction.BedLevelMachineAction(), "machine_action": UpgradeFirmwareMachineAction.UpgradeFirmwareMachineAction() } + return { "machine_action": BedLevelMachineAction.BedLevelMachineAction(), "machine_action": UpgradeFirmwareMachineAction.UpgradeFirmwareMachineAction(), "machine_action": UMOCheckupMachineAction.UMOCheckupMachineAction()}