mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-14 10:17:52 -06:00
Add firmware check
Contributes to CL-1222
This commit is contained in:
parent
2a3a1d6e35
commit
f2ddb2808f
3 changed files with 59 additions and 46 deletions
|
@ -517,6 +517,12 @@ class MachineManager(QObject):
|
||||||
return self._global_container_stack.getId()
|
return self._global_container_stack.getId()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = globalContainerChanged)
|
||||||
|
def activeMachineFirmwareVersion(self) -> str:
|
||||||
|
if not self._printer_output_devices[0]:
|
||||||
|
return ""
|
||||||
|
return self._printer_output_devices[0].firmwareVersion
|
||||||
|
|
||||||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||||
def printerConnected(self) -> bool:
|
def printerConnected(self) -> bool:
|
||||||
return bool(self._printer_output_devices)
|
return bool(self._printer_output_devices)
|
||||||
|
|
|
@ -45,7 +45,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
activePrinterChanged = pyqtSignal()
|
activePrinterChanged = pyqtSignal()
|
||||||
activeCameraUrlChanged = pyqtSignal()
|
activeCameraUrlChanged = pyqtSignal()
|
||||||
receivedPrintJobsChanged = pyqtSignal()
|
receivedPrintJobsChanged = pyqtSignal()
|
||||||
cloudFlowIsPossible = pyqtSignal()
|
|
||||||
|
|
||||||
# Notify can only use signals that are defined by the class that they are in, not inherited ones.
|
# Notify can only use signals that are defined by the class that they are in, not inherited ones.
|
||||||
# Therefore we create a private signal used to trigger the printersChanged signal.
|
# Therefore we create a private signal used to trigger the printersChanged signal.
|
||||||
|
@ -68,18 +67,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
|
|
||||||
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorStage.qml")
|
self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../resources/qml/MonitorStage.qml")
|
||||||
|
|
||||||
self._account = self._application.getCuraAPI().account
|
|
||||||
|
|
||||||
# Trigger the printersChanged signal when the private signal is triggered
|
# Trigger the printersChanged signal when the private signal is triggered
|
||||||
self.printersChanged.connect(self._clusterPrintersChanged)
|
self.printersChanged.connect(self._clusterPrintersChanged)
|
||||||
|
|
||||||
# Check if cloud flow is possible when user logs in
|
|
||||||
self._account.loginStateChanged.connect(self.checkCloudFlowIsPossible)
|
|
||||||
|
|
||||||
# Listen for when Cloud Flow is possible
|
|
||||||
self.cloudFlowIsPossible.connect(self._onCloudFlowPossible)
|
|
||||||
|
|
||||||
|
|
||||||
self._accepts_commands = True # type: bool
|
self._accepts_commands = True # type: bool
|
||||||
|
|
||||||
# Cluster does not have authentication, so default to authenticated
|
# Cluster does not have authentication, so default to authenticated
|
||||||
|
@ -677,40 +667,6 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
job = SendMaterialJob(device = self)
|
job = SendMaterialJob(device = self)
|
||||||
job.run()
|
job.run()
|
||||||
|
|
||||||
## Check if the prerequsites are in place to start the cloud flow
|
|
||||||
def checkCloudFlowIsPossible(self):
|
|
||||||
Logger.log("d", "Checking if cloud connection is possible...")
|
|
||||||
|
|
||||||
# Check #1: User is logged in with an Ultimaker account
|
|
||||||
if not self._account.isLoggedIn:
|
|
||||||
Logger.log("d", "Cloud Flow not possible: User not logged in!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check #2: Machine has a network connection
|
|
||||||
if not self._application.getMachineManager().activeMachineHasActiveNetworkConnection:
|
|
||||||
Logger.log("d", "Cloud Flow not possible: Machine is not connected!")
|
|
||||||
# TODO: This should only be network connections, not cloud connections
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check #3: Machine has correct firmware version
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Logger.log("d", "Cloud Flow not possible: Machine does not have necessary firmware!")
|
|
||||||
# return
|
|
||||||
|
|
||||||
# TODO: Check if machine is already set up to be cloud
|
|
||||||
|
|
||||||
self.cloudFlowIsPossible.emit()
|
|
||||||
Logger.log("d", "Cloud flow is ready to go!")
|
|
||||||
|
|
||||||
def _onCloudFlowPossible(self):
|
|
||||||
# Cloud flow is possible, so show the message
|
|
||||||
self._start_cloud_flow_message = Message(i18n_catalog.i18nc("@info:status", "Chain so thin when a breeze roll by, man it flow... man it flow..."))
|
|
||||||
self._start_cloud_flow_message.show()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def loadJsonFromReply(reply: QNetworkReply) -> Optional[List[Dict[str, Any]]]:
|
def loadJsonFromReply(reply: QNetworkReply) -> Optional[List[Dict[str, Any]]]:
|
||||||
try:
|
try:
|
||||||
result = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
result = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
||||||
|
|
|
@ -7,17 +7,20 @@ from time import time
|
||||||
|
|
||||||
from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
|
from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo
|
||||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
|
from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QObject
|
||||||
|
|
||||||
from cura.CuraApplication import CuraApplication
|
from cura.CuraApplication import CuraApplication
|
||||||
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
from UM.Signal import Signal, signalemitter
|
from UM.Signal import Signal, signalemitter
|
||||||
from UM.Version import Version
|
from UM.Version import Version
|
||||||
|
from UM.Message import Message
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
|
||||||
from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
|
from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
|
||||||
from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
|
from .Cloud.CloudOutputDeviceManager import CloudOutputDeviceManager
|
||||||
|
|
||||||
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
## This plugin handles the connection detection & creation of output device objects for the UM3 printer.
|
## This plugin handles the connection detection & creation of output device objects for the UM3 printer.
|
||||||
# Zero-Conf is used to detect printers, which are saved in a dict.
|
# Zero-Conf is used to detect printers, which are saved in a dict.
|
||||||
|
@ -27,6 +30,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
addDeviceSignal = Signal()
|
addDeviceSignal = Signal()
|
||||||
removeDeviceSignal = Signal()
|
removeDeviceSignal = Signal()
|
||||||
discoveredDevicesChanged = Signal()
|
discoveredDevicesChanged = Signal()
|
||||||
|
cloudFlowIsPossible = Signal()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
@ -34,6 +38,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
self._zero_conf = None
|
self._zero_conf = None
|
||||||
self._zero_conf_browser = None
|
self._zero_conf_browser = None
|
||||||
|
|
||||||
|
self._application = CuraApplication.getInstance()
|
||||||
|
|
||||||
# Create a cloud output device manager that abstracts all cloud connection logic away.
|
# Create a cloud output device manager that abstracts all cloud connection logic away.
|
||||||
self._cloud_output_device_manager = CloudOutputDeviceManager()
|
self._cloud_output_device_manager = CloudOutputDeviceManager()
|
||||||
|
|
||||||
|
@ -41,7 +47,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
self.addDeviceSignal.connect(self._onAddDevice)
|
self.addDeviceSignal.connect(self._onAddDevice)
|
||||||
self.removeDeviceSignal.connect(self._onRemoveDevice)
|
self.removeDeviceSignal.connect(self._onRemoveDevice)
|
||||||
|
|
||||||
CuraApplication.getInstance().globalContainerStackChanged.connect(self.reCheckConnections)
|
self._application.globalContainerStackChanged.connect(self.reCheckConnections)
|
||||||
|
|
||||||
self._discovered_devices = {}
|
self._discovered_devices = {}
|
||||||
|
|
||||||
|
@ -49,6 +55,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
self._network_manager.finished.connect(self._onNetworkRequestFinished)
|
self._network_manager.finished.connect(self._onNetworkRequestFinished)
|
||||||
|
|
||||||
self._min_cluster_version = Version("4.0.0")
|
self._min_cluster_version = Version("4.0.0")
|
||||||
|
self._min_cloud_version = Version("5.1.5")
|
||||||
|
|
||||||
self._api_version = "1"
|
self._api_version = "1"
|
||||||
self._api_prefix = "/api/v" + self._api_version + "/"
|
self._api_prefix = "/api/v" + self._api_version + "/"
|
||||||
|
@ -74,6 +81,14 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
self._service_changed_request_thread = Thread(target=self._handleOnServiceChangedRequests, daemon=True)
|
self._service_changed_request_thread = Thread(target=self._handleOnServiceChangedRequests, daemon=True)
|
||||||
self._service_changed_request_thread.start()
|
self._service_changed_request_thread.start()
|
||||||
|
|
||||||
|
self._account = self._application.getCuraAPI().account
|
||||||
|
|
||||||
|
# Check if cloud flow is possible when user logs in
|
||||||
|
self._account.loginStateChanged.connect(self.checkCloudFlowIsPossible)
|
||||||
|
|
||||||
|
# Listen for when Cloud Flow is possible
|
||||||
|
self.cloudFlowIsPossible.connect(self._onCloudFlowPossible)
|
||||||
|
|
||||||
def getDiscoveredDevices(self):
|
def getDiscoveredDevices(self):
|
||||||
return self._discovered_devices
|
return self._discovered_devices
|
||||||
|
|
||||||
|
@ -292,6 +307,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
|
if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"):
|
||||||
# Ensure that the configured connection type is set.
|
# Ensure that the configured connection type is set.
|
||||||
global_container_stack.addConfiguredConnectionType(device.connectionType.value)
|
global_container_stack.addConfiguredConnectionType(device.connectionType.value)
|
||||||
|
# global_container_stack.setFirmwareVersion(device.firmwareVersion)
|
||||||
device.connect()
|
device.connect()
|
||||||
device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
|
device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged)
|
||||||
|
|
||||||
|
@ -370,3 +386,38 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
self.removeDeviceSignal.emit(str(name))
|
self.removeDeviceSignal.emit(str(name))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
## Check if the prerequsites are in place to start the cloud flow
|
||||||
|
def checkCloudFlowIsPossible(self):
|
||||||
|
Logger.log("d", "Checking if cloud connection is possible...")
|
||||||
|
|
||||||
|
# TODO: Skip if already using cloud connection
|
||||||
|
|
||||||
|
# Check #1: User is logged in with an Ultimaker account
|
||||||
|
if not self._account.isLoggedIn:
|
||||||
|
Logger.log("d", "Cloud Flow not possible: User not logged in!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check #2: Machine has a network connection
|
||||||
|
if not self._application.getMachineManager().activeMachineHasActiveNetworkConnection:
|
||||||
|
Logger.log("d", "Cloud Flow not possible: Machine is not connected!")
|
||||||
|
# TODO: This should only be network connections, not cloud connections
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check #3: Machine has correct firmware version
|
||||||
|
firmware_version = self._application.getMachineManager().activeMachineFirmwareVersion
|
||||||
|
if not Version(firmware_version) > self._min_cloud_version:
|
||||||
|
Logger.log("d",
|
||||||
|
"Cloud Flow not possible: Machine firmware (%s) is too low! (Requires version %s)",
|
||||||
|
firmware_version,
|
||||||
|
self._min_cloud_version)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.cloudFlowIsPossible.emit()
|
||||||
|
Logger.log("d", "Cloud flow is ready to go!")
|
||||||
|
|
||||||
|
def _onCloudFlowPossible(self):
|
||||||
|
# Cloud flow is possible, so show the message
|
||||||
|
self._start_cloud_flow_message = Message(i18n_catalog.i18nc("@info:status", "Chain so thin when a breeze roll by, man it flow... man it flow..."))
|
||||||
|
self._start_cloud_flow_message.show()
|
||||||
|
return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue