def updateOutputModel(self, model: PrinterOutputModel) -> None:
        model.updateKey(self.uuid)
        model.updateName(self.friendly_name)
        model.updateType(self.machine_variant)
        model.updateState(self.status if self.enabled else "disabled")
        model.updateBuildplate(self.build_plate.type if self.build_plate else "glass")

        for configuration, extruder_output, extruder_config in \
                zip(self.configuration, model.extruders, model.printerConfiguration.extruderConfigurations):
            configuration.updateOutputModel(extruder_output)
            configuration.updateConfigurationModel(extruder_config)
Example #2
0
 def _onGlobalContainerStackChanged(self):
     container_stack = CuraApplication.getInstance(
     ).getGlobalContainerStack()
     num_extruders = container_stack.getProperty("machine_extruder_count",
                                                 "value")
     # Ensure that a printer is created.
     controller = GenericOutputController(self)
     controller.setCanUpdateFirmware(True)
     self._printers = [
         PrinterOutputModel(output_controller=controller,
                            number_of_extruders=num_extruders)
     ]
     self._printers[0].updateName(container_stack.getName())
Example #3
0
def test_availableConfigurations_removeConfig():
    model = PrinterOutputModel(MagicMock())

    configuration = MagicMock(spec=PrinterConfigurationModel)

    model.addAvailableConfiguration(configuration)
    model.removeAvailableConfiguration(configuration)
    assert model.availableConfigurations == []
Example #4
0
def test_peripherals():
    model = PrinterOutputModel(MagicMock())
    model.peripheralsChanged = MagicMock()

    peripheral = MagicMock(spec=Peripheral)
    peripheral.name = "test"
    peripheral2 = MagicMock(spec=Peripheral)
    peripheral2.name = "test2"

    model.addPeripheral(peripheral)
    assert model.peripheralsChanged.emit.call_count == 1
    model.addPeripheral(peripheral2)
    assert model.peripheralsChanged.emit.call_count == 2

    assert model.peripherals == "test, test2"

    model.removePeripheral(peripheral)
    assert model.peripheralsChanged.emit.call_count == 3
    assert model.peripherals == "test2"
Example #5
0
 def _updateAvailableConfigurations(self,
                                    model: PrinterOutputModel) -> None:
     # Generate a list of configurations for the left extruder.
     left_configurations = [
         slot for slot in self.material_station.material_slots
         if self._isSupportedConfiguration(slot=slot, extruder_index=0)
     ]
     # Generate a list of configurations for the right extruder.
     right_configurations = [
         slot for slot in self.material_station.material_slots
         if self._isSupportedConfiguration(slot=slot, extruder_index=1)
     ]
     # Create a list of all available combinations between both print cores.
     available_configurations = [
         self._createAvailableConfigurationFromPrinterConfiguration(
             left_slot=left_slot,
             right_slot=right_slot,
             printer_configuration=model.printerConfiguration)
         for left_slot, right_slot in product(left_configurations,
                                              right_configurations)
     ]
     # Let Cura know which available configurations there are.
     model.setAvailableConfigurations(available_configurations)
Example #6
0
    def createOutputModel(
            self, controller: PrinterOutputController) -> PrinterOutputModel:
        """Creates a new output model.

        :param controller: - The controller of the model.
        """

        # FIXME
        # Note that we're using '2' here as extruder count. We have hardcoded this for now to prevent issues where the
        # amount of extruders coming back from the API is actually lower (which it can be if a printer was just added
        # to a cluster). This should be fixed in the future, probably also on the cluster API side.
        model = PrinterOutputModel(controller,
                                   2,
                                   firmware_version=self.firmware_version)
        self.updateOutputModel(model)
        return model
Example #7
0
def test_availableConfigurations_addConfigTwice():
    model = PrinterOutputModel(MagicMock())

    configuration = MagicMock(spec=PrinterConfigurationModel)

    model.setAvailableConfigurations([configuration])
    assert model.availableConfigurations == [configuration]

    # Adding it again should not have any effect
    model.addAvailableConfiguration(configuration)
    assert model.availableConfigurations == [configuration]
