From ddf312eca5687a14f31382534cc156e3688a5e45 Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 15 Jun 2020 09:34:56 +0200 Subject: [PATCH 1/3] Refactor the connection status to be informed by the autosync The autosync, which happens every 30 seconds, will now also inform the connection status when the get request succeeds or fails, which is an indicator of whether the internet is reachable. CURA-7492 --- cura/API/ConnectionStatus.py | 50 ++++--------------- .../src/Cloud/CloudOutputDeviceManager.py | 7 ++- 2 files changed, 17 insertions(+), 40 deletions(-) diff --git a/cura/API/ConnectionStatus.py b/cura/API/ConnectionStatus.py index 007f03fdd1..2e73639b45 100644 --- a/cura/API/ConnectionStatus.py +++ b/cura/API/ConnectionStatus.py @@ -1,22 +1,16 @@ from typing import Optional -from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty -from PyQt5.QtNetwork import QNetworkReply +from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty -from UM.TaskManagement.HttpRequestManager import HttpRequestManager -from cura.UltimakerCloud import UltimakerCloudConstants +from UM.Logger import Logger class ConnectionStatus(QObject): """Status info for some web services""" - UPDATE_INTERVAL = 10.0 # seconds - ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudConstants.CuraCloudAPIRoot + "/connect/v1/" - __instance = None # type: Optional[ConnectionStatus] internetReachableChanged = pyqtSignal() - umCloudReachableChanged = pyqtSignal() @classmethod def getInstance(cls, *args, **kwargs) -> "ConnectionStatus": @@ -27,38 +21,16 @@ class ConnectionStatus(QObject): def __init__(self, parent: Optional["QObject"] = None): super().__init__(parent) - self._http = HttpRequestManager.getInstance() - self._statuses = { - self.ULTIMAKER_CLOUD_STATUS_URL: True, - "http://example.com": True - } + self._is_internet_reachable: bool = True - # Create a timer for automatic updates - self._update_timer = QTimer() - self._update_timer.setInterval(int(self.UPDATE_INTERVAL * 1000)) - # The timer is restarted automatically - self._update_timer.setSingleShot(False) - self._update_timer.timeout.connect(self._update) - self._update_timer.start() - - @pyqtProperty(bool, notify=internetReachableChanged) + @pyqtProperty(bool, notify = internetReachableChanged) def isInternetReachable(self) -> bool: - # Is any of the test urls reachable? - return any(self._statuses.values()) + return self._is_internet_reachable - def _update(self): - for url in self._statuses.keys(): - self._http.get( - url = url, - callback = self._statusCallback, - error_callback = self._statusCallback, - timeout = 5 - ) - - def _statusCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None): - url = reply.request().url().toString() - prev_statuses = self._statuses.copy() - self._statuses[url] = HttpRequestManager.replyIndicatesSuccess(reply, error) - - if any(self._statuses.values()) != any(prev_statuses.values()): + def setOnlineStatus(self, new_status: bool): + old_status = self._is_internet_reachable + self._is_internet_reachable = new_status + if old_status != new_status: + Logger.debug( + "Connection status has been set to {}".format("online" if self._is_internet_reachable else "offline")) self.internetReachableChanged.emit() diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 33c9caba05..852af0de4c 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -104,8 +104,10 @@ class CloudOutputDeviceManager: self._api.getClusters(self._onGetRemoteClustersFinished, self._onGetRemoteClusterFailed) def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: - """Callback for when the request for getting the clusters is finished.""" + """Callback for when the request for getting the clusters is successful and finished.""" + # Remote clusters were successfully retrieved, which means that the computer is online + CuraApplication.getInstance().getCuraAPI().connectionStatus.setOnlineStatus(True) self._um_cloud_printers = {m.getMetaDataEntry(self.META_CLUSTER_ID): m for m in CuraApplication.getInstance().getContainerRegistry().findContainerStacks( type = "machine") if m.getMetaDataEntry(self.META_CLUSTER_ID, None)} @@ -150,6 +152,9 @@ class CloudOutputDeviceManager: def _onGetRemoteClusterFailed(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None: self._syncing = False self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR) + # If getting the remote clusters fails, then the cloud printers are unreachable, so we need to inform the + # connection status + CuraApplication.getInstance().getCuraAPI().connectionStatus.setOnlineStatus(False) def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None: """**Synchronously** create machines for discovered devices From 9bf9bf9a3f87dbe09ac27e5c82f19bd70ef3039c Mon Sep 17 00:00:00 2001 From: Kostas Karmas Date: Mon, 15 Jun 2020 09:45:39 +0200 Subject: [PATCH 2/3] Fix typing CURA-7492 --- cura/API/ConnectionStatus.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/API/ConnectionStatus.py b/cura/API/ConnectionStatus.py index 2e73639b45..483284d1c7 100644 --- a/cura/API/ConnectionStatus.py +++ b/cura/API/ConnectionStatus.py @@ -18,16 +18,16 @@ class ConnectionStatus(QObject): cls.__instance = cls(*args, **kwargs) return cls.__instance - def __init__(self, parent: Optional["QObject"] = None): + def __init__(self, parent: Optional["QObject"] = None) -> None: super().__init__(parent) - self._is_internet_reachable: bool = True + self._is_internet_reachable = True # type: bool @pyqtProperty(bool, notify = internetReachableChanged) def isInternetReachable(self) -> bool: return self._is_internet_reachable - def setOnlineStatus(self, new_status: bool): + def setOnlineStatus(self, new_status: bool) -> None: old_status = self._is_internet_reachable self._is_internet_reachable = new_status if old_status != new_status: From 994f9fbde7230e90d557621533b21ccb50f2c278 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 15 Jun 2020 11:39:06 +0200 Subject: [PATCH 3/3] Re-implement ConnectionStatus by adding a pyqtSignal to HttpRequestMgr and using ConnectionStatus as proxy for it. CURA-7492 --- cura/API/ConnectionStatus.py | 23 +++++++++++-------- .../src/Cloud/CloudOutputDeviceManager.py | 5 ---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cura/API/ConnectionStatus.py b/cura/API/ConnectionStatus.py index 483284d1c7..36f804e3cf 100644 --- a/cura/API/ConnectionStatus.py +++ b/cura/API/ConnectionStatus.py @@ -2,11 +2,16 @@ from typing import Optional from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty -from UM.Logger import Logger +from UM.TaskManagement.HttpRequestManager import HttpRequestManager class ConnectionStatus(QObject): - """Status info for some web services""" + """Provides an estimation of whether internet is reachable + + Estimation is updated with every request through HttpRequestManager. + Acts as a proxy to HttpRequestManager.internetReachableChanged without + exposing the HttpRequestManager in its entirety. + """ __instance = None # type: Optional[ConnectionStatus] @@ -21,16 +26,16 @@ class ConnectionStatus(QObject): def __init__(self, parent: Optional["QObject"] = None) -> None: super().__init__(parent) - self._is_internet_reachable = True # type: bool + manager = HttpRequestManager.getInstance() + self._is_internet_reachable = manager.isInternetReachable # type: bool + manager.internetReachableChanged.connect(self._onInternetReachableChanged) @pyqtProperty(bool, notify = internetReachableChanged) def isInternetReachable(self) -> bool: return self._is_internet_reachable - def setOnlineStatus(self, new_status: bool) -> None: - old_status = self._is_internet_reachable - self._is_internet_reachable = new_status - if old_status != new_status: - Logger.debug( - "Connection status has been set to {}".format("online" if self._is_internet_reachable else "offline")) + def _onInternetReachableChanged(self, reachable: bool): + if reachable != self._is_internet_reachable: + self._is_internet_reachable = reachable self.internetReachableChanged.emit() + diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index 852af0de4c..da200c7fc2 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -106,8 +106,6 @@ class CloudOutputDeviceManager: def _onGetRemoteClustersFinished(self, clusters: List[CloudClusterResponse]) -> None: """Callback for when the request for getting the clusters is successful and finished.""" - # Remote clusters were successfully retrieved, which means that the computer is online - CuraApplication.getInstance().getCuraAPI().connectionStatus.setOnlineStatus(True) self._um_cloud_printers = {m.getMetaDataEntry(self.META_CLUSTER_ID): m for m in CuraApplication.getInstance().getContainerRegistry().findContainerStacks( type = "machine") if m.getMetaDataEntry(self.META_CLUSTER_ID, None)} @@ -152,9 +150,6 @@ class CloudOutputDeviceManager: def _onGetRemoteClusterFailed(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None: self._syncing = False self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR) - # If getting the remote clusters fails, then the cloud printers are unreachable, so we need to inform the - # connection status - CuraApplication.getInstance().getCuraAPI().connectionStatus.setOnlineStatus(False) def _onDevicesDiscovered(self, clusters: List[CloudClusterResponse]) -> None: """**Synchronously** create machines for discovered devices