DiscoverUM3Action.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. from cura.MachineAction import MachineAction
  2. from UM.Application import Application
  3. from UM.PluginRegistry import PluginRegistry
  4. from UM.Logger import Logger
  5. from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QUrl, QObject
  6. from PyQt5.QtQml import QQmlComponent, QQmlContext
  7. import os.path
  8. import time
  9. from UM.i18n import i18nCatalog
  10. catalog = i18nCatalog("cura")
  11. class DiscoverUM3Action(MachineAction):
  12. def __init__(self):
  13. super().__init__("DiscoverUM3Action", catalog.i18nc("@action","Connect via Network"))
  14. self._qml_url = "DiscoverUM3Action.qml"
  15. self._network_plugin = None
  16. self.__additional_components_context = None
  17. self.__additional_component = None
  18. self.__additional_components_view = None
  19. Application.getInstance().engineCreatedSignal.connect(self._createAdditionalComponentsView)
  20. self._last_zeroconf_event_time = time.time()
  21. self._zeroconf_change_grace_period = 0.25 # Time to wait after a zeroconf service change before allowing a zeroconf reset
  22. printersChanged = pyqtSignal()
  23. @pyqtSlot()
  24. def startDiscovery(self):
  25. if not self._network_plugin:
  26. self._network_plugin = Application.getInstance().getOutputDeviceManager().getOutputDevicePlugin("UM3NetworkPrinting")
  27. self._network_plugin.printerListChanged.connect(self._onPrinterDiscoveryChanged)
  28. self.printersChanged.emit()
  29. ## Re-filters the list of printers.
  30. @pyqtSlot()
  31. def reset(self):
  32. self.printersChanged.emit()
  33. @pyqtSlot()
  34. def restartDiscovery(self):
  35. # Ensure that there is a bit of time after a printer has been discovered.
  36. # This is a work around for an issue with Qt 5.5.1 up to Qt 5.7 which can segfault if we do this too often.
  37. # It's most likely that the QML engine is still creating delegates, where the python side already deleted or
  38. # garbage collected the data.
  39. # Whatever the case, waiting a bit ensures that it doesn't crash.
  40. if time.time() - self._last_zeroconf_event_time > self._zeroconf_change_grace_period:
  41. if not self._network_plugin:
  42. self.startDiscovery()
  43. else:
  44. self._network_plugin.startDiscovery()
  45. @pyqtSlot(str, str)
  46. def removeManualPrinter(self, key, address):
  47. if not self._network_plugin:
  48. return
  49. self._network_plugin.removeManualPrinter(key, address)
  50. @pyqtSlot(str, str)
  51. def setManualPrinter(self, key, address):
  52. if key != "":
  53. # This manual printer replaces a current manual printer
  54. self._network_plugin.removeManualPrinter(key)
  55. if address != "":
  56. self._network_plugin.addManualPrinter(address)
  57. def _onPrinterDiscoveryChanged(self, *args):
  58. self._last_zeroconf_event_time = time.time()
  59. self.printersChanged.emit()
  60. @pyqtProperty("QVariantList", notify = printersChanged)
  61. def foundDevices(self):
  62. if self._network_plugin:
  63. if Application.getInstance().getGlobalContainerStack():
  64. global_printer_type = Application.getInstance().getGlobalContainerStack().getBottom().getId()
  65. else:
  66. global_printer_type = "unknown"
  67. printers = list(self._network_plugin.getPrinters().values())
  68. # TODO; There are still some testing printers that don't have a correct printer type, so don't filter out unkown ones just yet.
  69. printers = [printer for printer in printers if printer.printerType == global_printer_type or printer.printerType == "unknown"]
  70. printers.sort(key = lambda k: k.name)
  71. return printers
  72. else:
  73. return []
  74. @pyqtSlot(str)
  75. def setKey(self, key):
  76. global_container_stack = Application.getInstance().getGlobalContainerStack()
  77. if global_container_stack:
  78. meta_data = global_container_stack.getMetaData()
  79. if "um_network_key" in meta_data:
  80. global_container_stack.setMetaDataEntry("um_network_key", key)
  81. # Delete old authentication data.
  82. Logger.log("d", "Removing old authentication id %s for device %s", global_container_stack.getMetaDataEntry("network_authentication_id", None), key)
  83. global_container_stack.removeMetaDataEntry("network_authentication_id")
  84. global_container_stack.removeMetaDataEntry("network_authentication_key")
  85. else:
  86. global_container_stack.addMetaDataEntry("um_network_key", key)
  87. if self._network_plugin:
  88. # Ensure that the connection states are refreshed.
  89. self._network_plugin.reCheckConnections()
  90. @pyqtSlot(result = str)
  91. def getStoredKey(self):
  92. global_container_stack = Application.getInstance().getGlobalContainerStack()
  93. if global_container_stack:
  94. meta_data = global_container_stack.getMetaData()
  95. if "um_network_key" in meta_data:
  96. return global_container_stack.getMetaDataEntry("um_network_key")
  97. return ""
  98. @pyqtSlot()
  99. def loadConfigurationFromPrinter(self):
  100. machine_manager = Application.getInstance().getMachineManager()
  101. hotend_ids = machine_manager.printerOutputDevices[0].hotendIds
  102. for index in range(len(hotend_ids)):
  103. machine_manager.printerOutputDevices[0].hotendIdChanged.emit(index, hotend_ids[index])
  104. material_ids = machine_manager.printerOutputDevices[0].materialIds
  105. for index in range(len(material_ids)):
  106. machine_manager.printerOutputDevices[0].materialIdChanged.emit(index, material_ids[index])
  107. def _createAdditionalComponentsView(self):
  108. Logger.log("d", "Creating additional ui components for UM3.")
  109. path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"), "UM3InfoComponents.qml"))
  110. self.__additional_component = QQmlComponent(Application.getInstance()._engine, path)
  111. # We need access to engine (although technically we can't)
  112. self.__additional_components_context = QQmlContext(Application.getInstance()._engine.rootContext())
  113. self.__additional_components_context.setContextProperty("manager", self)
  114. self.__additional_components_view = self.__additional_component.create(self.__additional_components_context)
  115. if not self.__additional_components_view:
  116. Logger.log("w", "Could not create ui components for UM3.")
  117. return
  118. Application.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton"))
  119. Application.getInstance().addAdditionalComponent("machinesDetailPane", self.__additional_components_view.findChild(QObject, "networkPrinterConnectionInfo"))