FirmwareUpdater.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # Copyright (c) 2021 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt5.QtCore import QObject, QUrl, pyqtSignal, pyqtProperty
  4. from enum import IntEnum
  5. from threading import Thread
  6. from typing import Union, Optional
  7. from UM.Logger import Logger
  8. MYPY = False
  9. if MYPY:
  10. from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
  11. class FirmwareUpdater(QObject):
  12. firmwareProgressChanged = pyqtSignal()
  13. firmwareUpdateStateChanged = pyqtSignal()
  14. def __init__(self, output_device: "PrinterOutputDevice", parent: Optional[QObject]) -> None:
  15. super(FirmwareUpdater, self).__init__(parent = parent)
  16. self._output_device = output_device
  17. self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True, name = "FirmwareUpdateThread")
  18. self._firmware_file = ""
  19. self._firmware_progress = 0
  20. self._firmware_update_state = FirmwareUpdateState.idle
  21. def updateFirmware(self, firmware_file: Union[str, QUrl]) -> None:
  22. # the file path could be url-encoded.
  23. if firmware_file.startswith("file://"):
  24. self._firmware_file = QUrl(firmware_file).toLocalFile()
  25. else:
  26. self._firmware_file = firmware_file
  27. if self._firmware_file == "":
  28. self._setFirmwareUpdateState(FirmwareUpdateState.firmware_not_found_error)
  29. return
  30. self._setFirmwareUpdateState(FirmwareUpdateState.updating)
  31. try:
  32. self._update_firmware_thread.start()
  33. except RuntimeError:
  34. Logger.warning("Could not start the update thread, since it's still running!")
  35. def _updateFirmware(self) -> None:
  36. raise NotImplementedError("_updateFirmware needs to be implemented")
  37. def _cleanupAfterUpdate(self) -> None:
  38. """Cleanup after a succesful update"""
  39. # Clean up for next attempt.
  40. self._update_firmware_thread = Thread(target=self._updateFirmware, daemon=True, name = "FirmwareUpdateThread")
  41. self._firmware_file = ""
  42. self._onFirmwareProgress(100)
  43. self._setFirmwareUpdateState(FirmwareUpdateState.completed)
  44. @pyqtProperty(int, notify = firmwareProgressChanged)
  45. def firmwareProgress(self) -> int:
  46. return self._firmware_progress
  47. @pyqtProperty(int, notify=firmwareUpdateStateChanged)
  48. def firmwareUpdateState(self) -> "FirmwareUpdateState":
  49. return self._firmware_update_state
  50. def _setFirmwareUpdateState(self, state: "FirmwareUpdateState") -> None:
  51. if self._firmware_update_state != state:
  52. self._firmware_update_state = state
  53. self.firmwareUpdateStateChanged.emit()
  54. # Callback function for firmware update progress.
  55. def _onFirmwareProgress(self, progress: int, max_progress: int = 100) -> None:
  56. self._firmware_progress = int(progress * 100 / max_progress) # Convert to scale of 0-100
  57. self.firmwareProgressChanged.emit()
  58. class FirmwareUpdateState(IntEnum):
  59. idle = 0
  60. updating = 1
  61. completed = 2
  62. unknown_error = 3
  63. communication_error = 4
  64. io_error = 5
  65. firmware_not_found_error = 6