Consistent naming, some bug fixes

This commit is contained in:
ChrisTerBeke 2019-07-29 17:24:10 +02:00
parent ddd282eef3
commit 1aa70748af
6 changed files with 70 additions and 132 deletions

View file

@ -75,7 +75,7 @@ class DiscoveredPrinter(QObject):
def readableMachineType(self) -> str: def readableMachineType(self) -> str:
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
machine_manager = CuraApplication.getInstance().getMachineManager() machine_manager = CuraApplication.getInstance().getMachineManager()
# In LocalClusterOutputDevice, when it updates a printer information, it updates the machine type using the field # In NetworkOutputDevice, when it updates a printer information, it updates the machine type using the field
# "machine_variant", and for some reason, it's not the machine type ID/codename/... but a human-readable string # "machine_variant", and for some reason, it's not the machine type ID/codename/... but a human-readable string
# like "Ultimaker 3". The code below handles this case. # like "Ultimaker 3". The code below handles this case.
if self._hasHumanReadableMachineTypeName(self._machine_type): if self._hasHumanReadableMachineTypeName(self._machine_type):

View file

@ -118,7 +118,7 @@ class GlobalStack(CuraContainerStack):
## \sa configuredConnectionTypes ## \sa configuredConnectionTypes
def removeConfiguredConnectionType(self, connection_type: int) -> None: def removeConfiguredConnectionType(self, connection_type: int) -> None:
configured_connection_types = self.configuredConnectionTypes configured_connection_types = self.configuredConnectionTypes
if connection_type in self.configured_connection_types: if connection_type in configured_connection_types:
# Store the values as a string. # Store the values as a string.
configured_connection_types.remove(connection_type) configured_connection_types.remove(connection_type)
self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types])) self.setMetaDataEntry("connection_type", ",".join([str(c_type) for c_type in configured_connection_types]))

View file

