diff --git a/octoprint/gcodefiles.py b/octoprint/gcodefiles.py index 2ac7292a..e34ae0a5 100644 --- a/octoprint/gcodefiles.py +++ b/octoprint/gcodefiles.py @@ -127,25 +127,25 @@ class GcodeManager: from octoprint.filemanager.destinations import FileDestinations if not file or not destination: - return None + return None, True local = True if destination == FileDestinations.LOCAL else False absolutePath = self.getAbsolutePath(file.filename, mustExist=False) if absolutePath is None: - return None + return None, True file.save(absolutePath) filename = file.filename if isGcodeFileName(filename): - return self.processGcode(absolutePath) + return self.processGcode(absolutePath), True curaEnabled = self._settings.get(["cura", "enabled"]) if curaEnabled and isSTLFileName(filename) and local: self.processStl(absolutePath) - return filename + return filename, False def getFutureFileName(self, file): @@ -167,10 +167,15 @@ class GcodeManager: config = self._settings.get(["cura", "config"]) slicingStart = time.time() - def stlProcessed(stlPath, gcodePath): - slicingStop = time.time() - eventManager().fire("SlicingDone", {"stl": self._getBasicFilename(stlPath), "gcode": self._getBasicFilename(gcodePath), "time": "%.2f" % (slicingStop - slicingStart)}) - self.processGcode(gcodePath) + def stlProcessed(stlPath, gcodePath, error=None): + if error: + eventManager().fire("SlicingFailed", {"stl": self._getBasicFilename(stlPath), "gcode": self._getBasicFilename(gcodePath), "reason": error}) + if os.path.exists(stlPath): + os.remove(stlPath) + else: + slicingStop = time.time() + eventManager().fire("SlicingDone", {"stl": self._getBasicFilename(stlPath), "gcode": self._getBasicFilename(gcodePath), "time": "%.2f" % (slicingStop - slicingStart)}) + self.processGcode(gcodePath) eventManager().fire("SlicingStarted", {"stl": self._getBasicFilename(absolutePath), "gcode": self._getBasicFilename(gcodePath)}) cura.process_file(config, gcodePath, absolutePath, stlProcessed, [absolutePath, gcodePath]) diff --git a/octoprint/server.py b/octoprint/server.py index 8eef377d..539696a6 100644 --- a/octoprint/server.py +++ b/octoprint/server.py @@ -83,6 +83,7 @@ class PrinterStateConnection(SockJSConnection): self._eventManager.subscribe("MovieDone", self._onMovieDone) self._eventManager.subscribe("SlicingStarted", self._onSlicingStarted) self._eventManager.subscribe("SlicingDone", self._onSlicingDone) + self._eventManager.subscribe("SlicingFailed", self._onSlicingFailed) global timelapse octoprint.timelapse.notifyCallbacks(timelapse) @@ -97,6 +98,7 @@ class PrinterStateConnection(SockJSConnection): self._eventManager.unsubscribe("MovieDone", self._onMovieDone) self._eventManager.unsubscribe("SlicingStarted", self._onSlicingStarted) self._eventManager.unsubscribe("SlicingDone", self._onSlicingDone) + self._eventManager.unsubscribe("SlicingFailed", self._onSlicingFailed) def on_message(self, message): pass @@ -155,6 +157,9 @@ class PrinterStateConnection(SockJSConnection): def _onSlicingDone(self, event, payload): self.sendUpdateTrigger("slicingDone", payload) + def _onSlicingFailed(self, event, payload): + self.sendUpdateTrigger("slicingFailed", payload) + def _emit(self, type, payload): self.send({type: payload}) @@ -410,7 +415,7 @@ def uploadGcodeFile(): destination = FileDestinations.SDCARD if sd else FileDestinations.LOCAL - filename = gcodeManager.addFile(file, destination) + filename, done = gcodeManager.addFile(file, destination) if filename is None: return make_response("Could not upload the file %s" % file.filename, 500) @@ -428,7 +433,7 @@ def uploadGcodeFile(): global eventManager eventManager.fire("Upload", filename) - return jsonify(files=gcodeManager.getAllFileData(), filename=filename) + return jsonify(files=gcodeManager.getAllFileData(), filename=filename, done=done) @app.route(BASEURL + "gcodefiles/load", methods=["POST"]) @@ -497,7 +502,10 @@ def apiLoad(): # Perform an upload file = request.files["file"] - filename = gcodeManager.addFile(file) + if not util.isGcodeFileName(file.filename): + abort(400) + + filename, done = gcodeManager.addFile(file) if filename is None: logger.warn("Upload via API failed") abort(500) diff --git a/octoprint/slicers/cura/__init__.py b/octoprint/slicers/cura/__init__.py index 0851e959..3467b208 100644 --- a/octoprint/slicers/cura/__init__.py +++ b/octoprint/slicers/cura/__init__.py @@ -56,6 +56,8 @@ class Cura(object): call_back(*call_back_args) except subprocess.CalledProcessError as (e): self._logger.warn("Could not slice via Cura, got return code %r" % e.returncode) + call_back_args.append("Got returncode %r" % e.returncode) + call_back(*call_back_args) executable = self.cura_path (workingDir, ignored) = os.path.split(executable) diff --git a/octoprint/static/js/app/dataupdater.js b/octoprint/static/js/app/dataupdater.js index 2a07e0ec..0fd509d9 100644 --- a/octoprint/static/js/app/dataupdater.js +++ b/octoprint/static/js/app/dataupdater.js @@ -107,10 +107,20 @@ function DataUpdater(loginStateViewModel, connectionViewModel, printerStateViewM } else if (type == "timelapseFiles") { timelapseViewModel.requestData(); } else if (type == "slicingStarted") { - $.pnotify({title: "Slicing started", text: "Slicing " + payload.stl + " to " + payload.gcode}); + $("#gcode_upload_progress .bar").css("width", "100%"); + $("#gcode_upload_progress").addClass("progress-striped").addClass("active"); + $("#gcode_upload_progress .bar").text("Slicing ..."); } else if (type == "slicingDone") { + $("#gcode_upload_progress .bar").css("width", "0%"); + $("#gcode_upload_progress").removeClass("progress-striped").removeClass("active"); + $("#gcode_upload_progress .bar").text(""); $.pnotify({title: "Slicing done", text: "Sliced " + payload.stl + " to " + payload.gcode + ", took " + payload.time + " seconds"}); gcodeFilesViewModel.requestData(payload.gcode); + } else if (type == "slicingFailed") { + $("#gcode_upload_progress .bar").css("width", "0%"); + $("#gcode_upload_progress").removeClass("progress-striped").removeClass("active"); + $("#gcode_upload_progress .bar").text(""); + $.pnotify({title: "Slicing failed", text: "Could not slice " + payload.stl + " to " + payload.gcode + ": " + payload.reason, type: "error"}); } break; } diff --git a/octoprint/static/js/app/main.js b/octoprint/static/js/app/main.js index ee11483f..40aecf1e 100644 --- a/octoprint/static/js/app/main.js +++ b/octoprint/static/js/app/main.js @@ -55,9 +55,11 @@ $(function() { function gcode_upload_done(e, data) { gcodeFilesViewModel.fromResponse(data.result); - $("#gcode_upload_progress .bar").css("width", "0%"); - $("#gcode_upload_progress").removeClass("progress-striped").removeClass("active"); - $("#gcode_upload_progress .bar").text(""); + if (data.result.done) { + $("#gcode_upload_progress .bar").css("width", "0%"); + $("#gcode_upload_progress").removeClass("progress-striped").removeClass("active"); + $("#gcode_upload_progress .bar").text(""); + } } function gcode_upload_fail(e, data) { diff --git a/octoprint/tests/test_file_manager.py b/octoprint/tests/test_file_manager.py index 96ba7abf..fae0bb43 100644 --- a/octoprint/tests/test_file_manager.py +++ b/octoprint/tests/test_file_manager.py @@ -33,11 +33,13 @@ class FileManipulationTestCase(unittest.TestCase): self.filenames.append(fake.filename) fake.__getitem__ = "SOMETHING" - result = self.manager.addFile(fake, FileDestinations.LOCAL) + result, done = self.manager.addFile(fake, FileDestinations.LOCAL) logging.info("RESULT:%s" % str(result)) self.assertTrue(process.called) + self.assertTrue(fake.filename == result) + self.assertFalse(done) def test_add_gcode_file(self): fake = Mock() @@ -45,11 +47,12 @@ class FileManipulationTestCase(unittest.TestCase): self.filenames.append(fake.filename) fake.__getitem__ = "SOMETHING" - result = self.manager.addFile(fake, FileDestinations.LOCAL) + result, done = self.manager.addFile(fake, FileDestinations.LOCAL) logging.info("RESULT:%s" % str(result)) self.assertTrue(fake.filename == result) + self.assertTrue(done) class FileUtilTestCase(unittest.TestCase):