DiscoverUM3Action.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import os.path
  4. import time
  5. from typing import Optional
  6. from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject
  7. from UM.PluginRegistry import PluginRegistry
  8. from UM.Logger import Logger
  9. from UM.i18n import i18nCatalog
  10. from cura.CuraApplication import CuraApplication
  11. from cura.MachineAction import MachineAction
  12. from .UM3OutputDevicePlugin import UM3OutputDevicePlugin
  13. catalog = i18nCatalog("cura")
  14. class DiscoverUM3Action(MachineAction):
  15. discoveredDevicesChanged = pyqtSignal()
  16. def __init__(self) -> None:
  17. super().__init__("DiscoverUM3Action", catalog.i18nc("@action","Connect via Network"))
  18. self._qml_url = "DiscoverUM3Action.qml"
  19. self._network_plugin = None #type: Optional[UM3OutputDevicePlugin]
  20. self.__additional_components_view = None #type: Optional[QObject]
  21. CuraApplication.getInstance().engineCreatedSignal.connect(self._createAdditionalComponentsView)
  22. self._last_zero_conf_event_time = time.time() #type: float
  23. # Time to wait after a zero-conf service change before allowing a zeroconf reset
  24. self._zero_conf_change_grace_period = 0.25 #type: float
  25. @pyqtSlot()
  26. def startDiscovery(self):
  27. if not self._network_plugin:
  28. Logger.log("d", "Starting device discovery.")
  29. self._network_plugin = CuraApplication.getInstance().getOutputDeviceManager().getOutputDevicePlugin("UM3NetworkPrinting")
  30. self._network_plugin.discoveredDevicesChanged.connect(self._onDeviceDiscoveryChanged)
  31. self.discoveredDevicesChanged.emit()
  32. ## Re-filters the list of devices.
  33. @pyqtSlot()
  34. def reset(self):
  35. Logger.log("d", "Reset the list of found devices.")
  36. if self._network_plugin:
  37. self._network_plugin.resetLastManualDevice()
  38. self.discoveredDevicesChanged.emit()
  39. @pyqtSlot()
  40. def restartDiscovery(self):
  41. # Ensure that there is a bit of time after a printer has been discovered.
  42. # 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.
  43. # It's most likely that the QML engine is still creating delegates, where the python side already deleted or
  44. # garbage collected the data.
  45. # Whatever the case, waiting a bit ensures that it doesn't crash.
  46. if time.time() - self._last_zero_conf_event_time > self._zero_conf_change_grace_period:
  47. if not self._network_plugin:
  48. self.startDiscovery()
  49. else:
  50. self._network_plugin.startDiscovery()
  51. @pyqtSlot(str, str)
  52. def removeManualDevice(self, key, address):
  53. if not self._network_plugin:
  54. return
  55. self._network_plugin.removeManualDevice(key, address)
  56. @pyqtSlot(str, str)
  57. def setManualDevice(self, key, address):
  58. if key != "":
  59. # This manual printer replaces a current manual printer
  60. self._network_plugin.removeManualDevice(key)
  61. if address != "":
  62. self._network_plugin.addManualDevice(address)
  63. def _onDeviceDiscoveryChanged(self, *args):
  64. self._last_zero_conf_event_time = time.time()
  65. self.discoveredDevicesChanged.emit()
  66. @pyqtProperty("QVariantList", notify = discoveredDevicesChanged)
  67. def foundDevices(self):
  68. if self._network_plugin:
  69. printers = list(self._network_plugin.getDiscoveredDevices().values())
  70. printers.sort(key = lambda k: k.name)
  71. return printers
  72. else:
  73. return []
  74. @pyqtSlot(str)
  75. def setGroupName(self, group_name: str) -> None:
  76. Logger.log("d", "Attempting to set the group name of the active machine to %s", group_name)
  77. global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
  78. if global_container_stack:
  79. meta_data = global_container_stack.getMetaData()
  80. if "connect_group_name" in meta_data:
  81. previous_connect_group_name = meta_data["connect_group_name"]
  82. global_container_stack.setMetaDataEntry("connect_group_name", group_name)
  83. # Find all the places where there is the same group name and change it accordingly
  84. CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connect_group_name", value = previous_connect_group_name, new_value = group_name)
  85. else:
  86. global_container_stack.addMetaDataEntry("connect_group_name", group_name)
  87. global_container_stack.addMetaDataEntry("hidden", False)
  88. if self._network_plugin:
  89. # Ensure that the connection states are refreshed.
  90. self._network_plugin.reCheckConnections()
  91. @pyqtSlot(str)
  92. def setKey(self, key: str) -> None:
  93. Logger.log("d", "Attempting to set the network key of the active machine to %s", key)
  94. global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
  95. if global_container_stack:
  96. meta_data = global_container_stack.getMetaData()
  97. if "um_network_key" in meta_data:
  98. previous_network_key= meta_data["um_network_key"]
  99. global_container_stack.setMetaDataEntry("um_network_key", key)
  100. # Delete old authentication data.
  101. Logger.log("d", "Removing old authentication id %s for device %s", global_container_stack.getMetaDataEntry("network_authentication_id", None), key)
  102. global_container_stack.removeMetaDataEntry("network_authentication_id")
  103. global_container_stack.removeMetaDataEntry("network_authentication_key")
  104. CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = key)
  105. else:
  106. global_container_stack.addMetaDataEntry("um_network_key", key)
  107. if self._network_plugin:
  108. # Ensure that the connection states are refreshed.
  109. self._network_plugin.reCheckConnections()
  110. @pyqtSlot(result = str)
  111. def getStoredKey(self) -> str:
  112. global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
  113. if global_container_stack:
  114. meta_data = global_container_stack.getMetaData()
  115. if "um_network_key" in meta_data:
  116. return global_container_stack.getMetaDataEntry("um_network_key")
  117. return ""
  118. @pyqtSlot(result = str)
  119. def getLastManualEntryKey(self) -> str:
  120. if self._network_plugin:
  121. return self._network_plugin.getLastManualDevice()
  122. return ""
  123. @pyqtSlot(str, result = bool)
  124. def existsKey(self, key: str) -> bool:
  125. return CuraApplication.getInstance().getMachineManager().existNetworkInstances(network_key = key)
  126. @pyqtSlot()
  127. def loadConfigurationFromPrinter(self) -> None:
  128. machine_manager = CuraApplication.getInstance().getMachineManager()
  129. hotend_ids = machine_manager.printerOutputDevices[0].hotendIds
  130. for index in range(len(hotend_ids)):
  131. machine_manager.printerOutputDevices[0].hotendIdChanged.emit(index, hotend_ids[index])
  132. material_ids = machine_manager.printerOutputDevices[0].materialIds
  133. for index in range(len(material_ids)):
  134. machine_manager.printerOutputDevices[0].materialIdChanged.emit(index, material_ids[index])
  135. def _createAdditionalComponentsView(self) -> None:
  136. Logger.log("d", "Creating additional ui components for UM3.")
  137. # Create networking dialog
  138. path = os.path.join(PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"), "UM3InfoComponents.qml")
  139. self.__additional_components_view = CuraApplication.getInstance().createQmlComponent(path, {"manager": self})
  140. if not self.__additional_components_view:
  141. Logger.log("w", "Could not create ui components for UM3.")
  142. return
  143. # Create extra components
  144. CuraApplication.getInstance().addAdditionalComponent("monitorButtons", self.__additional_components_view.findChild(QObject, "networkPrinterConnectButton"))
  145. CuraApplication.getInstance().addAdditionalComponent("machinesDetailPane", self.__additional_components_view.findChild(QObject, "networkPrinterConnectionInfo"))