Example #8
0
def test_uniqueConfigurations(printer_output_device):
    printer = PrinterOutputModel(MagicMock())
    # Add a printer and fire the signal that ensures they get hooked up correctly.
    printer_output_device._printers = [printer]
    printer_output_device._onPrintersChanged()

    assert printer_output_device.uniqueConfigurations == []
    configuration = PrinterConfigurationModel()
    printer.addAvailableConfiguration(configuration)

    assert printer_output_device.uniqueConfigurations == [configuration]

    # Once the type of printer is set, it's active configuration counts as being set.
    # In that case, that should also be added to the list of available configurations
    printer.updateType("blarg!")
    loaded_material = MaterialOutputModel(guid = "", type = "PLA", color = "Blue", brand = "Generic", name = "Blue PLA")
    loaded_left_extruder = ExtruderConfigurationModel(0)
    loaded_left_extruder.setMaterial(loaded_material)
    loaded_right_extruder = ExtruderConfigurationModel(1)
    loaded_right_extruder.setMaterial(loaded_material)
    printer.printerConfiguration.setExtruderConfigurations([loaded_left_extruder, loaded_right_extruder])
    assert printer_output_device.uniqueConfigurations == [configuration, printer.printerConfiguration]
Example #9
0
 def _createPrinterList(self) -> None:
     printer = PrinterOutputModel(output_controller=self._output_controller, number_of_extruders=self._number_of_extruders)
     printer.updateName(self.name)
     self._printers = [printer]
     self.printersChanged.emit()
Example #10
0
    def updateOutputModel(self, model: PrinterOutputModel) -> None:
        model.updateKey(self.uuid)
        model.updateName(self.friendly_name)
        model.updateType(self.machine_variant)
        model.updateState(self.status if self.enabled else "disabled")
        model.updateBuildplate(
            self.build_plate.type if self.build_plate else "glass")
        model.setCameraUrl(
            QUrl("http://{}:8080/?action=stream".format(self.ip_address)))

        # Set the possible configurations based on whether a Material Station is present or not.
        if self.material_station and self.material_station.material_slots:
            self._updateAvailableConfigurations(model)
        if self.configuration:
            self._updateActiveConfiguration(model)
Example #11
0
    def updateOutputModel(self, model: PrinterOutputModel) -> None:
        model.updateKey(self.uuid)
        model.updateName(self.friendly_name)
        model.updateType(self.machine_variant)
        model.updateState(self.status if self.enabled else "disabled")
        model.updateBuildplate(
            self.build_plate.type if self.build_plate else "glass")
        model.setCameraUrl(
            QUrl("http://{}:8080/?action=stream".format(self.ip_address)))

        if model.printerConfiguration is not None:
            for configuration, extruder_output, extruder_config in \
                    zip(self.configuration, model.extruders, model.printerConfiguration.extruderConfigurations):
                configuration.updateOutputModel(extruder_output)
                configuration.updateConfigurationModel(extruder_config)
Example #12
0
    def _updatePrinter(self, printer: PrinterOutputModel,
                       data: Dict[str, Any]) -> None:
        # For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.
        # Then we suddenly need the unique name. So in order to not have to mess up all the other code, we save a mapping.
        self._printer_uuid_to_unique_name_mapping[
            data["uuid"]] = data["unique_name"]

        definitions = ContainerRegistry.getInstance().findDefinitionContainers(
            name=data["machine_variant"])
        if not definitions:
            Logger.log("w", "Unable to find definition for machine variant %s",
                       data["machine_variant"])
            return

        machine_definition = definitions[0]

        printer.updateName(data["friendly_name"])
        printer.updateKey(data["uuid"])
        printer.updateType(data["machine_variant"])

        if data["status"] != "unreachable":
            self._application.getDiscoveredPrintersModel(
            ).updateDiscoveredPrinter(data["ip_address"],
                                      name=data["friendly_name"],
                                      machine_type=data["machine_variant"])

        # Do not store the build plate information that comes from connect if the current printer has not build plate information
        if "build_plate" in data and machine_definition.getMetaDataEntry(
                "has_variant_buildplates", False):
            printer.updateBuildplate(data["build_plate"]["type"])
        if not data["enabled"]:
            printer.updateState("disabled")
        else:
            printer.updateState(data["status"])

        for index in range(0, self._number_of_extruders):
            extruder = printer.extruders[index]
            try:
                extruder_data = data["configuration"][index]
            except IndexError:
                break

            extruder.updateHotendID(extruder_data.get("print_core_id", ""))

            material_data = extruder_data["material"]
            if extruder.activeMaterial is None or extruder.activeMaterial.guid != material_data[
                    "guid"]:
                material = self._createMaterialOutputModel(material_data)
                extruder.updateActiveMaterial(material)
    def _onGetPrinterDataFinished(self, reply):
        status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute)
        if status_code == 200:
            try:
                result = json.loads(bytes(reply.readAll()).decode("utf-8"))
            except json.decoder.JSONDecodeError:
                Logger.log("w", "Received an invalid printer state message: Not valid JSON.")
                return

            if not self._printers:
                # Quickest way to get the firmware version is to grab it from the zeroconf.
                firmware_version = self._properties.get(b"firmware_version", b"").decode("utf-8")
                self._printers = [PrinterOutputModel(output_controller=self._output_controller, number_of_extruders=self._number_of_extruders, firmware_version=firmware_version)]
                self._printers[0].setCameraUrl(QUrl("http://" + self._address + ":8080/?action=stream"))
                for extruder in self._printers[0].extruders:
                    extruder.activeMaterialChanged.connect(self.materialIdChanged)
                    extruder.hotendIDChanged.connect(self.hotendIdChanged)
                self.printersChanged.emit()

            # LegacyUM3 always has a single printer.
            printer = self._printers[0]
            printer.updateBedTemperature(result["bed"]["temperature"]["current"])
            printer.updateTargetBedTemperature(result["bed"]["temperature"]["target"])
            printer.updateState(result["status"])

            try:
                # If we're still handling the request, we should ignore remote for a bit.
                if not printer.getController().isPreheatRequestInProgress():
                    printer.updateIsPreheating(result["bed"]["pre_heat"]["active"])
            except KeyError:
                # Older firmwares don't support preheating, so we need to fake it.
                pass

            head_position = result["heads"][0]["position"]
            printer.updateHeadPosition(head_position["x"], head_position["y"], head_position["z"])

            for index in range(0, self._number_of_extruders):
                temperatures = result["heads"][0]["extruders"][index]["hotend"]["temperature"]
                extruder = printer.extruders[index]
                extruder.updateTargetHotendTemperature(temperatures["target"])
                extruder.updateHotendTemperature(temperatures["current"])

                material_guid = result["heads"][0]["extruders"][index]["active_material"]["guid"]

                if extruder.activeMaterial is None or extruder.activeMaterial.guid != material_guid:
                    # Find matching material (as we need to set brand, type & color)
                    containers = ContainerRegistry.getInstance().findInstanceContainers(type="material",
                                                                                        GUID=material_guid)
                    if containers:
                        color = containers[0].getMetaDataEntry("color_code")
                        brand = containers[0].getMetaDataEntry("brand")
                        material_type = containers[0].getMetaDataEntry("material")
                        name = containers[0].getName()
                    else:
                        # Unknown material.
                        color = "#00000000"
                        brand = "Unknown"
                        material_type = "Unknown"
                        name = "Unknown"
                    material = MaterialOutputModel(guid=material_guid, type=material_type,
                                                   brand=brand, color=color, name = name)
                    extruder.updateActiveMaterial(material)

                try:
                    hotend_id = result["heads"][0]["extruders"][index]["hotend"]["id"]
                except KeyError:
                    hotend_id = ""
                printer.extruders[index].updateHotendID(hotend_id)

        else:
            Logger.log("w",
                       "Got status code {status_code} while trying to get printer data".format(status_code = status_code))
Example #14
0
 def _createPrinterModel(self, data: Dict[str, Any]) -> PrinterOutputModel:
     printer = PrinterOutputModel(output_controller = ClusterUM3PrinterOutputController(self),
                                  number_of_extruders = self._number_of_extruders)
     printer.setCameraUrl(QUrl("http://" + data["ip_address"] + ":8080/?action=stream"))
     self._printers.append(printer)
     return printer
Example #15
0
    def updateOutputModel(self, model: PrinterOutputModel) -> None:
        model.updateKey(self.uuid)
        model.updateName(self.friendly_name)
        model.updateType(self.machine_variant)
        model.updateState(self.status if self.enabled else "disabled")
        model.updateBuildplate(
            self.build_plate.type if self.build_plate else "glass")
        model.setCameraUrl(
            QUrl("http://{}:8080/?action=stream".format(self.ip_address)))

        if not model.printerConfiguration:
            # Prevent accessing printer configuration when not available.
            # This sometimes happens when a printer was just added to a group and Cura is connected to that group.
            return

        # Set the possible configurations based on whether a Material Station is present or not.
        if self.material_station and self.material_station.material_slots:
            self._updateAvailableConfigurations(model)
        if self.configuration:
            self._updateActiveConfiguration(model)
Example #16
0
    def _updatePrinter(self, printer: PrinterOutputModel, data: Dict[str, Any]) -> None:
        # For some unknown reason the cluster wants UUID for everything, except for sending a job directly to a printer.
        # Then we suddenly need the unique name. So in order to not have to mess up all the other code, we save a mapping.
        self._printer_uuid_to_unique_name_mapping[data["uuid"]] = data["unique_name"]

        definitions = ContainerRegistry.getInstance().findDefinitionContainers(name = data["machine_variant"])
        if not definitions:
            Logger.log("w", "Unable to find definition for machine variant %s", data["machine_variant"])
            return

        machine_definition = definitions[0]

        printer.updateName(data["friendly_name"])
        printer.updateKey(data["uuid"])
        printer.updateType(data["machine_variant"])

        if data["status"] != "unreachable":
            self._application.getDiscoveredPrintersModel().updateDiscoveredPrinter(data["ip_address"],
                                                                               name = data["friendly_name"],
                                                                               machine_type = data["machine_variant"])

        # Do not store the build plate information that comes from connect if the current printer has not build plate information
        if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
            printer.updateBuildplate(data["build_plate"]["type"])
        if not data["enabled"]:
            printer.updateState("disabled")
        else:
            printer.updateState(data["status"])

        for index in range(0, self._number_of_extruders):
            extruder = printer.extruders[index]
            try:
                extruder_data = data["configuration"][index]
            except IndexError:
                break

            extruder.updateHotendID(extruder_data.get("print_core_id", ""))

            material_data = extruder_data["material"]
            if extruder.activeMaterial is None or extruder.activeMaterial.guid != material_data["guid"]:
                material = self._createMaterialOutputModel(material_data)
                extruder.updateActiveMaterial(material)
Example #17
0
 def _createPrinterModel(self, data: Dict[str, Any]) -> PrinterOutputModel:
     printer = PrinterOutputModel(output_controller = ClusterUM3PrinterOutputController(self),
                                  number_of_extruders = self._number_of_extruders)
     printer.setCameraUrl(QUrl("http://" + data["ip_address"] + ":8080/?action=stream"))
     self._printers.append(printer)
     return printer
Example #18
0
 def _build_printer_output_model(self) -> PrinterOutputModel:
     """Returns printer Output Model for this device."""
     printer_output_model = PrinterOutputModel(
         output_controller=self._printer_output_controller,
         number_of_extruders=_NUM_EXTRUDERS)
     printer_output_model.updateKey(self._address)
     printer_output_model.updateName(self.address)
     printer_output_model.updateState('idle')
     printer_output_model.setAvailableConfigurations(
         [_build_printer_conf_model()])
     printer_output_model.updateType('Monoprice Select Mini')
     printer_output_model.updateActivePrintJob(self._print_job_model)
     return printer_output_model
Example #19
0
 def createOutputModel(self, controller: PrinterOutputController) -> PrinterOutputModel:
     model = PrinterOutputModel(controller, len(self.configuration), firmware_version = self.firmware_version)
     self.updateOutputModel(model)
     return model
Example #20
0
        "value": ["yay"]
    },
]

test_validate_data_get_update = [
    {
        "attribute": "configuration",
        "value": PrinterConfigurationModel()
    },
    {
        "attribute": "owner",
        "value": "WHOO"
    },
    {
        "attribute": "assignedPrinter",
        "value": PrinterOutputModel(MagicMock())
    },
    {
        "attribute": "key",
        "value": "YAY"
    },
    {
        "attribute": "name",
        "value": "Turtles"
    },
    {
        "attribute": "timeTotal",
        "value": 10
    },
    {
        "attribute": "timeElapsed",