diff --git a/cura/API/ConnectionStatus.py b/cura/API/ConnectionStatus.py new file mode 100644 index 0000000000..0dbe6a4293 --- /dev/null +++ b/cura/API/ConnectionStatus.py @@ -0,0 +1,64 @@ +from typing import Optional + +from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty +from PyQt5.QtNetwork import QNetworkReply + +from UM.TaskManagement.HttpRequestManager import HttpRequestManager +from cura.UltimakerCloud import UltimakerCloudAuthentication + + +class ConnectionStatus(QObject): + """Status info for some web services""" + + UPDATE_INTERVAL = 5.0 # seconds + ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudAuthentication.CuraCloudAPIRoot + "/connect/v1/" + + __instance = None # type: Optional[ConnectionStatus] + + internetReachableChanged = pyqtSignal() + umCloudReachableChanged = pyqtSignal() + + @classmethod + def getInstance(cls, *args, **kwargs) -> "ConnectionStatus": + if cls.__instance is None: + cls.__instance = cls(*args, **kwargs) + return cls.__instance + + 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 + } + + # 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) + def isInternetReachable(self) -> bool: + # Is any of the test urls reachable? + return any(self._statuses.values()) + + 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()): + self.internetReachableChanged.emit() diff --git a/cura/API/__init__.py b/cura/API/__init__.py index 26c9a4c829..bcd4032f97 100644 --- a/cura/API/__init__.py +++ b/cura/API/__init__.py @@ -5,6 +5,7 @@ from typing import Optional, TYPE_CHECKING from PyQt5.QtCore import QObject, pyqtProperty from cura.API.Backups import Backups +from cura.API.ConnectionStatus import ConnectionStatus from cura.API.Interface import Interface from cura.API.Account import Account @@ -45,6 +46,8 @@ class CuraAPI(QObject): # Backups API self._backups = Backups(self._application) + self._connectionStatus = ConnectionStatus() + # Interface API self._interface = Interface(self._application) @@ -55,6 +58,10 @@ class CuraAPI(QObject): def account(self) -> "Account": return self._account + @pyqtProperty(QObject, constant = True) + def connectionStatus(self) -> "ConnectionStatus": + return self._connectionStatus + @property def backups(self) -> "Backups": return self._backups