mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-13 01:37:51 -06:00
CloudOutputDevice scaffolding
This commit is contained in:
parent
2497325d60
commit
69ca7c0f89
5 changed files with 152 additions and 0 deletions
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
from cura.PrinterOutput.PrinterOutputController import PrinterOutputController
|
||||||
|
|
||||||
|
|
||||||
|
class CloudOutputController(PrinterOutputController):
|
||||||
|
def __init__(self, output_device):
|
||||||
|
super().__init__(output_device)
|
||||||
|
|
||||||
|
# The cloud connection only supports fetching the printer and queue status and adding a job to the queue.
|
||||||
|
# To let the UI know this we mark all features below as False.
|
||||||
|
self.can_pause = False
|
||||||
|
self.can_abort = False
|
||||||
|
self.can_pre_heat_bed = False
|
||||||
|
self.can_pre_heat_hotends = False
|
||||||
|
self.can_send_raw_gcode = False
|
||||||
|
self.can_control_manually = False
|
||||||
|
self.can_update_firmware = False
|
134
plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
Normal file
134
plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
import json
|
||||||
|
from typing import List, Optional, Dict
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
||||||
|
from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest
|
||||||
|
|
||||||
|
from UM import i18nCatalog
|
||||||
|
from UM.FileHandler.FileHandler import FileHandler
|
||||||
|
from UM.Logger import Logger
|
||||||
|
from UM.Scene.SceneNode import SceneNode
|
||||||
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice, AuthState
|
||||||
|
from cura.PrinterOutput.PrinterOutputModel import PrinterOutputModel
|
||||||
|
from plugins.UM3NetworkPrinting.src.Cloud.CloudOutputController import CloudOutputController
|
||||||
|
from plugins.UM3NetworkPrinting.src.UM3PrintJobOutputModel import UM3PrintJobOutputModel
|
||||||
|
|
||||||
|
|
||||||
|
## The cloud output device is a network output device that works remotely but has limited functionality.
|
||||||
|
# Currently it only supports viewing the printer and print job status and adding a new job to the queue.
|
||||||
|
# As such, those methods have been implemented here.
|
||||||
|
# Note that this device represents a single remote cluster, not a list of multiple clusters.
|
||||||
|
#
|
||||||
|
# TODO: figure our how the QML interface for the cluster networking should operate with this limited functionality.
|
||||||
|
# TODO: figure out how to pair remote clusters, local networked clusters and local cura printer presets.
|
||||||
|
class CloudOutputDevice(NetworkedPrinterOutputDevice):
|
||||||
|
|
||||||
|
# The translation catalog for this device.
|
||||||
|
I18N_CATALOG = i18nCatalog("cura")
|
||||||
|
|
||||||
|
# The cloud URL to use for remote clusters.
|
||||||
|
API_ROOT_PATH_FORMAT = "https://api.ultimaker.com/connect/clusters/{cluster_id}"
|
||||||
|
|
||||||
|
# Signal triggered when the printers in the remote cluster were changed.
|
||||||
|
printersChanged = pyqtSignal()
|
||||||
|
|
||||||
|
# Signal triggered when the print jobs in the queue were changed.
|
||||||
|
printJobsChanged = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, device_id: str, address: str, properties: Dict[bytes, bytes], parent: QObject = None):
|
||||||
|
super().__init__(device_id = device_id, address = address, properties = properties, parent = parent)
|
||||||
|
self._setInterfaceElements()
|
||||||
|
|
||||||
|
# The API prefix is automatically added when doing any HTTP call on the device.
|
||||||
|
self._api_prefix = self.API_ROOT_PATH_FORMAT.format(device_id) # TODO: verify we can use device_id here
|
||||||
|
self._authentication_state = AuthState.Authenticated # TODO: use cura.API.Account to set this?
|
||||||
|
|
||||||
|
# Properties to populate later on with received cloud data.
|
||||||
|
self._printers = []
|
||||||
|
self._print_jobs = []
|
||||||
|
self._number_of_extruders = 2 # All networked printers are dual-extrusion Ultimaker machines.
|
||||||
|
|
||||||
|
## Set all the interface elements and texts for this output device.
|
||||||
|
def _setInterfaceElements(self):
|
||||||
|
self.setPriority(3)
|
||||||
|
self.setName(self._id)
|
||||||
|
# TODO: how to name these?
|
||||||
|
self.setShortDescription(self.I18N_CATALOG.i18nc("@action:button", "Print via Cloud"))
|
||||||
|
self.setDescription(self.I18N_CATALOG.i18nc("@properties:tooltip", "Print via Cloud"))
|
||||||
|
self.setConnectionText(self.I18N_CATALOG.i18nc("@info:status", "Connected via Cloud"))
|
||||||
|
|
||||||
|
## Called when Cura requests an output device to receive a (G-code) file.
|
||||||
|
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mime_types: bool = False,
|
||||||
|
file_handler: Optional[FileHandler] = None, **kwargs: str) -> None:
|
||||||
|
self.writeStarted.emit(self)
|
||||||
|
|
||||||
|
# TODO: actually implement this
|
||||||
|
self._addPrintJobToQueue()
|
||||||
|
|
||||||
|
## Get remote printers.
|
||||||
|
@pyqtProperty("QVariantList", notify = printersChanged)
|
||||||
|
def printers(self):
|
||||||
|
return self._printers
|
||||||
|
|
||||||
|
## Get remote print jobs.
|
||||||
|
@pyqtProperty("QVariantList", notify = printJobsChanged)
|
||||||
|
def printJobs(self) -> List[UM3PrintJobOutputModel]:
|
||||||
|
return self._print_jobs
|
||||||
|
|
||||||
|
## Called when the connection to the cluster changes.
|
||||||
|
def connect(self) -> None:
|
||||||
|
super().connect()
|
||||||
|
|
||||||
|
## Called when the network data should be updated.
|
||||||
|
def _update(self) -> None:
|
||||||
|
super()._update()
|
||||||
|
self.get("/status", on_finished = self._onStatusCallFinished)
|
||||||
|
|
||||||
|
def _onStatusCallFinished(self, reply: QNetworkReply) -> None:
|
||||||
|
status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
|
||||||
|
if status_code != 200:
|
||||||
|
Logger.log("w", "Got unexpected response while trying to get cloud cluster data: {}, {}"
|
||||||
|
.format(status_code, reply.getErrorString()))
|
||||||
|
return
|
||||||
|
|
||||||
|
data = self._parseStatusResponse(reply)
|
||||||
|
if data is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Update all data from the cluster.
|
||||||
|
self._updatePrinters(data.get("printers", []))
|
||||||
|
self._updatePrintJobs(data.get("print_jobs", []))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parseStatusResponse(reply: QNetworkReply) -> Optional[dict]:
|
||||||
|
try:
|
||||||
|
result = json.loads(bytes(reply.readAll()).decode("utf-8"))
|
||||||
|
# TODO: use model or named tuple here.
|
||||||
|
return result
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
Logger.logException("w", "Unable to decode JSON from reply.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _updatePrinters(self, remote_printers: List[Dict[str, any]]) -> None:
|
||||||
|
# TODO: use model or tuple for remote_printers data
|
||||||
|
for printer in remote_printers:
|
||||||
|
|
||||||
|
# If the printer does not exist yet, create it.
|
||||||
|
if not self._getPrinterByKey(printer["uuid"]):
|
||||||
|
self._printers.append(PrinterOutputModel(
|
||||||
|
output_controller = CloudOutputController(self),
|
||||||
|
number_of_extruders = self._number_of_extruders
|
||||||
|
))
|
||||||
|
|
||||||
|
# TODO: properly handle removed and updated printers
|
||||||
|
self.printersChanged.emit()
|
||||||
|
|
||||||
|
def _updatePrintJobs(self, remote_print_jobs: List[Dict[str, any]]) -> None:
|
||||||
|
# TODO: use model or tuple for remote_print_jobs data
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _addPrintJobToQueue(self):
|
||||||
|
# TODO: implement this
|
||||||
|
pass
|
0
plugins/UM3NetworkPrinting/src/Cloud/__init__.py
Normal file
0
plugins/UM3NetworkPrinting/src/Cloud/__init__.py
Normal file
0
plugins/UM3NetworkPrinting/src/__init__.py
Normal file
0
plugins/UM3NetworkPrinting/src/__init__.py
Normal file
0
plugins/__init__.py
Normal file
0
plugins/__init__.py
Normal file
Loading…
Add table
Add a link
Reference in a new issue