mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
STAR-322: Fixing printer matching by network key
This commit is contained in:
parent
cd67100097
commit
7e76913736
5 changed files with 97 additions and 64 deletions
|
@ -1,6 +1,6 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, List
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
|
||||
|
@ -8,10 +8,12 @@ from UM import i18nCatalog
|
|||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
from .CloudApiClient import CloudApiClient
|
||||
from .CloudOutputDevice import CloudOutputDevice
|
||||
from .Models.CloudCluster import CloudCluster
|
||||
from .Models.CloudErrorObject import CloudErrorObject
|
||||
from .Utils import findChanges
|
||||
|
||||
|
||||
## The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
|
||||
|
@ -19,7 +21,9 @@ from .Models.CloudErrorObject import CloudErrorObject
|
|||
#
|
||||
# API spec is available on https://api.ultimaker.com/docs/connect/spec/.
|
||||
#
|
||||
|
||||
class CloudOutputDeviceManager:
|
||||
META_CLUSTER_ID = "um_cloud_cluster_id"
|
||||
|
||||
# The interval with which the remote clusters are checked
|
||||
CHECK_CLUSTER_INTERVAL = 5.0 # seconds
|
||||
|
@ -42,59 +46,48 @@ class CloudOutputDeviceManager:
|
|||
|
||||
# When switching machines we check if we have to activate a remote cluster.
|
||||
application.globalContainerStackChanged.connect(self._connectToActiveMachine)
|
||||
|
||||
self.update_timer = QTimer(CuraApplication.getInstance())
|
||||
self.update_timer.setInterval(self.CHECK_CLUSTER_INTERVAL * 1000)
|
||||
self.update_timer.setSingleShot(False)
|
||||
self.update_timer.timeout.connect(self._getRemoteClusters)
|
||||
|
||||
# create a timer to update the remote cluster list
|
||||
self._update_timer = QTimer(application)
|
||||
self._update_timer.setInterval(self.CHECK_CLUSTER_INTERVAL * 1000)
|
||||
self._update_timer.setSingleShot(False)
|
||||
self._update_timer.timeout.connect(self._getRemoteClusters)
|
||||
|
||||
## Gets all remote clusters from the API.
|
||||
def _getRemoteClusters(self) -> None:
|
||||
Logger.log("i", "Retrieving remote clusters")
|
||||
if self._account.isLoggedIn:
|
||||
self._api.getClusters(self._onGetRemoteClustersFinished)
|
||||
|
||||
# Only start the polling timer after the user is authenticated
|
||||
# The first call to _getRemoteClusters comes from self._account.loginStateChanged
|
||||
if not self.update_timer.isActive():
|
||||
self.update_timer.start()
|
||||
# Only start the polling timer after the user is authenticated
|
||||
# The first call to _getRemoteClusters comes from self._account.loginStateChanged
|
||||
if not self._update_timer.isActive():
|
||||
self._update_timer.start()
|
||||
|
||||
## Callback for when the request for getting the clusters. is finished.
|
||||
def _onGetRemoteClustersFinished(self, clusters: List[CloudCluster]) -> None:
|
||||
found_clusters = {c.cluster_id: c for c in clusters}
|
||||
online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudCluster]
|
||||
|
||||
Logger.log("i", "Parsed remote clusters to %s", found_clusters)
|
||||
removed_devices, added_clusters, updates = findChanges(self._remote_clusters, online_clusters)
|
||||
|
||||
known_cluster_ids = set(self._remote_clusters.keys())
|
||||
found_cluster_ids = set(found_clusters.keys())
|
||||
Logger.log("i", "Parsed remote clusters to %s", online_clusters)
|
||||
|
||||
# Remove output devices that are gone
|
||||
for removed_cluster in removed_devices:
|
||||
self._output_device_manager.removeOutputDevice(removed_cluster.key)
|
||||
del self._remote_clusters[removed_cluster.key]
|
||||
|
||||
# Add an output device for each new remote cluster.
|
||||
# We only add when is_online as we don't want the option in the drop down if the cluster is not online.
|
||||
for cluster_id in found_cluster_ids.difference(known_cluster_ids):
|
||||
if found_clusters[cluster_id].is_online:
|
||||
self._addCloudOutputDevice(found_clusters[cluster_id])
|
||||
for added_cluster in added_clusters:
|
||||
device = CloudOutputDevice(self._api, added_cluster.cluster_id, added_cluster.host_name)
|
||||
self._output_device_manager.addOutputDevice(device)
|
||||
self._remote_clusters[added_cluster.cluster_id] = device
|
||||
|
||||
# Remove output devices that are gone
|
||||
for cluster_id in known_cluster_ids.difference(found_cluster_ids):
|
||||
self._removeCloudOutputDevice(found_clusters[cluster_id])
|
||||
for device, cluster in updates:
|
||||
device.host_name = cluster.host_name
|
||||
|
||||
# TODO: not pass clusters that are not online?
|
||||
self._connectToActiveMachine()
|
||||
|
||||
## Adds a CloudOutputDevice for each entry in the remote cluster list from the API.
|
||||
# \param cluster: The cluster that was added.
|
||||
def _addCloudOutputDevice(self, cluster: CloudCluster):
|
||||
device = CloudOutputDevice(self._api, cluster.cluster_id)
|
||||
self._output_device_manager.addOutputDevice(device)
|
||||
self._remote_clusters[cluster.cluster_id] = device
|
||||
|
||||
## Remove a CloudOutputDevice
|
||||
# \param cluster: The cluster that was removed
|
||||
def _removeCloudOutputDevice(self, cluster: CloudCluster):
|
||||
self._output_device_manager.removeOutputDevice(cluster.cluster_id)
|
||||
if cluster.cluster_id in self._remote_clusters:
|
||||
del self._remote_clusters[cluster.cluster_id]
|
||||
|
||||
## Callback for when the active machine was changed by the user or a new remote cluster was found.
|
||||
def _connectToActiveMachine(self) -> None:
|
||||
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
|
@ -102,23 +95,27 @@ class CloudOutputDeviceManager:
|
|||
return
|
||||
|
||||
# Check if the stored cluster_id for the active machine is in our list of remote clusters.
|
||||
stored_cluster_id = active_machine.getMetaDataEntry("um_cloud_cluster_id")
|
||||
if stored_cluster_id in self._remote_clusters.keys():
|
||||
return self._remote_clusters.get(stored_cluster_id).connect()
|
||||
stored_cluster_id = active_machine.getMetaDataEntry(self.META_CLUSTER_ID)
|
||||
if stored_cluster_id in self._remote_clusters:
|
||||
device = self._remote_clusters[stored_cluster_id]
|
||||
if not device.isConnected():
|
||||
device.connect()
|
||||
else:
|
||||
self._connectByNetworkKey(active_machine)
|
||||
|
||||
## Tries to match the
|
||||
def _connectByNetworkKey(self, active_machine: GlobalStack) -> None:
|
||||
# Check if the active printer has a local network connection and match this key to the remote cluster.
|
||||
# The local network key is formatted as ultimakersystem-xxxxxxxxxxxx._ultimaker._tcp.local.
|
||||
# The optional remote host_name is formatted as ultimakersystem-xxxxxxxxxxxx.
|
||||
# This means we can match the two by checking if the host_name is in the network key string.
|
||||
|
||||
local_network_key = active_machine.getMetaDataEntry("um_network_key")
|
||||
if not local_network_key:
|
||||
return
|
||||
|
||||
# TODO: get host_name in the output device so we can iterate here
|
||||
# cluster_id = next(local_network_key in cluster.host_name for cluster in self._remote_clusters.items())
|
||||
# if cluster_id in self._remote_clusters.keys():
|
||||
# return self._remote_clusters.get(cluster_id).connect()
|
||||
device = next((c for c in self._remote_clusters.values() if c.matchesNetworkKey(local_network_key)), None)
|
||||
if not device:
|
||||
return
|
||||
|
||||
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
||||
return device.connect()
|
||||
|
||||
## Handles an API error received from the cloud.
|
||||
# \param errors: The errors received
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue