mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-13 04:29:01 +08:00
Merge pull request #17149 from Ultimaker/CURA-11138-makerbot-cloud-printing
CURA-11138-makerbot-cloud-printing
This commit is contained in:
commit
82d0bf4673
@ -51,6 +51,9 @@ class CompatibleMachineModel(ListModel):
|
|||||||
for output_device in machine_manager.printerOutputDevices:
|
for output_device in machine_manager.printerOutputDevices:
|
||||||
for printer in output_device.printers:
|
for printer in output_device.printers:
|
||||||
extruder_configs = dict()
|
extruder_configs = dict()
|
||||||
|
# If the printer name already exist in the queue skip it
|
||||||
|
if printer.name in [item["name"] for item in self.items]:
|
||||||
|
continue
|
||||||
|
|
||||||
# initialize & add current active material:
|
# initialize & add current active material:
|
||||||
for extruder in printer.extruders:
|
for extruder in printer.extruders:
|
||||||
|
@ -40,9 +40,22 @@ class ExtruderConfigurationModel(QObject):
|
|||||||
|
|
||||||
def setHotendID(self, hotend_id: Optional[str]) -> None:
|
def setHotendID(self, hotend_id: Optional[str]) -> None:
|
||||||
if self._hotend_id != hotend_id:
|
if self._hotend_id != hotend_id:
|
||||||
self._hotend_id = hotend_id
|
self._hotend_id = ExtruderConfigurationModel.applyNameMappingHotend(hotend_id)
|
||||||
self.extruderConfigurationChanged.emit()
|
self.extruderConfigurationChanged.emit()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def applyNameMappingHotend(hotendId) -> str:
|
||||||
|
_EXTRUDER_NAME_MAP = {
|
||||||
|
"mk14_hot":"1XA",
|
||||||
|
"mk14_hot_s":"2XA",
|
||||||
|
"mk14_c":"1C",
|
||||||
|
"mk14":"1A",
|
||||||
|
"mk14_s":"2A"
|
||||||
|
}
|
||||||
|
if hotendId in _EXTRUDER_NAME_MAP:
|
||||||
|
return _EXTRUDER_NAME_MAP[hotendId]
|
||||||
|
return hotendId
|
||||||
|
|
||||||
@pyqtProperty(str, fset = setHotendID, notify = extruderConfigurationChanged)
|
@pyqtProperty(str, fset = setHotendID, notify = extruderConfigurationChanged)
|
||||||
def hotendID(self) -> Optional[str]:
|
def hotendID(self) -> Optional[str]:
|
||||||
return self._hotend_id
|
return self._hotend_id
|
||||||
|
@ -9,7 +9,9 @@ from PyQt6.QtCore import pyqtProperty, QObject
|
|||||||
class MaterialOutputModel(QObject):
|
class MaterialOutputModel(QObject):
|
||||||
def __init__(self, guid: Optional[str], type: str, color: str, brand: str, name: str, parent = None) -> None:
|
def __init__(self, guid: Optional[str], type: str, color: str, brand: str, name: str, parent = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._guid = guid
|
|
||||||
|
name, guid = MaterialOutputModel.getMaterialFromDefinition(guid,type, brand, name)
|
||||||
|
self._guid =guid
|
||||||
self._type = type
|
self._type = type
|
||||||
self._color = color
|
self._color = color
|
||||||
self._brand = brand
|
self._brand = brand
|
||||||
@ -19,6 +21,34 @@ class MaterialOutputModel(QObject):
|
|||||||
def guid(self) -> str:
|
def guid(self) -> str:
|
||||||
return self._guid if self._guid else ""
|
return self._guid if self._guid else ""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def getMaterialFromDefinition(guid, type, brand, name):
|
||||||
|
|
||||||
|
_MATERIAL_MAP = { "abs" :{"name" :"abs_175" ,"guid": "2780b345-577b-4a24-a2c5-12e6aad3e690"},
|
||||||
|
"abs-wss1" :{"name" :"absr_175" ,"guid": "88c8919c-6a09-471a-b7b6-e801263d862d"},
|
||||||
|
"asa" :{"name" :"asa_175" ,"guid": "416eead4-0d8e-4f0b-8bfc-a91a519befa5"},
|
||||||
|
"nylon-cf" :{"name" :"cffpa_175" ,"guid": "85bbae0e-938d-46fb-989f-c9b3689dc4f0"},
|
||||||
|
"nylon" :{"name" :"nylon_175" ,"guid": "283d439a-3490-4481-920c-c51d8cdecf9c"},
|
||||||
|
"pc" :{"name" :"pc_175" ,"guid": "62414577-94d1-490d-b1e4-7ef3ec40db02"},
|
||||||
|
"petg" :{"name" :"petg_175" ,"guid": "69386c85-5b6c-421a-bec5-aeb1fb33f060"},
|
||||||
|
"pla" :{"name" :"pla_175" ,"guid": "0ff92885-617b-4144-a03c-9989872454bc"},
|
||||||
|
"pva" :{"name" :"pva_175" ,"guid": "a4255da2-cb2a-4042-be49-4a83957a2f9a"},
|
||||||
|
"wss1" :{"name" :"rapidrinse_175","guid": "a140ef8f-4f26-4e73-abe0-cfc29d6d1024"},
|
||||||
|
"sr30" :{"name" :"sr30_175" ,"guid": "77873465-83a9-4283-bc44-4e542b8eb3eb"},
|
||||||
|
"im-pla" :{"name" :"tough_pla_175" ,"guid": "96fca5d9-0371-4516-9e96-8e8182677f3c"},
|
||||||
|
"bvoh" :{"name" :"bvoh_175" ,"guid": "923e604c-8432-4b09-96aa-9bbbd42207f4"},
|
||||||
|
"cpe" :{"name" :"cpe_175" ,"guid": "da1872c1-b991-4795-80ad-bdac0f131726"},
|
||||||
|
"hips" :{"name" :"hips_175" ,"guid": "a468d86a-220c-47eb-99a5-bbb47e514eb0"},
|
||||||
|
"tpu" :{"name" :"tpu_175" ,"guid": "19baa6a9-94ff-478b-b4a1-8157b74358d2"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if guid is None and brand is not "empty" and type in _MATERIAL_MAP:
|
||||||
|
name = _MATERIAL_MAP[type]["name"]
|
||||||
|
guid = _MATERIAL_MAP[type]["guid"]
|
||||||
|
return name, guid
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def type(self) -> str:
|
def type(self) -> str:
|
||||||
return self._type
|
return self._type
|
||||||
|
@ -415,7 +415,18 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def printerType(self) -> str:
|
def printerType(self) -> str:
|
||||||
return self._properties.get(b"printer_type", b"Unknown").decode("utf-8")
|
return NetworkedPrinterOutputDevice.applyPrinterTypeMapping(self._properties.get(b"printer_type", b"Unknown").decode("utf-8"))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def applyPrinterTypeMapping(printer_type):
|
||||||
|
_PRINTER_TYPE_NAME = {
|
||||||
|
"fire_e": "ultimaker_method",
|
||||||
|
"lava_f": "ultimaker_methodx",
|
||||||
|
"magma_10": "ultimaker_methodxl"
|
||||||
|
}
|
||||||
|
if printer_type in _PRINTER_TYPE_NAME:
|
||||||
|
return _PRINTER_TYPE_NAME[printer_type]
|
||||||
|
return printer_type
|
||||||
|
|
||||||
@pyqtProperty(str, constant = True)
|
@pyqtProperty(str, constant = True)
|
||||||
def ipAddress(self) -> str:
|
def ipAddress(self) -> str:
|
||||||
|
@ -284,16 +284,20 @@ class CuraStackBuilder:
|
|||||||
abstract_machines = registry.findContainerStacks(id = abstract_machine_id)
|
abstract_machines = registry.findContainerStacks(id = abstract_machine_id)
|
||||||
if abstract_machines:
|
if abstract_machines:
|
||||||
return cast(GlobalStack, abstract_machines[0])
|
return cast(GlobalStack, abstract_machines[0])
|
||||||
|
|
||||||
definitions = registry.findDefinitionContainers(id=definition_id)
|
definitions = registry.findDefinitionContainers(id=definition_id)
|
||||||
|
|
||||||
name = ""
|
name = ""
|
||||||
|
|
||||||
if definitions:
|
if definitions:
|
||||||
name = definitions[0].getName()
|
name = definitions[0].getName()
|
||||||
|
|
||||||
stack = cls.createMachine(abstract_machine_id, definition_id, show_warning_message=False)
|
stack = cls.createMachine(abstract_machine_id, definition_id, show_warning_message=False)
|
||||||
if not stack:
|
if not stack:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not stack.getMetaDataEntry("visible", True):
|
||||||
|
return None
|
||||||
|
|
||||||
stack.setName(name)
|
stack.setName(name)
|
||||||
|
|
||||||
stack.setMetaDataEntry("is_abstract_machine", True)
|
stack.setMetaDataEntry("is_abstract_machine", True)
|
||||||
|
@ -208,12 +208,14 @@ Item
|
|||||||
anchors.rightMargin: UM.Theme.getSize("thin_margin").height
|
anchors.rightMargin: UM.Theme.getSize("thin_margin").height
|
||||||
|
|
||||||
enabled: UM.Backend.state == UM.Backend.Done
|
enabled: UM.Backend.state == UM.Backend.Done
|
||||||
currentIndex: UM.Backend.state == UM.Backend.Done ? 0 : 1
|
currentIndex: UM.Backend.state == UM.Backend.Done ? dfFilenameTextfield.text.startsWith("MM")? 1 : 0 : 2
|
||||||
|
|
||||||
textRole: "text"
|
textRole: "text"
|
||||||
valueRole: "value"
|
valueRole: "value"
|
||||||
|
|
||||||
model: [
|
model: [
|
||||||
{ text: catalog.i18nc("@option", "Save Cura project and print file"), key: "3mf_ufp", value: ["3mf", "ufp"] },
|
{ text: catalog.i18nc("@option", "Save Cura project and .ufp print file"), key: "3mf_ufp", value: ["3mf", "ufp"] },
|
||||||
|
{ text: catalog.i18nc("@option", "Save Cura project and .makerbot print file"), key: "3mf_makerbot", value: ["3mf", "makerbot"] },
|
||||||
{ text: catalog.i18nc("@option", "Save Cura project"), key: "3mf", value: ["3mf"] },
|
{ text: catalog.i18nc("@option", "Save Cura project"), key: "3mf", value: ["3mf"] },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ from .ExportFileJob import ExportFileJob
|
|||||||
class DFFileExportAndUploadManager:
|
class DFFileExportAndUploadManager:
|
||||||
"""
|
"""
|
||||||
Class responsible for exporting the scene and uploading the exported data to the Digital Factory Library. Since 3mf
|
Class responsible for exporting the scene and uploading the exported data to the Digital Factory Library. Since 3mf
|
||||||
and UFP files may need to be uploaded at the same time, this class keeps a single progress and success message for
|
and (UFP or makerbot) files may need to be uploaded at the same time, this class keeps a single progress and success message for
|
||||||
both files and updates those messages according to the progress of both the file job uploads.
|
both files and updates those messages according to the progress of both the file job uploads.
|
||||||
"""
|
"""
|
||||||
def __init__(self, file_handlers: Dict[str, FileHandler],
|
def __init__(self, file_handlers: Dict[str, FileHandler],
|
||||||
@ -118,7 +118,7 @@ class DFFileExportAndUploadManager:
|
|||||||
library_project_id = self._library_project_id,
|
library_project_id = self._library_project_id,
|
||||||
source_file_id = self._source_file_id
|
source_file_id = self._source_file_id
|
||||||
)
|
)
|
||||||
self._api.requestUploadUFP(request, on_finished = self._uploadFileData, on_error = self._onRequestUploadPrintFileFailed)
|
self._api.requestUploadMeshFile(request, on_finished = self._uploadFileData, on_error = self._onRequestUploadPrintFileFailed)
|
||||||
|
|
||||||
def _uploadFileData(self, file_upload_response: Union[DFLibraryFileUploadResponse, DFPrintJobUploadResponse]) -> None:
|
def _uploadFileData(self, file_upload_response: Union[DFLibraryFileUploadResponse, DFPrintJobUploadResponse]) -> None:
|
||||||
"""Uploads the exported file data after the file or print job upload has been registered at the Digital Factory
|
"""Uploads the exported file data after the file or print job upload has been registered at the Digital Factory
|
||||||
@ -279,22 +279,25 @@ class DFFileExportAndUploadManager:
|
|||||||
This means that something went wrong with the initial request to create a "file" entry in the digital library.
|
This means that something went wrong with the initial request to create a "file" entry in the digital library.
|
||||||
"""
|
"""
|
||||||
reply_string = bytes(reply.readAll()).decode()
|
reply_string = bytes(reply.readAll()).decode()
|
||||||
filename_ufp = self._file_name + ".ufp"
|
if "ufp" in self._formats:
|
||||||
Logger.log("d", "An error occurred while uploading the print job file '{}' to the Digital Library project '{}': {}".format(filename_ufp, self._library_project_id, reply_string))
|
filename_meshfile = self._file_name + ".ufp"
|
||||||
|
elif "makerbot" in self._formats:
|
||||||
|
filename_meshfile = self._file_name + ".makerbot"
|
||||||
|
Logger.log("d", "An error occurred while uploading the print job file '{}' to the Digital Library project '{}': {}".format(filename_meshfile, self._library_project_id, reply_string))
|
||||||
with self._message_lock:
|
with self._message_lock:
|
||||||
# Set the progress to 100% when the upload job fails, to avoid having the progress message stuck
|
# Set the progress to 100% when the upload job fails, to avoid having the progress message stuck
|
||||||
self._file_upload_job_metadata[filename_ufp]["upload_status"] = "failed"
|
self._file_upload_job_metadata[filename_meshfile]["upload_status"] = "failed"
|
||||||
self._file_upload_job_metadata[filename_ufp]["upload_progress"] = 100
|
self._file_upload_job_metadata[filename_meshfile]["upload_progress"] = 100
|
||||||
|
|
||||||
human_readable_error = self.extractErrorTitle(reply_string)
|
human_readable_error = self.extractErrorTitle(reply_string)
|
||||||
self._file_upload_job_metadata[filename_ufp]["file_upload_failed_message"] = getBackwardsCompatibleMessage(
|
self._file_upload_job_metadata[filename_meshfile]["file_upload_failed_message"] = getBackwardsCompatibleMessage(
|
||||||
title = "File upload error",
|
title = "File upload error",
|
||||||
text = "Failed to upload the file '{}' to '{}'. {}".format(filename_ufp, self._library_project_name, human_readable_error),
|
text = "Failed to upload the file '{}' to '{}'. {}".format(filename_meshfile, self._library_project_name, human_readable_error),
|
||||||
message_type_str = "ERROR",
|
message_type_str = "ERROR",
|
||||||
lifetime = 30
|
lifetime = 30
|
||||||
)
|
)
|
||||||
self._on_upload_error()
|
self._on_upload_error()
|
||||||
self._onFileUploadFinished(filename_ufp)
|
self._onFileUploadFinished(filename_meshfile)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extractErrorTitle(reply_body: Optional[str]) -> str:
|
def extractErrorTitle(reply_body: Optional[str]) -> str:
|
||||||
@ -407,4 +410,28 @@ class DFFileExportAndUploadManager:
|
|||||||
job_ufp = ExportFileJob(self._file_handlers["ufp"], self._nodes, self._file_name, "ufp")
|
job_ufp = ExportFileJob(self._file_handlers["ufp"], self._nodes, self._file_name, "ufp")
|
||||||
job_ufp.finished.connect(self._onPrintFileExported)
|
job_ufp.finished.connect(self._onPrintFileExported)
|
||||||
self._upload_jobs.append(job_ufp)
|
self._upload_jobs.append(job_ufp)
|
||||||
|
|
||||||
|
if "makerbot" in self._formats and "makerbot" in self._file_handlers and self._file_handlers["makerbot"]:
|
||||||
|
filename_makerbot = self._file_name + ".makerbot"
|
||||||
|
metadata[filename_makerbot] = {
|
||||||
|
"export_job_output" : None,
|
||||||
|
"upload_progress" : -1,
|
||||||
|
"upload_status" : "",
|
||||||
|
"file_upload_response": None,
|
||||||
|
"file_upload_success_message": getBackwardsCompatibleMessage(
|
||||||
|
text = "'{}' was uploaded to '{}'.".format(filename_makerbot, self._library_project_name),
|
||||||
|
title = "Upload successful",
|
||||||
|
message_type_str = "POSITIVE",
|
||||||
|
lifetime = 30,
|
||||||
|
),
|
||||||
|
"file_upload_failed_message": getBackwardsCompatibleMessage(
|
||||||
|
text = "Failed to upload the file '{}' to '{}'.".format(filename_makerbot, self._library_project_name),
|
||||||
|
title = "File upload error",
|
||||||
|
message_type_str = "ERROR",
|
||||||
|
lifetime = 30
|
||||||
|
)
|
||||||
|
}
|
||||||
|
job_makerbot = ExportFileJob(self._file_handlers["makerbot"], self._nodes, self._file_name, "makerbot")
|
||||||
|
job_makerbot.finished.connect(self._onPrintFileExported)
|
||||||
|
self._upload_jobs.append(job_makerbot)
|
||||||
return metadata
|
return metadata
|
||||||
|
@ -313,7 +313,7 @@ class DigitalFactoryApiClient:
|
|||||||
error_callback = on_error,
|
error_callback = on_error,
|
||||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||||
|
|
||||||
def requestUploadUFP(self, request: DFPrintJobUploadRequest,
|
def requestUploadMeshFile(self, request: DFPrintJobUploadRequest,
|
||||||
on_finished: Callable[[DFPrintJobUploadResponse], Any],
|
on_finished: Callable[[DFPrintJobUploadResponse], Any],
|
||||||
on_error: Optional[Callable[["QNetworkReply", "QNetworkReply.NetworkError"], None]] = None) -> None:
|
on_error: Optional[Callable[["QNetworkReply", "QNetworkReply.NetworkError"], None]] = None) -> None:
|
||||||
"""Requests the Digital Factory to register the upload of a file in a library project.
|
"""Requests the Digital Factory to register the upload of a file in a library project.
|
||||||
|
@ -92,7 +92,8 @@ class DigitalFactoryOutputDevice(ProjectOutputDevice):
|
|||||||
if not self._controller.file_handlers:
|
if not self._controller.file_handlers:
|
||||||
self._controller.file_handlers = {
|
self._controller.file_handlers = {
|
||||||
"3mf": CuraApplication.getInstance().getWorkspaceFileHandler(),
|
"3mf": CuraApplication.getInstance().getWorkspaceFileHandler(),
|
||||||
"ufp": CuraApplication.getInstance().getMeshFileHandler()
|
"ufp": CuraApplication.getInstance().getMeshFileHandler(),
|
||||||
|
"makerbot": CuraApplication.getInstance().getMeshFileHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
self._dialog = CuraApplication.getInstance().createQmlComponent(self._dialog_path, {"manager": self._controller})
|
self._dialog = CuraApplication.getInstance().createQmlComponent(self._dialog_path, {"manager": self._controller})
|
||||||
|
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method X.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method X.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 202 KiB |
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method XL.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method XL.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 KiB |
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method.png
Normal file
BIN
plugins/UM3NetworkPrinting/resources/png/MakerBot Method.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 140 KiB |
@ -115,7 +115,7 @@ UM.Dialog
|
|||||||
// Utils
|
// Utils
|
||||||
function formatPrintJobName(name)
|
function formatPrintJobName(name)
|
||||||
{
|
{
|
||||||
var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp" ]
|
var extensions = [ ".gcode.gz", ".gz", ".gcode", ".ufp", ".makerbot" ]
|
||||||
for (var i = 0; i < extensions.length; i++)
|
for (var i = 0; i < extensions.length; i++)
|
||||||
{
|
{
|
||||||
var extension = extensions[i]
|
var extension = extensions[i]
|
||||||
|
@ -82,7 +82,16 @@ class CloudApiClient:
|
|||||||
# HACK: There is something weird going on with the API, as it reports printer types in formats like
|
# HACK: There is something weird going on with the API, as it reports printer types in formats like
|
||||||
# "ultimaker_s3", but wants "Ultimaker S3" when using the machine_variant filter query. So we need to do some
|
# "ultimaker_s3", but wants "Ultimaker S3" when using the machine_variant filter query. So we need to do some
|
||||||
# conversion!
|
# conversion!
|
||||||
|
# API points to "MakerBot Method" for a makerbot printertypes which we already changed to allign with other printer_type
|
||||||
|
|
||||||
|
method_x = {
|
||||||
|
"ultimaker_method":"MakerBot Method",
|
||||||
|
"ultimaker_methodx":"MakerBot Method X",
|
||||||
|
"ultimaker_methodxl":"MakerBot Method XL"
|
||||||
|
}
|
||||||
|
if machine_type in method_x:
|
||||||
|
machine_type = method_x[machine_type]
|
||||||
|
else:
|
||||||
machine_type = machine_type.replace("_plus", "+")
|
machine_type = machine_type.replace("_plus", "+")
|
||||||
machine_type = machine_type.replace("_", " ")
|
machine_type = machine_type.replace("_", " ")
|
||||||
machine_type = machine_type.replace("ultimaker", "ultimaker ")
|
machine_type = machine_type.replace("ultimaker", "ultimaker ")
|
||||||
|
@ -58,6 +58,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
|
|
||||||
# The minimum version of firmware that support print job actions over cloud.
|
# The minimum version of firmware that support print job actions over cloud.
|
||||||
PRINT_JOB_ACTIONS_MIN_VERSION = Version("5.2.12")
|
PRINT_JOB_ACTIONS_MIN_VERSION = Version("5.2.12")
|
||||||
|
PRINT_JOB_ACTIONS_MIN_VERSION_METHOD = Version("2.700")
|
||||||
|
|
||||||
# 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.
|
||||||
@ -325,8 +326,13 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
|||||||
if not self._printers:
|
if not self._printers:
|
||||||
return False
|
return False
|
||||||
version_number = self.printers[0].firmwareVersion.split(".")
|
version_number = self.printers[0].firmwareVersion.split(".")
|
||||||
|
if len(version_number)> 2:
|
||||||
firmware_version = Version([version_number[0], version_number[1], version_number[2]])
|
firmware_version = Version([version_number[0], version_number[1], version_number[2]])
|
||||||
return firmware_version >= self.PRINT_JOB_ACTIONS_MIN_VERSION
|
return firmware_version >= self.PRINT_JOB_ACTIONS_MIN_VERSION
|
||||||
|
else:
|
||||||
|
firmware_version = Version([version_number[0], version_number[1]])
|
||||||
|
return firmware_version >= self.PRINT_JOB_ACTIONS_MIN_VERSION_METHOD
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty(bool, constant = True)
|
@pyqtProperty(bool, constant = True)
|
||||||
def supportsPrintJobQueue(self) -> bool:
|
def supportsPrintJobQueue(self) -> bool:
|
||||||
|
@ -9,6 +9,7 @@ from PyQt6.QtWidgets import QMessageBox
|
|||||||
|
|
||||||
from UM import i18nCatalog
|
from UM import i18nCatalog
|
||||||
from UM.Logger import Logger # To log errors talking to the API.
|
from UM.Logger import Logger # To log errors talking to the API.
|
||||||
|
from UM.Message import Message
|
||||||
from UM.Settings.Interfaces import ContainerInterface
|
from UM.Settings.Interfaces import ContainerInterface
|
||||||
from UM.Signal import Signal
|
from UM.Signal import Signal
|
||||||
from UM.Util import parseBool
|
from UM.Util import parseBool
|
||||||
@ -25,7 +26,7 @@ from .CloudOutputDevice import CloudOutputDevice
|
|||||||
from ..Messages.RemovedPrintersMessage import RemovedPrintersMessage
|
from ..Messages.RemovedPrintersMessage import RemovedPrintersMessage
|
||||||
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
||||||
from ..Messages.NewPrinterDetectedMessage import NewPrinterDetectedMessage
|
from ..Messages.NewPrinterDetectedMessage import NewPrinterDetectedMessage
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
class CloudOutputDeviceManager:
|
class CloudOutputDeviceManager:
|
||||||
"""The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
|
"""The cloud output device manager is responsible for using the Ultimaker Cloud APIs to manage remote clusters.
|
||||||
@ -179,6 +180,13 @@ class CloudOutputDeviceManager:
|
|||||||
return
|
return
|
||||||
Logger.log("e", f"Failed writing to specific cloud printer: {unique_id} not in remote clusters.")
|
Logger.log("e", f"Failed writing to specific cloud printer: {unique_id} not in remote clusters.")
|
||||||
|
|
||||||
|
# This message is added so that user knows when the print job was not sent to cloud printer
|
||||||
|
message = Message(catalog.i18nc("@info:status",
|
||||||
|
"Failed writing to specific cloud printer: {0} not in remote clusters.").format(unique_id),
|
||||||
|
title=catalog.i18nc("@info:title", "Error"),
|
||||||
|
message_type=Message.MessageType.ERROR)
|
||||||
|
message.show()
|
||||||
|
|
||||||
def _createMachineStacksForDiscoveredClusters(self, discovered_clusters: List[CloudClusterResponse]) -> None:
|
def _createMachineStacksForDiscoveredClusters(self, discovered_clusters: List[CloudClusterResponse]) -> None:
|
||||||
"""**Synchronously** create machines for discovered devices
|
"""**Synchronously** create machines for discovered devices
|
||||||
|
|
||||||
|
@ -106,6 +106,10 @@ class MeshFormatHandler:
|
|||||||
if "application/x-ufp" not in machine_file_formats and Version(firmware_version) >= Version("4.4"):
|
if "application/x-ufp" not in machine_file_formats and Version(firmware_version) >= Version("4.4"):
|
||||||
machine_file_formats = ["application/x-ufp"] + machine_file_formats
|
machine_file_formats = ["application/x-ufp"] + machine_file_formats
|
||||||
|
|
||||||
|
# Exception for makerbot firmware version >=2.700: makerbot is supported
|
||||||
|
elif "application/x-makerbot" not in machine_file_formats and Version(firmware_version >= Version("2.700")):
|
||||||
|
machine_file_formats = ["application/x-makerbot"] + machine_file_formats
|
||||||
|
|
||||||
# Take the intersection between file_formats and machine_file_formats.
|
# Take the intersection between file_formats and machine_file_formats.
|
||||||
format_by_mimetype = {f["mime_type"]: f for f in file_formats}
|
format_by_mimetype = {f["mime_type"]: f for f in file_formats}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
|
from cura.PrinterOutput.NetworkedPrinterOutputDevice import NetworkedPrinterOutputDevice
|
||||||
from ..BaseModel import BaseModel
|
from ..BaseModel import BaseModel
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ class CloudClusterResponse(BaseModel):
|
|||||||
self.host_version = host_version
|
self.host_version = host_version
|
||||||
self.host_internal_ip = host_internal_ip
|
self.host_internal_ip = host_internal_ip
|
||||||
self.friendly_name = friendly_name
|
self.friendly_name = friendly_name
|
||||||
self.printer_type = printer_type
|
self.printer_type = NetworkedPrinterOutputDevice.applyPrinterTypeMapping(printer_type)
|
||||||
self.printer_count = printer_count
|
self.printer_count = printer_count
|
||||||
self.capabilities = capabilities if capabilities is not None else []
|
self.capabilities = capabilities if capabilities is not None else []
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
@ -51,3 +52,4 @@ class CloudClusterResponse(BaseModel):
|
|||||||
:return: A human-readable representation of the data in this object.
|
:return: A human-readable representation of the data in this object.
|
||||||
"""
|
"""
|
||||||
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})
|
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user