Skip to content

Commit

Permalink
Version number bumped to 1.3.0
Browse files Browse the repository at this point in the history
Auto-print checkbox moved to filename dialog box and now it's preset is being stored in preferences
Added setting for enabling Chamber Loop fans while printing at specified layer (setting is under the Cura's "Cooling" section)
Fixed: When aborting print from Cura, in monitor stage the printer state showing 'pause' until printer finishes the abort command
Updated README.md
  • Loading branch information
alkaes committed Oct 9, 2020
1 parent 8712ab2 commit 3384d1f
Showing 5 changed files with 138 additions and 15 deletions.
64 changes: 53 additions & 11 deletions QidiPrintOutputDevice.py
Original file line number Diff line number Diff line change
@@ -63,6 +63,11 @@ def __init__(self, name, address):
self._PluginName = 'QIDI Print'
self.setPriority(3)

self._application = CuraApplication.getInstance()
self._preferences = Application.getInstance().getPreferences()
self._preferences.addPreference("QidiPrint/autoprint", False)
self._autoPrint = self._preferences.getValue("QidiPrint/autoprint")

self._update_timer.setInterval(1000)

self._output_controller = GenericOutputController(self)
@@ -134,7 +139,8 @@ def resumePrint(self):
self.sendCommand("M24")

def cancelPrint(self):
self.sendCommand("M33")
self._cancelPrint = True
self.sendCommand("M33")

def _update_status(self):
printer = self.printers[0]
@@ -172,14 +178,18 @@ def _update_status(self):
if progress > 0:
print_job.updateTimeTotal(int(self._qidi._printing_time / progress))
if self._qidi._isIdle:
job_state = 'paused'
if self._cancelPrint:
job_state = 'aborting'
else:
job_state = 'paused'
else:
job_state = 'printing'
print_job.updateState(job_state)
else:
if printer.activePrintJob:
printer.updateActivePrintJob(None)
job_state = 'idle'
self._cancelPrint = False
print_job = None

printer.updateState(job_state)
@@ -203,9 +213,10 @@ def requestWrite(self, node, fileName=None, *args, **kwargs):
self._dialog.textChanged.connect(self.onFilenameChanged)
self._dialog.accepted.connect(self.onFilenameAccepted)
self._dialog.show()
self._dialog.findChild(QObject, "autoPrint").setProperty('checked', self._autoPrint)
self._dialog.findChild(QObject, "nameField").setProperty('text', self.targetSendFileName)
self._dialog.findChild(QObject, "nameField").select(0, len(self.targetSendFileName))
self._dialog.findChild(QObject, "nameField").setProperty('focus', True)
self._dialog.findChild(QObject, "nameField").setProperty('focus', True)

def onFilenameChanged(self):
fileName = self._dialog.findChild(QObject, "nameField").property('text').strip()
@@ -245,6 +256,7 @@ def startSendingThread(self):
self._message.addAction("PRINT", catalog.i18nc("@action:button", "YES"), None, "")
self._message.addAction("NO", catalog.i18nc("@action:button", "NO"), None, "")
self._message.actionTriggered.connect(self._onActionTriggered)
self._message.setProgress(None)
self._message.show()
else:
self._onActionTriggered(self._message, "PRINT")
@@ -278,11 +290,46 @@ def startSendingThread(self):
self._message.show()
Logger.log('e', result_msg)

def updateChamberFan(self):
global_container_stack = self._application.getGlobalContainerStack()
if not global_container_stack:
return

cooling_chamber = global_container_stack.getProperty("cooling_chamber", "value")
if cooling_chamber == False:
return

cooling_chamber_at_layer = global_container_stack.getProperty("cooling_chamber_at_layer", "value")

scene = self._application.getController().getScene()
gcode_dict = getattr(scene, "gcode_dict", {})
if not gcode_dict:
return

data = gcode_dict[0]
for layer in data:
lines = layer.split("\n")
for line in lines:
if ";LAYER:" in line:
index = data.index(layer)
current_layer = int(line.split(":")[1])
if current_layer == cooling_chamber_at_layer:
layer = "M106 T-2 ;Enable chamber loop\n" + layer
data[index] = layer
data[-1] = "M107 T-2 ;Disable chamber loop\n" + data[-1]
setattr(scene, "gcode_dict", gcode_dict)
return


def onFilenameAccepted(self):
self.targetSendFileName = self._dialog.findChild(QObject, "nameField").property('text').strip()
autoprint = self._dialog.findChild(QObject, "autoPrint").property('checked')
if autoprint != self._autoPrint:
self._autoPrint = autoprint
self._preferences.setValue("QidiPrint/autoprint", self._autoPrint)
Logger.log("d", self._name + " | Filename set to: " + self.targetSendFileName)
self._dialog.deleteLater()

self._dialog.deleteLater()
self.updateChamberFan()
success = False
with open(self._localTempGcode, 'w+', buffering=1) as fp:
if fp:
@@ -293,12 +340,10 @@ def onFilenameAccepted(self):
self._message = Message(
catalog.i18nc("@info:status", "Uploading to {}").format(self._name),
title=catalog.i18nc("@label", "Print jobs"),
progress=-1, lifetime=0, dismissable=False, use_inactivity_timer=False, option_text="Auto Print", option_state=False
progress=-1, lifetime=0, dismissable=False, use_inactivity_timer=False
)
self._message.addAction("ABORT", catalog.i18nc("@action:button", "Cancel"), None, "")
self._message.actionTriggered.connect(self._onActionTriggered)
self._message.optionToggled.connect(self._onOptionStateChanged)
self._autoPrint = False
self._message.show()
Thread(target=self.startSendingThread, daemon=True, name=self._name + " File Send").start()
else:
@@ -319,9 +364,6 @@ def _onActionTriggered(self, message, action):
Logger.log("i", "Stopping upload because the user pressed cancel.")
self._qidi._abort = True

def _onOptionStateChanged(self, optstate):
self._autoPrint = bool(optstate)

def getProperties(self):
return self._properties

66 changes: 65 additions & 1 deletion QidiPrintPlugin.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,9 @@
from UM.Message import Message
from UM.Logger import Logger
from UM.Application import Application

from UM.Settings.SettingDefinition import SettingDefinition
from UM.Settings.DefinitionContainer import DefinitionContainer
from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.PluginRegistry import PluginRegistry
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.Signal import Signal, signalemitter
@@ -19,6 +21,7 @@
catalog = i18nCatalog("cura")

from cura.CuraApplication import CuraApplication
from collections import OrderedDict

@signalemitter
class QidiPrintPlugin(QObject, OutputDevicePlugin):
@@ -39,6 +42,67 @@ def __init__(self):
self._scan_job = QidiFinderJob()
self._scan_job.IPListChanged.connect(self._discoveredDevices)

self._i18n_catalog = catalog
self._settings_dict = OrderedDict()
self._settings_dict["cooling_chamber"] = {
"label": "Chamber Loop Fans",
"description": "Enables Chamber Loop fans while printing",
"type": "bool",
"default_value": False,
"settable_per_mesh": False,
"settable_per_extruder": False,
"settable_per_meshgroup": False
}
self._settings_dict["cooling_chamber_at_layer"] = {
"label": "Start Chamber Loop on Layer",
"description": "Start Chamber Loop on Layer Nr",
"type": "int",
"unit": "layer",
"default_value": 1,
"minimum_value": 1,
"minimum_value_warning": 1,
"enabled": "cooling_chamber",
"maximum_value_warning": 300,
"settable_per_mesh": False,
"settable_per_extruder": False,
"settable_per_meshgroup": False
}

ContainerRegistry.getInstance().containerLoadComplete.connect(self._onContainerLoadComplete)

def _onContainerLoadComplete(self, container_id):
if not ContainerRegistry.getInstance().isLoaded(container_id):
# skip containers that could not be loaded, or subsequent findContainers() will cause an infinite loop
return

try:
container = ContainerRegistry.getInstance().findContainers(id = container_id)[0]
except IndexError:
# the container no longer exists
return

if not isinstance(container, DefinitionContainer):
# skip containers that are not definitions
return
if container.getMetaDataEntry("type") == "extruder":
# skip extruder definitions
return

cooling_category = container.findDefinitions(key="cooling")
cooling_chamber_setting = container.findDefinitions(key=list(self._settings_dict.keys())[0])
if cooling_category and not cooling_chamber_setting:
# this machine doesn't have a cooling chamber setting yet
cooling_category = cooling_category[0]
for setting_key, setting_dict in self._settings_dict.items():

definition = SettingDefinition(setting_key, container, cooling_category, self._i18n_catalog)
definition.deserialize(setting_dict)

cooling_category._children.append(definition)
container._definition_cache[setting_key] = definition
container._updateRelations(definition)


@classmethod
def getInstance(cls, *args, **kwargs) -> "QidiPrintPlugin":
return cls.__instance
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -6,21 +6,31 @@

![Screenshot of the monitor stage](/screenshots/monitor.png)

## Installation via Cura Marketplace

Simply open Cura and go to the **Marketplace** in the menubar, search for the QidiPrint plugin and install it!

## Manual Installation

with Cura not running, unpack the zip file from the
With Cura not running, unpack the zip file from the
[release](https://github.com/alkaes/QidiPrint/releases/latest) to this
specific folder:


* Windows: `%USERPROFILE%\AppData\Roaming\cura\4.7\plugins\`
* MacOS: `~/Library/Application Support/Cura/4.7/plugins/`
* Linux: `/home/<username>/.local/share/cura/4.7/plugins/`

If you don't have Qidi printers available in Cura, unpack the [Qidi Printer Definitions.zip](https://github.com/alkaes/QidiPrint/releases/download/1.2.0/Qidi.Printer.Definitions.zip) to this specific folder:
* Windows: `%USERPROFILE%\AppData\Roaming\cura\4.7\`
* MacOS: `~/Library/Application Support/Cura/4.7/`
* Linux: `/home/<username>/.local/share/cura/4.7/`

## Configuration

**Do NOT try to add a new "networked printer"!** This is only for Ultimaker printers.

**If you did not use printer definitions archive from above to add Qidi printer, in order for this plugin working properly, your printer.def.json must have "manufacturer" property set to "Qidi"**

QIDI printers are configured through the extension menu bar:

* Start Cura
2 changes: 1 addition & 1 deletion plugin.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"name": "QidiPrint",
"author": "Aleksey Sokolov",
"description": "Enables remote printing and monitoring of Qidi 3D printers over network",
"version": "1.2.0",
"version": "1.3.0",
"api": 5,
"supported_sdk_versions": ["7.2.0", "7.3.0"],
"i18n-catalog": "cura"
7 changes: 7 additions & 0 deletions qml/UploadFilename.qml
Original file line number Diff line number Diff line change
@@ -48,6 +48,13 @@ UM.Dialog
visible: !base.validName;
text: base.validationError;
}

CheckBox {
objectName: "autoPrint"
id: autoPrint
checked: true
text: "Auto Print"
}
}

rightButtons: [

0 comments on commit 3384d1f

Please sign in to comment.