@ -6,7 +6,6 @@ from PyQt5.QtCore import QTimer
from UM import i18nCatalog from UM import i18nCatalog
from UM.Logger import Logger from UM.Logger import Logger
from UM.Message import Message
from UM.Signal import Signal from UM.Signal import Signal
from cura.API import Account from cura.API import Account
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
@ -54,13 +53,32 @@ class CloudOutputDeviceManager:
self._running = False self._running = False
## Starts running the cloud output device manager, thus periodically requesting cloud data.
def start(self):
if self._running:
return
self._account.loginStateChanged.connect(self._onLoginStateChanged)
# When switching machines we check if we have to activate a remote cluster.
self._application.globalContainerStackChanged.connect(self._connectToActiveMachine)
self._update_timer.timeout.connect(self._getRemoteClusters)
self._onLoginStateChanged(is_logged_in = self._account.isLoggedIn)
## Stops running the cloud output device manager.
def stop(self):
if not self._running:
return
self._account.loginStateChanged.disconnect(self._onLoginStateChanged)
# When switching machines we check if we have to activate a remote cluster.
self._application.globalContainerStackChanged.disconnect(self._connectToActiveMachine)
self._update_timer.timeout.disconnect(self._getRemoteClusters)
self._onLoginStateChanged(is_logged_in = False)
## Force refreshing connections. ## Force refreshing connections.
def refreshConnections(self) -> None: def refreshConnections(self) -> None:
pass self._connectToActiveMachine()
## Called when the uses logs in or out ## Called when the uses logs in or out
def _onLoginStateChanged(self, is_logged_in: bool) -> None: def _onLoginStateChanged(self, is_logged_in: bool) -> None:
Logger.log("d", "Log in state changed to %s", is_logged_in)
if is_logged_in: if is_logged_in:
if not self._update_timer.isActive(): if not self._update_timer.isActive():
self._update_timer.start() self._update_timer.start()
@ -74,18 +92,13 @@ class CloudOutputDeviceManager:
## Gets all remote clusters from the API. ## Gets all remote clusters from the API.
def _getRemoteClusters(self) -> None: def _getRemoteClusters(self) -> None:
Logger.log("d", "Retrieving remote clusters")
self._api.getClusters(self._onGetRemoteClustersFinished) self._api.getClusters(self._onGetRemoteClustersFinished)
## Callback for when the request for getting the clusters. is finished. ## Callback for when the request for getting the clusters. is finished.
def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None:
online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse] online_clusters = {c.cluster_id: c for c in clusters if c.is_online} # type: Dict[str, CloudClusterResponse]
removed_devices, added_clusters, updates = findChanges(self._remote_clusters, online_clusters) removed_devices, added_clusters, updates = findChanges(self._remote_clusters, online_clusters)
Logger.log("d", "Parsed remote clusters to %s", [cluster.toDict() for cluster in online_clusters.values()])
Logger.log("d", "Removed: %s, added: %s, updates: %s", len(removed_devices), len(added_clusters), len(updates))
# Remove output devices that are gone # Remove output devices that are gone
for device in removed_devices: for device in removed_devices:
if device.isConnected(): if device.isConnected():
@ -136,12 +149,7 @@ class CloudOutputDeviceManager:
# The newly added machine is automatically activated. # The newly added machine is automatically activated.
self._application.getMachineManager().addMachine(machine_type_id, group_name) self._application.getMachineManager().addMachine(machine_type_id, group_name)
active_machine = CuraApplication.getInstance().getGlobalContainerStack() self._connectToActiveMachine()
if not active_machine:
return
active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
self._connectToOutputDevice(device, active_machine)
## Callback for when the active machine was changed by the user or a new remote cluster was found. ## Callback for when the active machine was changed by the user or a new remote cluster was found.
def _connectToActiveMachine(self) -> None: def _connectToActiveMachine(self) -> None:
@ -182,31 +190,12 @@ class CloudOutputDeviceManager:
## Connects to an output device and makes sure it is registered in the output device manager. ## Connects to an output device and makes sure it is registered in the output device manager.
def _connectToOutputDevice(self, device: CloudOutputDevice, active_machine: GlobalStack) -> None: def _connectToOutputDevice(self, device: CloudOutputDevice, active_machine: GlobalStack) -> None:
device.connect() device.connect()
self._output_device_manager.addOutputDevice(device) active_machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
active_machine.addConfiguredConnectionType(device.connectionType.value) active_machine.addConfiguredConnectionType(device.connectionType.value)
self._output_device_manager.addOutputDevice(device)
## Handles an API error received from the cloud. ## Handles an API error received from the cloud.
# \param errors: The errors received # \param errors: The errors received
@staticmethod @staticmethod
def _onApiError(errors: List[CloudError] = None) -> None: def _onApiError(errors: List[CloudError] = None) -> None:
Logger.log("w", str(errors)) Logger.log("w", str(errors))
## Starts running the cloud output device manager, thus periodically requesting cloud data.
def start(self):
if self._running:
return
self._account.loginStateChanged.connect(self._onLoginStateChanged)
# When switching machines we check if we have to activate a remote cluster.
self._application.globalContainerStackChanged.connect(self._connectToActiveMachine)
self._update_timer.timeout.connect(self._getRemoteClusters)
self._onLoginStateChanged(is_logged_in = self._account.isLoggedIn)
## Stops running the cloud output device manager.
def stop(self):
if not self._running:
return
self._account.loginStateChanged.disconnect(self._onLoginStateChanged)
# When switching machines we check if we have to activate a remote cluster.
self._application.globalContainerStackChanged.disconnect(self._connectToActiveMachine)
self._update_timer.timeout.disconnect(self._getRemoteClusters)
self._onLoginStateChanged(is_logged_in = False)

View file

@ -20,7 +20,7 @@ from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOut
I18N_CATALOG = i18nCatalog("cura") I18N_CATALOG = i18nCatalog("cura")
class LocalClusterOutputDevice(UltimakerNetworkedPrinterOutputDevice): class NetworkOutputDevice(UltimakerNetworkedPrinterOutputDevice):
activeCameraUrlChanged = pyqtSignal() activeCameraUrlChanged = pyqtSignal()

