diff --git a/octoprint/cura/__init__.py b/octoprint/cura/__init__.py new file mode 100644 index 00000000..a9df95b7 --- /dev/null +++ b/octoprint/cura/__init__.py @@ -0,0 +1,57 @@ +__author__ = "Ross Hendrickson savorywatt" +__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' + +import logging + +from octoprint.settings import settings + +class CuraFactory(object): + + @staticmethod + def create_slicer(path=None): + if path: + return CuraEngine(path) + current_settings = settings(init=True) + path = current_settings.get(["curaEngine", "path"]) + + return CuraEngine(path) + + +class CuraEngine(object): + + def __init__(self, cura_path): + + if not cura_path: + raise Exception("Unable to create CuraEngine - no path specified") + + self.cura_path = cura_path + + logging.info('CuraEngine Created') + + + def process_file(self, config, gcode, file_path, call_back, call_back_args): + """Wraps around the main.cpp processFile method. + :param config: :class: `string` :path to a cura config file: + :param gcode: :class: `string :path to write out the gcode generated: + :param file_path: :class: `string :path to the STL to be sliced: + :note: This will spawn a thread to handle the subprocess call and allow + us to be able to have a call back + """ + import threading + + def start_thread(call_back, call_back_args, call_args): + import subprocess + logging.info("Starting SubProcess in Thread") + logging.info("Subprocess args: %s" % str(call_args)) + process = subprocess.call(call_args) + call_back(*call_back_args) + logging.info("Slicing call back complete") + + args = [self.cura_path, '-s', config, '-o', gcode, file_path] + logging.info('CuraEngine args:%s' % str(args)) + + thread = threading.Thread(target=start_thread, args=(call_back, + call_back_args, args)) + + thread.start() + logging.info('CuraEngine Slicing File:%s' % file_path) diff --git a/octoprint/cura/cura.py b/octoprint/cura/cura.py deleted file mode 100644 index d5c7db9e..00000000 --- a/octoprint/cura/cura.py +++ /dev/null @@ -1,48 +0,0 @@ -__author__ = "Ross Hendrickson savorywatt" -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - -import logging -import subprocess - -APPNAME="OctoPrint" - - -class CuraFactory(object): - - CURA_PATH = '/home/rosshendrickson/workspaces/opensource/CuraEngine/CuraEngine' - - @staticmethod - def create_slicer(path=None): - - if path: - return CuraEngine(path) - else: - return CuraEngine(CuraFactory.CURA_PATH) - - - -class CuraEngine(object): - - def __init__(self, cura_path): - - - self.cura_path = cura_path - - logging.info('CuraEngine Created') - - - def process_file(self, config, gcode, file_path): - """Wraps around the main.cpp processFile method. - - :param config: :class: `string` :path to a cura config file: - :param gcode: :class: `string :path to write out the gcode generated: - :param file_path: :class: `string :path to the STL to be sliced: - - :note This just uses subprocess at the moment. - """ - - args = [self.cura_path, '-s', config, '-o', gcode, file_path] - logging.info('CuraEngine args:%s' % str(args)) - - process = subprocess.call(args) - logging.info('CuraEngine Exit:%s' % str(process)) diff --git a/octoprint/cura/tests/test_cura.py b/octoprint/cura/tests/test_cura.py index ad3d4cc9..a75f507f 100644 --- a/octoprint/cura/tests/test_cura.py +++ b/octoprint/cura/tests/test_cura.py @@ -1,9 +1,10 @@ import unittest +from mock import patch -from cura import CuraFactory -from cura import CuraEngine +from octoprint.cura import CuraFactory +from octoprint.cura import CuraEngine class CuraFactoryTestCase(unittest.TestCase): @@ -15,14 +16,19 @@ class CuraFactoryTestCase(unittest.TestCase): self.assertEqual(fake_path, result.cura_path) - def test_cura_engine_process_file(self): - cura_engine = CuraFactory.create_slicer() + @patch('threading.Thread') + def test_cura_engine_process_file(self, thread): + path = 'rosshendrickson/workspaces/opensource/CuraEngine/' + + cura_engine = CuraFactory.create_slicer(path) + file_path = './cura/tests/test.stl' + config_path = './cura/tests/config' + gcode_filename= './cura/tests/output.gcode' - file_path = './cura/tests/test.stl' - config_path = './cura/tests/config' - gcode_filename= './cura/tests/output.gcode' - - cura_engine.process_file(config_path, gcode_filename, file_path) + args = [path, '-s', config_path, '-o', file_path] + + cura_engine.process_file(config_path, gcode_filename, file_path) + self.assertTrue(thread.called) diff --git a/octoprint/filemanager/__init__.py b/octoprint/filemanager/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/octoprint/filemanager/types.py b/octoprint/filemanager/types.py new file mode 100644 index 00000000..0c9d098e --- /dev/null +++ b/octoprint/filemanager/types.py @@ -0,0 +1,6 @@ + + +class FileTypes(object): + + STL = "stl" + GCODE = "gcode" diff --git a/octoprint/gcodefiles.py b/octoprint/gcodefiles.py index f4cfb416..177c419b 100644 --- a/octoprint/gcodefiles.py +++ b/octoprint/gcodefiles.py @@ -114,18 +114,55 @@ class GcodeManager: #~~ file handling def addFile(self, file): - if file: - absolutePath = self.getAbsolutePath(file.filename, mustExist=False) - if absolutePath is not None: - if file.filename in self._metadata.keys(): - # delete existing metadata entry, since the file is going to get overwritten - del self._metadata[file.filename] - self._metadataDirty = True - self._saveMetadata() - file.save(absolutePath) - self._metadataAnalyzer.addFileToQueue(os.path.basename(absolutePath)) - return self._getBasicFilename(absolutePath) - return None + from octoprint.filemanager.types import FileTypes + if not file: + return None + + absolutePath = self.getAbsolutePath(file.filename, mustExist=False) + logging.info("Abs Path %s" % absolutePath) + if absolutePath is None: + return None + + file.save(absolutePath) + fileType = file.filename.rsplit(".", 1)[1] + + if not fileType: + return None + + if fileType == FileTypes.GCODE: + return self.processGcode(file.filename, absolutePath) + + if fileType == FileTypes.STL: + return self.processSTL(file.filename, absolutePath) + + def processSTL(self, filename, absolutePath): + + from octoprint.cura import CuraFactory + + callBack = self.processGcode + gcodeFileName = util.genGcodeFileName(filename) + gcodePath = util.genGcodeFileName(absolutePath) + + callBackArgs = [gcodeFileName, gcodePath] + + curaEngine = CuraFactory.create_slicer() + current_settings = settings() + + config = current_settings.get(["curaEngine", "config"]) + + curaEngine.process_file( + config, gcodePath, absolutePath, callBack, callBackArgs) + + return self._getBasicFilename(absolutePath) + + def processGcode(self, filename, absolutePath): + if filename in self._metadata.keys(): + # delete existing metadata entry, since the file is going to get overwritten + del self._metadata[filename] + self._metadataDirty = True + self._saveMetadata() + self._metadataAnalyzer.addFileToQueue(os.path.basename(absolutePath)) + return self._getBasicFilename(absolutePath) def removeFile(self, filename): filename = self._getBasicFilename(filename) @@ -139,11 +176,11 @@ class GcodeManager: def getAbsolutePath(self, filename, mustExist=True): """ - Returns the absolute path of the given filename in the gcode upload folder. + Returns the absolute path of the given filename in the correct upload folder. Ensures that the file