From b2b10f693d412634a15a83099483895d13943f01 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 6 May 2021 15:43:39 +0200 Subject: [PATCH 1/2] Rate limit the sending of materials to networked ultimakers Some ultimakers tend to choke if you try and send a lot of materials in one go. Previously we would also always send the materials on the main thread, which would also make the interface freeze a bit. That should no longer happen. The implementation of this is not really great, but since this is a hotfix i've opted to change as little as possible. CURA-8224 --- .../src/Network/SendMaterialJob.py | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py index 28f6b29dd9..4607f5206e 100644 --- a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py @@ -7,26 +7,34 @@ from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest from UM.Job import Job from UM.Logger import Logger from cura.CuraApplication import CuraApplication +from cura.Utils.Threading import call_on_qt_thread from ..Models.Http.ClusterMaterial import ClusterMaterial from ..Models.LocalMaterial import LocalMaterial from ..Messages.MaterialSyncMessage import MaterialSyncMessage +import time +import threading + if TYPE_CHECKING: from .LocalClusterOutputDevice import LocalClusterOutputDevice class SendMaterialJob(Job): + """Asynchronous job to send material profiles to the printer. This way it won't freeze up the interface while sending those materials. """ - - def __init__(self, device: "LocalClusterOutputDevice") -> None: super().__init__() self.device = device # type: LocalClusterOutputDevice + self._send_material_thread = threading.Thread(target=self._sendMissingMaterials) + self._send_material_thread.setDaemon(True) + + self._remote_materials = {} # type: Dict[str, ClusterMaterial] + def run(self) -> None: """Send the request to the printer and register a callback""" @@ -36,9 +44,15 @@ class SendMaterialJob(Job): """Callback for when the remote materials were returned.""" remote_materials_by_guid = {material.guid: material for material in materials} - self._sendMissingMaterials(remote_materials_by_guid) + self._remote_materials = remote_materials_by_guid + # It's not the nicest way to do it, but if we don't handle this in a thread + # we are blocking the main interface (even though the original call was done in a job) + # This should really be refactored so that calculating the list of materials that need to be sent + # to the printer is done outside of the job (and running the job actually sends the materials) + # TODO: Fix this hack that was introduced for 4.9.1 + self._send_material_thread.start() - def _sendMissingMaterials(self, remote_materials_by_guid: Dict[str, ClusterMaterial]) -> None: + def _sendMissingMaterials(self) -> None: """Determine which materials should be updated and send them to the printer. :param remote_materials_by_guid: The remote materials by GUID. @@ -47,7 +61,7 @@ class SendMaterialJob(Job): if len(local_materials_by_guid) == 0: Logger.log("d", "There are no local materials to synchronize with the printer.") return - material_ids_to_send = self._determineMaterialsToSend(local_materials_by_guid, remote_materials_by_guid) + material_ids_to_send = self._determineMaterialsToSend(local_materials_by_guid, self._remote_materials) if len(material_ids_to_send) == 0: Logger.log("d", "There are no remote materials to update.") return @@ -96,7 +110,11 @@ class SendMaterialJob(Job): file_name = os.path.basename(file_path) self._sendMaterialFile(file_path, file_name, root_material_id) + time.sleep(1) # Throttle the sending a bit. + # This needs to be called on the QT thread since the onFinished needs to happen + # in the same thread as where the network manager is located (aka; main thread) + @call_on_qt_thread def _sendMaterialFile(self, file_path: str, file_name: str, material_id: str) -> None: """Send a single material file to the printer. From 16c5fdd798a087fcfdee069c6c21c83f3376c61d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 6 May 2021 16:27:09 +0200 Subject: [PATCH 2/2] Code style: Spaces around binary operators Contrbutes to issue CURA-8224. --- plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py index 4607f5206e..96a2b78e8f 100644 --- a/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py +++ b/plugins/UM3NetworkPrinting/src/Network/SendMaterialJob.py @@ -30,7 +30,7 @@ class SendMaterialJob(Job): super().__init__() self.device = device # type: LocalClusterOutputDevice - self._send_material_thread = threading.Thread(target=self._sendMissingMaterials) + self._send_material_thread = threading.Thread(target = self._sendMissingMaterials) self._send_material_thread.setDaemon(True) self._remote_materials = {} # type: Dict[str, ClusterMaterial]