diff --git a/cura/FirmwareUpdater.py b/cura/FirmwareUpdater.py new file mode 100644 index 0000000000..ca5997bfb1 --- /dev/null +++ b/cura/FirmwareUpdater.py @@ -0,0 +1,81 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty + +from UM.Resources import Resources +from cura.PrinterOutputDevice import PrinterOutputDevice + +from enum import IntEnum + +class FirmwareUpdater(QObject): + firmwareProgressChanged = pyqtSignal() + firmwareUpdateStateChanged = pyqtSignal() + + def __init__(self, output_device: PrinterOutputDevice) -> None: + self._output_device = output_device + + self._update_firmware_thread = Thread(target=self._updateFirmware, daemon = True) + + self._firmware_view = None + self._firmware_location = None + self._firmware_progress = 0 + self._firmware_update_state = FirmwareUpdateState.idle + + def updateFirmware(self, file): + # the file path could be url-encoded. + if file.startswith("file://"): + self._firmware_location = QUrl(file).toLocalFile() + else: + self._firmware_location = file + self.showFirmwareInterface() + self.setFirmwareUpdateState(FirmwareUpdateState.updating) + self._update_firmware_thread.start() + + def _updateFirmware(self): + raise NotImplementedError("_updateFirmware needs to be implemented") + + def cleanupAfterUpdate(self): + # Clean up for next attempt. + self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True) + self._firmware_location = "" + self._onFirmwareProgress(100) + self.setFirmwareUpdateState(FirmwareUpdateState.completed) + + ## Show firmware interface. + # This will create the view if its not already created. + def showFirmwareInterface(self): + if self._firmware_view is None: + path = Resources.getPath(self.ResourceTypes.QmlFiles, "FirmwareUpdateWindow.qml") + self._firmware_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) + + self._firmware_view.show() + + @pyqtProperty(float, notify = firmwareProgressChanged) + def firmwareProgress(self): + return self._firmware_progress + + @pyqtProperty(int, notify=firmwareUpdateStateChanged) + def firmwareUpdateState(self): + return self._firmware_update_state + + def setFirmwareUpdateState(self, state): + if self._firmware_update_state != state: + self._firmware_update_state = state + self.firmwareUpdateStateChanged.emit() + + # Callback function for firmware update progress. + def _onFirmwareProgress(self, progress, max_progress = 100): + self._firmware_progress = (progress / max_progress) * 100 # Convert to scale of 0-100 + self.firmwareProgressChanged.emit() + + +class FirmwareUpdateState(IntEnum): + idle = 0 + updating = 1 + completed = 2 + unknown_error = 3 + communication_error = 4 + io_error = 5 + firmware_not_found_error = 6 + diff --git a/plugins/USBPrinting/AvrFirmwareUpdater.py b/plugins/USBPrinting/AvrFirmwareUpdater.py index 681601e3a5..d3028be0e4 100644 --- a/plugins/USBPrinting/AvrFirmwareUpdater.py +++ b/plugins/USBPrinting/AvrFirmwareUpdater.py @@ -1,43 +1,16 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty - from cura.PrinterOutputDevice import PrinterOutputDevice +from cura.FirmwareUpdater import FirmwareUpdater, FirmwareUpdateState from .avr_isp import stk500v2, intelHex -from enum import IntEnum - -class AvrFirmwareUpdater(QObject): - firmwareProgressChanged = pyqtSignal() - firmwareUpdateStateChanged = pyqtSignal() - +class AvrFirmwareUpdater(FirmwareUpdater): def __init__(self, output_device: PrinterOutputDevice) -> None: - self._output_device = output_device - - self._update_firmware_thread = Thread(target=self._updateFirmware, daemon = True) - - self._firmware_view = None - self._firmware_location = None - self._firmware_progress = 0 - self._firmware_update_state = FirmwareUpdateState.idle - - def updateFirmware(self, file): - # the file path could be url-encoded. - if file.startswith("file://"): - self._firmware_location = QUrl(file).toLocalFile() - else: - self._firmware_location = file - self.showFirmwareInterface() - self.setFirmwareUpdateState(FirmwareUpdateState.updating) - self._update_firmware_thread.start() + super().__init__(output_device) def _updateFirmware(self): - # Ensure that other connections are closed. - if self._connection_state != ConnectionState.closed: - self.close() - try: hex_file = intelHex.readHex(self._firmware_location) assert len(hex_file) > 0 @@ -73,49 +46,7 @@ class AvrFirmwareUpdater(QObject): programmer.close() - # Clean up for next attempt. - self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True) - self._firmware_location = "" - self._onFirmwareProgress(100) - self.setFirmwareUpdateState(FirmwareUpdateState.completed) - # Try to re-connect with the machine again, which must be done on the Qt thread, so we use call later. CuraApplication.getInstance().callLater(self.connect) - ## Show firmware interface. - # This will create the view if its not already created. - def showFirmwareInterface(self): - if self._firmware_view is None: - path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml") - self._firmware_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self}) - - self._firmware_view.show() - - @pyqtProperty(float, notify = firmwareProgressChanged) - def firmwareProgress(self): - return self._firmware_progress - - @pyqtProperty(int, notify=firmwareUpdateStateChanged) - def firmwareUpdateState(self): - return self._firmware_update_state - - def setFirmwareUpdateState(self, state): - if self._firmware_update_state != state: - self._firmware_update_state = state - self.firmwareUpdateStateChanged.emit() - - # Callback function for firmware update progress. - def _onFirmwareProgress(self, progress, max_progress = 100): - self._firmware_progress = (progress / max_progress) * 100 # Convert to scale of 0-100 - self.firmwareProgressChanged.emit() - - -class FirmwareUpdateState(IntEnum): - idle = 0 - updating = 1 - completed = 2 - unknown_error = 3 - communication_error = 4 - io_error = 5 - firmware_not_found_error = 6 - + self.cleanupAfterUpdate() diff --git a/plugins/USBPrinting/FirmwareUpdateWindow.qml b/resources/qml/FirmwareUpdateWindow.qml similarity index 100% rename from plugins/USBPrinting/FirmwareUpdateWindow.qml rename to resources/qml/FirmwareUpdateWindow.qml