From 4adf4dceb8528098c0c832a9be10eb1b8333ac1d Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Fri, 3 Apr 2020 12:02:27 +0200 Subject: [PATCH 01/11] Automatically make discovered printers available to use. instead of the list of available printers to be connected CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index ccc64f8073..308d6ca0c5 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from typing import Dict, List, Optional + from PyQt5.QtCore import QTimer from UM import i18nCatalog @@ -11,7 +12,6 @@ from cura.API import Account from cura.CuraApplication import CuraApplication from cura.Settings.CuraStackBuilder import CuraStackBuilder from cura.Settings.GlobalStack import GlobalStack - from .CloudApiClient import CloudApiClient from .CloudOutputDevice import CloudOutputDevice from ..Models.Http.CloudClusterResponse import CloudClusterResponse @@ -100,15 +100,13 @@ class CloudOutputDeviceManager: def _onDeviceDiscovered(self, cluster_data: CloudClusterResponse) -> None: device = CloudOutputDevice(self._api, cluster_data) - CuraApplication.getInstance().getDiscoveredPrintersModel().addDiscoveredPrinter( - ip_address=device.key, - key=device.getId(), - name=device.getName(), - create_callback=self._createMachineFromDiscoveredDevice, - machine_type=device.printerType, - device=device - ) self._remote_clusters[device.getId()] = device + + # Create a machine if we don't already have it. Do not make it the active machine. + meta_data = {self.META_CLUSTER_ID: device.key} + if CuraApplication.getInstance().getMachineManager().getMachine(device.printerType, meta_data) is None: + self._createMachineFromDiscoveredDevice(device.getId(), activate = False) + self.discoveredDevicesChanged.emit() self._connectToActiveMachine() @@ -134,19 +132,22 @@ class CloudOutputDeviceManager: output_device_manager.removeOutputDevice(device.key) self.discoveredDevicesChanged.emit() - def _createMachineFromDiscoveredDevice(self, key: str) -> None: + def _createMachineFromDiscoveredDevice(self, key: str, activate: bool = True) -> None: device = self._remote_clusters[key] if not device: return - # Create a new machine and activate it. + # Create a new machine. # We do not use use MachineManager.addMachine here because we need to set the cluster ID before activating it. new_machine = CuraStackBuilder.createMachine(device.name, device.printerType) if not new_machine: Logger.log("e", "Failed creating a new machine") return new_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) - CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId()) + + if activate: + CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId()) + self._connectToOutputDevice(device, new_machine) ## Callback for when the active machine was changed by the user or a new remote cluster was found. From a80a5f36ff2b5ebce243daa7d279323249efbbf8 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 6 Apr 2020 13:44:48 +0200 Subject: [PATCH 02/11] Add a Message informing users of progress on cloud syncing printers. CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 308d6ca0c5..64661aefba 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -7,6 +7,7 @@ from PyQt5.QtCore import QTimer from UM import i18nCatalog from UM.Logger import Logger # To log errors talking to the API. +from UM.Message import Message from UM.Signal import Signal from cura.API import Account from cura.CuraApplication import CuraApplication @@ -87,28 +88,59 @@ class CloudOutputDeviceManager: ## Callback for when the request for getting the clusters is finished. def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: + new_clusters = [] online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse] for device_id, cluster_data in online_clusters.items(): if device_id not in self._remote_clusters: - self._onDeviceDiscovered(cluster_data) + new_clusters.append(cluster_data) else: self._onDiscoveredDeviceUpdated(cluster_data) + self._onDevicesDiscovered(new_clusters) + removed_device_keys = set(self._remote_clusters.keys()) - set(online_clusters.keys()) for device_id in removed_device_keys: self._onDiscoveredDeviceRemoved(device_id) - def _onDeviceDiscovered(self, cluster_data: CloudClusterResponse) -> None: - device = CloudOutputDevice(self._api, cluster_data) - self._remote_clusters[device.getId()] = device + if new_clusters or removed_device_keys: + self.discoveredDevicesChanged.emit() + if removed_device_keys: + # If the removed device was active we should connect to the new active device + self._connectToActiveMachine() - # Create a machine if we don't already have it. Do not make it the active machine. - meta_data = {self.META_CLUSTER_ID: device.key} - if CuraApplication.getInstance().getMachineManager().getMachine(device.printerType, meta_data) is None: + def _onDevicesDiscovered(self, clusters: [CloudClusterResponse]) -> None: + new_devices = [] + for cluster_data in clusters: + device = CloudOutputDevice(self._api, cluster_data) + # Create a machine if we don't already have it. Do not make it the active machine. + meta_data = {self.META_CLUSTER_ID: device.key} + if CuraApplication.getInstance().getMachineManager().getMachine(device.printerType, meta_data) is None: + new_devices.append(device) + + if not new_devices: + return + + message = Message( + title = self.I18N_CATALOG.i18ncp("info:status", "New cloud printer detected", "New cloud printers detected", len(new_devices)), + progress = 0, + lifetime = 0 + ) + message.show() + + for idx, device in enumerate(new_devices): + message.setText(self.I18N_CATALOG.i18nc("info:status", "Adding printer '{}' from your account", device.name)) + message.setProgress((idx / len(new_devices)) * 100) + CuraApplication.getInstance().processEvents() + self._remote_clusters[device.getId()] = device self._createMachineFromDiscoveredDevice(device.getId(), activate = False) - self.discoveredDevicesChanged.emit() - self._connectToActiveMachine() + message.setProgress(100) + message.setText(self.I18N_CATALOG.i18ncp( + "info:status", + "{} cloud printer added from your account", + "{} cloud printers added from your account", + len(new_devices) + )) def _onDiscoveredDeviceUpdated(self, cluster_data: CloudClusterResponse) -> None: device = self._remote_clusters.get(cluster_data.cluster_id) @@ -130,7 +162,6 @@ class CloudOutputDeviceManager: output_device_manager = CuraApplication.getInstance().getOutputDeviceManager() if device.key in output_device_manager.getOutputDeviceIds(): output_device_manager.removeOutputDevice(device.key) - self.discoveredDevicesChanged.emit() def _createMachineFromDiscoveredDevice(self, key: str, activate: bool = True) -> None: device = self._remote_clusters[key] From 52ef794c4db5197c99c8bf4c848f3889c12978bc Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 6 Apr 2020 14:49:45 +0200 Subject: [PATCH 03/11] Add a Message informing users of progress on cloud syncing printers. CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 64661aefba..2393b535aa 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -109,6 +109,13 @@ class CloudOutputDeviceManager: self._connectToActiveMachine() def _onDevicesDiscovered(self, clusters: [CloudClusterResponse]) -> None: + """**Synchronously** create machines for discovered devices + + Any new machines are made available to the user. + May take a long time to complete. As this code needs access to the Application + and blocks the GIL, creating a Job for this would not make sense. + Shows a Message informing the user of progress. + """ new_devices = [] for cluster_data in clusters: device = CloudOutputDevice(self._api, cluster_data) @@ -121,26 +128,37 @@ class CloudOutputDeviceManager: return message = Message( - title = self.I18N_CATALOG.i18ncp("info:status", "New cloud printer detected", "New cloud printers detected", len(new_devices)), + title = self.I18N_CATALOG.i18ncp( + "info:status", + "New cloud printer detected from your Ultimaker account", + "New cloud printers detected from your Ultimaker account", + len(new_devices) + ), progress = 0, lifetime = 0 ) message.show() for idx, device in enumerate(new_devices): - message.setText(self.I18N_CATALOG.i18nc("info:status", "Adding printer '{}' from your account", device.name)) - message.setProgress((idx / len(new_devices)) * 100) + message_text = self.I18N_CATALOG.i18nc( + "info:status", "Adding printer {} ({}) from your account", + device.name, + device.printerTypeName + ) + message.setText(message_text) + if len(new_devices) > 1: + message.setProgress((idx / len(new_devices)) * 100) CuraApplication.getInstance().processEvents() self._remote_clusters[device.getId()] = device self._createMachineFromDiscoveredDevice(device.getId(), activate = False) - message.setProgress(100) - message.setText(self.I18N_CATALOG.i18ncp( + message.setProgress(None) + message_text = self.I18N_CATALOG.i18nc( "info:status", - "{} cloud printer added from your account", - "{} cloud printers added from your account", - len(new_devices) - )) + "Cloud printers added from your account:\n{}", + "\n".join(["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices]) + ) + message.setText(message_text) def _onDiscoveredDeviceUpdated(self, cluster_data: CloudClusterResponse) -> None: device = self._remote_clusters.get(cluster_data.cluster_id) From b141bb139eb58d57e79d6162edc28e28d83de17f Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 6 Apr 2020 15:04:39 +0200 Subject: [PATCH 04/11] Update documentation of _connectToActiveMachine CURA-7055 --- .../UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 2393b535aa..95a6a73610 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -199,8 +199,9 @@ class CloudOutputDeviceManager: self._connectToOutputDevice(device, new_machine) - ## Callback for when the active machine was changed by the user or a new remote cluster was found. def _connectToActiveMachine(self) -> None: + """Callback for when the active machine was changed by the user""" + active_machine = CuraApplication.getInstance().getGlobalContainerStack() if not active_machine: return From 0ec3e0972b84cb3bbde88b17614176361aea5fd7 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 6 Apr 2020 18:01:57 +0200 Subject: [PATCH 05/11] Add an image to the cloud printer sync message CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 95a6a73610..91c1ba645c 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -1,6 +1,6 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. - +import os from typing import Dict, List, Optional from PyQt5.QtCore import QTimer @@ -127,6 +127,11 @@ class CloudOutputDeviceManager: if not new_devices: return + image_path = os.path.join( + CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "", + "resources", "svg", "cloud-flow-completed.svg" + ) + message = Message( title = self.I18N_CATALOG.i18ncp( "info:status", @@ -135,7 +140,8 @@ class CloudOutputDeviceManager: len(new_devices) ), progress = 0, - lifetime = 0 + lifetime = 0, + image_source = image_path ) message.show() From 22a06fca3b2491c0bde8ea3875f461656d6802ee Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 7 Apr 2020 13:50:24 +0200 Subject: [PATCH 06/11] Shorten new cloud printers message So the plural form also fits on one line CURA-7055 --- .../UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 91c1ba645c..674ad0960b 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -135,8 +135,8 @@ class CloudOutputDeviceManager: message = Message( title = self.I18N_CATALOG.i18ncp( "info:status", - "New cloud printer detected from your Ultimaker account", - "New cloud printers detected from your Ultimaker account", + "New printer detected from your Ultimaker account", + "New printers detected from your Ultimaker account", len(new_devices) ), progress = 0, From 99b4b86052328212d683ee2ab1194d539679dec7 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 7 Apr 2020 14:33:59 +0200 Subject: [PATCH 07/11] Display max 3 printer names in the printer discover message CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 674ad0960b..3a1fa7af51 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -127,6 +127,8 @@ class CloudOutputDeviceManager: if not new_devices: return + new_devices.sort(key = lambda x: x.name.lower()) + image_path = os.path.join( CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "", "resources", "svg", "cloud-flow-completed.svg" @@ -159,10 +161,20 @@ class CloudOutputDeviceManager: self._createMachineFromDiscoveredDevice(device.getId(), activate = False) message.setProgress(None) + + max_disp_devices = 3 + if len(new_devices) > max_disp_devices: + num_hidden = len(new_devices) - max_disp_devices + 1 + device_name_list = ["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices[0:num_hidden]] + device_name_list.append(self.I18N_CATALOG.i18nc("info:hidden list items", "- and {} others", num_hidden)) + device_names = "\n".join(device_name_list) + else: + device_names = "\n".join(["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices]) + message_text = self.I18N_CATALOG.i18nc( "info:status", "Cloud printers added from your account:\n{}", - "\n".join(["- {} ({})".format(device.name, device.printerTypeName) for device in new_devices]) + device_names ) message.setText(message_text) From ff017e6a5202ec515463f486a7b039a687758643 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 7 Apr 2020 14:44:24 +0200 Subject: [PATCH 08/11] Remove unnecessary call to remove printer from qt model Since cloud printers are not added to that model anymore CURA-7055 --- plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 3a1fa7af51..c1d8fdb6d2 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -194,7 +194,6 @@ class CloudOutputDeviceManager: if not device: return device.close() - CuraApplication.getInstance().getDiscoveredPrintersModel().removeDiscoveredPrinter(device.key) output_device_manager = CuraApplication.getInstance().getOutputDeviceManager() if device.key in output_device_manager.getOutputDeviceIds(): output_device_manager.removeOutputDevice(device.key) From 33b3bb77c3f1f777a8e29015a219105231ba96d7 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 7 Apr 2020 16:58:08 +0200 Subject: [PATCH 09/11] Fix typing List wasn't added, so mypy borked. CURA-7055 --- .../UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index c1d8fdb6d2..20d4c0d9c3 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -108,7 +108,7 @@ class CloudOutputDeviceManager: # If the removed device was active we should connect to the new active device self._connectToActiveMachine() - def _onDevicesDiscovered(self, clusters: [CloudClusterResponse]) -> None: + def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None: """**Synchronously** create machines for discovered devices Any new machines are made available to the user. From d1337c9e22a9fbe7f02a5785f2962b28a913bde2 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 9 Apr 2020 16:39:47 +0200 Subject: [PATCH 10/11] Prevent printer from being added twice if it's in cloud and local CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 20d4c0d9c3..e2249a621c 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -120,8 +120,11 @@ class CloudOutputDeviceManager: for cluster_data in clusters: device = CloudOutputDevice(self._api, cluster_data) # Create a machine if we don't already have it. Do not make it the active machine. - meta_data = {self.META_CLUSTER_ID: device.key} - if CuraApplication.getInstance().getMachineManager().getMachine(device.printerType, meta_data) is None: + machine_manager = CuraApplication.getInstance().getMachineManager() + + # We only need to add it if it wasn't already added by "local" network or by cloud. + if machine_manager.getMachine(device.printerType, {self.META_CLUSTER_ID: device.key}) is None \ + and machine_manager.getMachine(device.printerType, {self.META_NETWORK_KEY: cluster_data.host_name + "*"}) is None: # The host name is part of the network key. new_devices.append(device) if not new_devices: From 783b8e08ff8e7289d436f1cc6c9299781c3f2454 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 14 Apr 2020 11:40:04 +0200 Subject: [PATCH 11/11] Only schedule a new cloud sync after the previous one finished Prevents concurrent syncs, which would create duplicate printers. Also doxygen comments to docstring CURA-7055 --- .../src/Cloud/CloudOutputDeviceManager.py | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index e2249a621c..0b65f55cfd 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -18,10 +18,12 @@ from .CloudOutputDevice import CloudOutputDevice from ..Models.Http.CloudClusterResponse import CloudClusterResponse -## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters. -# Keeping all cloud related logic in this class instead of the UM3OutputDevicePlugin results in more readable code. -# API spec is available on https://api.ultimaker.com/docs/connect/spec/. class CloudOutputDeviceManager: + """The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters. + + Keeping all cloud related logic in this class instead of the UM3OutputDevicePlugin results in more readable code. + API spec is available on https://api.ultimaker.com/docs/connect/spec/. + """ META_CLUSTER_ID = "um_cloud_cluster_id" META_NETWORK_KEY = "um_network_key" @@ -45,14 +47,16 @@ class CloudOutputDeviceManager: # Create a timer to update the remote cluster list self._update_timer = QTimer() self._update_timer.setInterval(int(self.CHECK_CLUSTER_INTERVAL * 1000)) - self._update_timer.setSingleShot(False) + # The timer is restarted explicitly after an update was processed. This prevents 2 concurrent updates + self._update_timer.setSingleShot(True) self._update_timer.timeout.connect(self._getRemoteClusters) # Ensure we don't start twice. self._running = False - ## Starts running the cloud output device manager, thus periodically requesting cloud data. def start(self): + """Starts running the cloud output device manager, thus periodically requesting cloud data.""" + if self._running: return if not self._account.isLoggedIn: @@ -62,8 +66,9 @@ class CloudOutputDeviceManager: self._update_timer.start() self._getRemoteClusters() - ## Stops running the cloud output device manager. def stop(self): + """Stops running the cloud output device manager.""" + if not self._running: return self._running = False @@ -71,23 +76,27 @@ class CloudOutputDeviceManager: self._update_timer.stop() self._onGetRemoteClustersFinished([]) # Make sure we remove all cloud output devices. - ## Force refreshing connections. def refreshConnections(self) -> None: + """Force refreshing connections.""" + self._connectToActiveMachine() - ## Called when the uses logs in or out def _onLoginStateChanged(self, is_logged_in: bool) -> None: + """Called when the uses logs in or out""" + if is_logged_in: self.start() else: self.stop() - ## Gets all remote clusters from the API. def _getRemoteClusters(self) -> None: + """Gets all remote clusters from the API.""" + self._api.getClusters(self._onGetRemoteClustersFinished) - ## Callback for when the request for getting the clusters is finished. def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: + """Callback for when the request for getting the clusters is finished.""" + new_clusters = [] online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse] for device_id, cluster_data in online_clusters.items(): @@ -107,6 +116,8 @@ class CloudOutputDeviceManager: if removed_device_keys: # If the removed device was active we should connect to the new active device self._connectToActiveMachine() + # Schedule a new update + self._update_timer.start() def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None: """**Synchronously** create machines for discovered devices @@ -240,8 +251,9 @@ class CloudOutputDeviceManager: # Remove device if it is not meant for the active machine. output_device_manager.removeOutputDevice(device.key) - ## Connects to an output device and makes sure it is registered in the output device manager. def _connectToOutputDevice(self, device: CloudOutputDevice, machine: GlobalStack) -> None: + """Connects to an output device and makes sure it is registered in the output device manager.""" + machine.setName(device.name) machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) machine.setMetaDataEntry("group_name", device.name)