View file

@ -15,9 +15,10 @@ from UM.Version import Version
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice from cura.PrinterOutput.PrinterOutputDevice import PrinterOutputDevice
from cura.Settings.GlobalStack import GlobalStack
from .ClusterApiClient import ClusterApiClient from .ClusterApiClient import ClusterApiClient
from .LocalClusterOutputDevice import LocalClusterOutputDevice from .NetworkOutputDevice import NetworkOutputDevice
from .ManualPrinterRequest import ManualPrinterRequest from .ManualPrinterRequest import ManualPrinterRequest
@ -38,9 +39,10 @@ class NetworkOutputDeviceManager:
def __init__(self) -> None: def __init__(self) -> None:
# Persistent dict containing the networked clusters. # Persistent dict containing the networked clusters.
self._discovered_devices = {} # type: Dict[str, LocalClusterOutputDevice] self._discovered_devices = {} # type: Dict[str, NetworkOutputDevice]
self._output_device_manager = CuraApplication.getInstance().getOutputDeviceManager() self._output_device_manager = CuraApplication.getInstance().getOutputDeviceManager()
# TODO: move zeroconf stuff to own class
self._zero_conf = None # type: Optional[Zeroconf] self._zero_conf = None # type: Optional[Zeroconf]
self._zero_conf_browser = None # type: Optional[ServiceBrowser] self._zero_conf_browser = None # type: Optional[ServiceBrowser]
self._service_changed_request_queue = None # type: Optional[Queue] self._service_changed_request_queue = None # type: Optional[Queue]
@ -55,30 +57,6 @@ class NetworkOutputDeviceManager:
self.addedNetworkCluster.connect(self._onAddDevice) self.addedNetworkCluster.connect(self._onAddDevice)
self.removedNetworkCluster.connect(self._onRemoveDevice) self.removedNetworkCluster.connect(self._onRemoveDevice)
## Force reset all network device connections.
def refreshConnections(self):
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
um_network_key = active_machine.getMetaDataEntry("um_network_key")
for key in self._discovered_devices:
if key == um_network_key:
if not self._discovered_devices[key].isConnected():
Logger.log("d", "Attempting to connect with [%s]" % key)
# It should already be set, but if it actually connects we know for sure it's supported!
active_machine.addConfiguredConnectionType(self._discovered_devices[key].connectionType.value)
self._discovered_devices[key].connect()
self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
else:
self._onDeviceConnectionStateChanged(key)
else:
if self._discovered_devices[key].isConnected():
Logger.log("d", "Attempting to close connection with [%s]" % key)
self._discovered_devices[key].close()
self._discovered_devices[key].connectionStateChanged.disconnect(
self._onDeviceConnectionStateChanged)
## Start the network discovery. ## Start the network discovery.
def start(self): def start(self):
# The ZeroConf service changed requests are handled in a separate thread so we don't block the UI. # The ZeroConf service changed requests are handled in a separate thread so we don't block the UI.
@ -145,7 +123,6 @@ class NetworkOutputDeviceManager:
if not address: if not address:
address = self._discovered_devices[key].ipAddress address = self._discovered_devices[key].ipAddress
self._onRemoveDevice(key) self._onRemoveDevice(key)
# TODO: self.resetLastManualDevice()
if address in self._manual_instances: if address in self._manual_instances:
manual_printer_request = self._manual_instances.pop(address) manual_printer_request = self._manual_instances.pop(address)
@ -155,6 +132,33 @@ class NetworkOutputDeviceManager:
if manual_printer_request.callback is not None: if manual_printer_request.callback is not None:
CuraApplication.getInstance().callLater(manual_printer_request.callback, False, address) CuraApplication.getInstance().callLater(manual_printer_request.callback, False, address)
## Force reset all network device connections.
def refreshConnections(self):
self._connectToActiveMachine()
## Callback for when the active machine was changed by the user or a new remote cluster was found.
def _connectToActiveMachine(self):
active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine:
return
for device_id in self._discovered_devices:
CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(device_id)
stored_network_key = active_machine.getMetaDataEntry("um_network_key")
if stored_network_key in self._discovered_devices:
device = self._discovered_devices[stored_network_key]
self._connectToOutputDevice(device, active_machine)
## Add a device to the current active machine.
@staticmethod
def _connectToOutputDevice(device: PrinterOutputDevice, active_machine: GlobalStack) -> None:
device.connect()
active_machine.setMetaDataEntry("um_network_key", device.key)
active_machine.setMetaDataEntry("group_name", device.name)
active_machine.addConfiguredConnectionType(device.connectionType.value)
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
## Handles an API error received from the cloud. ## Handles an API error received from the cloud.
# \param errors: The errors received # \param errors: The errors received
def _onApiError(self, errors) -> None: def _onApiError(self, errors) -> None:
@ -212,7 +216,7 @@ class NetworkOutputDeviceManager:
if cluster_size == -1: if cluster_size == -1:
return return
device = LocalClusterOutputDevice(key, address, properties) device = NetworkOutputDevice(key, address, properties)
CuraApplication.getInstance().getDiscoveredPrintersModel().addDiscoveredPrinter( CuraApplication.getInstance().getDiscoveredPrintersModel().addDiscoveredPrinter(
ip_address=address, ip_address=address,
@ -225,28 +229,17 @@ class NetworkOutputDeviceManager:
self._discovered_devices[device.getId()] = device self._discovered_devices[device.getId()] = device
self.discoveredDevicesChanged.emit() self.discoveredDevicesChanged.emit()
self._connectToActiveMachine()
global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
# Ensure that the configured connection type is set.
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(device)
global_container_stack.addConfiguredConnectionType(device.connectionType.value)
device.connect()
device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
## Remove a device. ## Remove a device.
def _onRemoveDevice(self, device_id: str) -> None: def _onRemoveDevice(self, device_id: str) -> None:
device = self._discovered_devices.pop(device_id, None) device = self._discovered_devices.pop(device_id, None)
if device: if not device:
if device.isConnected(): return
device.disconnect() if device.isConnected():
try: device.disconnect()
device.connectionStateChanged.disconnect(self._onDeviceConnectionStateChanged) CuraApplication.getInstance().getDiscoveredPrintersModel().removeDiscoveredPrinter(device.address)
except TypeError: self.discoveredDevicesChanged.emit()
# Disconnect already happened.
pass
CuraApplication.getInstance().getDiscoveredPrintersModel().removeDiscoveredPrinter(device.address)
self.discoveredDevicesChanged.emit()
## Appends a service changed request so later the handling thread will pick it up and processes it. ## Appends a service changed request so later the handling thread will pick it up and processes it.
def _appendServiceChangedRequest(self, zeroconf: Zeroconf, service_type, name: str, def _appendServiceChangedRequest(self, zeroconf: Zeroconf, service_type, name: str,
@ -285,20 +278,6 @@ class NetworkOutputDeviceManager:
for request in reschedule_requests: for request in reschedule_requests:
self._service_changed_request_queue.put(request) self._service_changed_request_queue.put(request)
## Callback handler for when the connection state of a networked device has changed.
def _onDeviceConnectionStateChanged(self, key: str) -> None:
if key not in self._discovered_devices:
return
if self._discovered_devices[key].isConnected():
um_network_key = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key")
if key != um_network_key:
return
CuraApplication.getInstance().getOutputDeviceManager().addOutputDevice(self._discovered_devices[key])
# TODO: self.checkCloudFlowIsPossible(None)
else:
CuraApplication.getInstance().getOutputDeviceManager().removeOutputDevice(key)
## Handler for zeroConf detection. ## Handler for zeroConf detection.
# Return True or False indicating if the process succeeded. # Return True or False indicating if the process succeeded.
# Note that this function can take over 3 seconds to complete. Be careful calling it from the main thread. # Note that this function can take over 3 seconds to complete. Be careful calling it from the main thread.
@ -347,48 +326,18 @@ class NetworkOutputDeviceManager:
self.removedNetworkCluster.emit(str(name)) self.removedNetworkCluster.emit(str(name))
return True return True
def _associateActiveMachineWithPrinterDevice(self, printer_device: Optional[PrinterOutputDevice]) -> None:
if not printer_device:
return
Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)
machine_manager = CuraApplication.getInstance().getMachineManager()
global_container_stack = machine_manager.activeMachine
if not global_container_stack:
return
for machine in machine_manager.getMachinesInGroup(global_container_stack.getMetaDataEntry("group_id")):
machine.setMetaDataEntry("um_network_key", printer_device.key)
machine.setMetaDataEntry("group_name", printer_device.name)
# Delete old authentication data.
Logger.log("d", "Removing old authentication id %s for device %s",
global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key)
machine.removeMetaDataEntry("network_authentication_id")
machine.removeMetaDataEntry("network_authentication_key")
# Ensure that these containers do know that they are configured for network connection
machine.addConfiguredConnectionType(printer_device.connectionType.value)
## Create a machine instance based on the discovered network printer. ## Create a machine instance based on the discovered network printer.
def _createMachineFromDiscoveredPrinter(self, key: str) -> None: def _createMachineFromDiscoveredPrinter(self, key: str) -> None:
discovered_device = self._discovered_devices.get(key) discovered_device = self._discovered_devices.get(key)
if discovered_device is None: if discovered_device is None:
Logger.log("e", "Could not find discovered device with key [%s]", key) Logger.log("e", "Could not find discovered device with key [%s]", key)
return return
group_name = discovered_device.getProperty("name") group_name = discovered_device.getProperty("name")
machine_type_id = discovered_device.getProperty("printer_type") machine_type_id = discovered_device.getProperty("printer_type")
Logger.log("i", "Creating machine from network device with key = [%s], group name = [%s], printer type = [%s]", Logger.log("i", "Creating machine from network device with key = [%s], group name = [%s], printer type = [%s]",
key, group_name, machine_type_id) key, group_name, machine_type_id)
CuraApplication.getInstance().getMachineManager().addMachine(machine_type_id, group_name) CuraApplication.getInstance().getMachineManager().addMachine(machine_type_id, group_name)
# connect the new machine to that network printer self._connectToActiveMachine()
self._associateActiveMachineWithPrinterDevice(discovered_device)
# ensure that the connection states are refreshed.
self.refreshConnections()
## Load the user-configured manual devices from Cura preferences. ## Load the user-configured manual devices from Cura preferences.
def _getStoredManualInstances(self) -> Dict[str, ManualPrinterRequest]: def _getStoredManualInstances(self) -> Dict[str, ManualPrinterRequest]:

View file

@ -13,7 +13,7 @@ from .Models.ClusterMaterial import ClusterMaterial
from .Models.LocalMaterial import LocalMaterial from .Models.LocalMaterial import LocalMaterial
if TYPE_CHECKING: if TYPE_CHECKING:
from .Network.LocalClusterOutputDevice import LocalClusterOutputDevice from .Network.NetworkOutputDevice import NetworkOutputDevice
## Asynchronous job to send material profiles to the printer. ## Asynchronous job to send material profiles to the printer.
@ -21,9 +21,9 @@ if TYPE_CHECKING:
# This way it won't freeze up the interface while sending those materials. # This way it won't freeze up the interface while sending those materials.
class SendMaterialJob(Job): class SendMaterialJob(Job):
def __init__(self, device: "LocalClusterOutputDevice") -> None: def __init__(self, device: "NetworkOutputDevice") -> None:
super().__init__() super().__init__()
self.device = device # type: LocalClusterOutputDevice self.device = device # type: NetworkOutputDevice
## Send the request to the printer and register a callback ## Send the request to the printer and register a callback
def run(self) -> None: def run(self) -> None: