From 4581722bbeff521f511a83f828e3becd880af041 Mon Sep 17 00:00:00 2001 From: James Gao Date: Tue, 8 Oct 2013 18:37:56 -0700 Subject: [PATCH 1/9] Less scary message with Ctrl-C, remove gcode viewer for android --- src/octoprint/server.py | 2 ++ src/octoprint/static/js/app/main.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/octoprint/server.py b/src/octoprint/server.py index 0bf86796..44056155 100644 --- a/src/octoprint/server.py +++ b/src/octoprint/server.py @@ -1207,6 +1207,8 @@ class Server(): printer.connect(port, baudrate) try: IOLoop.instance().start() + except KeyboardInterrupt: + logger.info("Goodbye!") except: logger.fatal("Now that is embarrassing... Something really really went wrong here. Please report this including the stacktrace below in OctoPrint's bugtracker. Thanks!") logger.exception("Stacktrace follows:") diff --git a/src/octoprint/static/js/app/main.js b/src/octoprint/static/js/app/main.js index e4cd786e..9cc5e913 100644 --- a/src/octoprint/static/js/app/main.js +++ b/src/octoprint/static/js/app/main.js @@ -1,4 +1,9 @@ $(function() { + //Detect mobile browsers and remove gcode pane + //from http://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-handheld-device-in-jquery + if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { + $("#gcode, a[href='#gcode']").remove(); + } //~~ Initialize view models var loginStateViewModel = new LoginStateViewModel(); From 858873dfa03090d56298fecd649fd407854fe7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 20 Jan 2014 15:33:08 +0100 Subject: [PATCH 2/9] Also provide the filename (basename without the path) in print events --- src/octoprint/util/comm.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 1a970495..4679fc22 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -341,6 +341,7 @@ class MachineCom(object): if self._currentFile is not None: payload = { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation() } eventManager().fire(Events.PRINT_FAILED, payload) @@ -372,6 +373,7 @@ class MachineCom(object): self._changeState(self.STATE_PRINTING) eventManager().fire(Events.PRINT_STARTED, { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation() }) @@ -438,6 +440,7 @@ class MachineCom(object): eventManager().fire(Events.PRINT_CANCELLED, { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation() }) @@ -454,6 +457,7 @@ class MachineCom(object): eventManager().fire(Events.PRINT_RESUMED, { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation() }) elif pause and self.isPrinting(): @@ -463,6 +467,7 @@ class MachineCom(object): eventManager().fire(Events.PRINT_PAUSED, { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation() }) @@ -665,6 +670,7 @@ class MachineCom(object): self._changeState(self.STATE_OPERATIONAL) eventManager().fire(Events.PRINT_DONE, { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation(), "time": time.time() - self._currentFile.getStartTime() }) @@ -939,6 +945,7 @@ class MachineCom(object): else: payload = { "file": self._currentFile.getFilename(), + "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation(), "time": time.time() - self._currentFile.getStartTime() } From 3f7b222b92fb48817a168a4272128afcd3b91030 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Fri, 14 Feb 2014 11:33:53 -0800 Subject: [PATCH 3/9] fix up urls in API example requests --- docs/api/connection.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/connection.rst b/docs/api/connection.rst index 27feb765..ee2f88f2 100644 --- a/docs/api/connection.rst +++ b/docs/api/connection.rst @@ -20,7 +20,7 @@ Get connection settings .. sourcecode:: http - GET /api/control/connection HTTP/1.1 + GET /api/connection HTTP/1.1 Host: example.com Content-Type: application/json X-Api-Key: abcdef... @@ -77,7 +77,7 @@ Issue a connection command .. sourcecode:: http - POST /api/control/connection HTTP/1.1 + POST /api/connection HTTP/1.1 Host: example.com Content-Type: application/json X-Api-Key: abcdef... @@ -94,7 +94,7 @@ Issue a connection command .. sourcecode:: http - POST /api/control/connection HTTP/1.1 + POST /api/connection HTTP/1.1 Host: example.com Content-Type: application/json X-Api-Key: abcdef... From a630b74fa818bdb0d6dd85ed17d1005d8af1a0a3 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Fri, 14 Feb 2014 20:55:42 -0800 Subject: [PATCH 4/9] fix crash when getStartTime() returns None --- src/octoprint/util/comm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 4679fc22..6a805d7e 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -672,7 +672,7 @@ class MachineCom(object): "file": self._currentFile.getFilename(), "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation(), - "time": time.time() - self._currentFile.getStartTime() + "time": self.getPrintTime() }) elif 'Done saving file' in line: self.refreshSdFiles() @@ -934,7 +934,7 @@ class MachineCom(object): payload = { "local": self._currentFile.getLocalFilename(), "remote": self._currentFile.getRemoteFilename(), - "time": time.time() - self._currentFile.getStartTime() + "time": self.getPrintTime() } self._currentFile = None @@ -947,7 +947,7 @@ class MachineCom(object): "file": self._currentFile.getFilename(), "filename": os.path.basename(self._currentFile.getFilename()), "origin": self._currentFile.getFileLocation(), - "time": time.time() - self._currentFile.getStartTime() + "time": self.getPrintTime() } self._callback.mcPrintjobDone() self._changeState(self.STATE_OPERATIONAL) From b8a59097c270740a9a96a2145998436796e04e5c Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Fri, 14 Feb 2014 22:51:27 -0800 Subject: [PATCH 5/9] correct response code for connection success --- docs/api/connection.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/connection.rst b/docs/api/connection.rst index 27feb765..19841545 100644 --- a/docs/api/connection.rst +++ b/docs/api/connection.rst @@ -114,6 +114,6 @@ Issue a connection command Defaults to ``false`` if not set. :json boolean autoconnect: ``connect`` command: Whether to attempt to automatically connect to the printer on server startup. If not set no changes will be made to the current setting. - :statuscode 200: No error + :statuscode 204: No error :statuscode 400: If the selected `port` or `baudrate` for a ``connect`` command are not part of the available options. \ No newline at end of file From 322834b762548ccedab1dbc2c2704dc62b5db0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sat, 15 Feb 2014 09:58:52 +0100 Subject: [PATCH 6/9] Moved "Less scary error message" patch to new location --- src/octoprint/server/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index 1fccc3e3..705c1afb 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -190,6 +190,8 @@ class Server(): printer.connect(port, baudrate) try: IOLoop.instance().start() + except KeyboardInterrupt: + logger.info("Goodbye!") except: logger.fatal("Now that is embarrassing... Something really really went wrong here. Please report this including the stacktrace below in OctoPrint's bugtracker. Thanks!") logger.exception("Stacktrace follows:") From 3f86272913ffe662b4eb2296c6b01be6d9e1f81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sat, 15 Feb 2014 10:00:14 +0100 Subject: [PATCH 7/9] There's now a different mechanism in place to prevent mobile browsers from crashing on large gcode files being visualized --- src/octoprint/static/js/app/main.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/octoprint/static/js/app/main.js b/src/octoprint/static/js/app/main.js index 66fd1ba4..dfe612c1 100644 --- a/src/octoprint/static/js/app/main.js +++ b/src/octoprint/static/js/app/main.js @@ -1,10 +1,4 @@ $(function() { - //Detect mobile browsers and remove gcode pane - //from http://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-handheld-device-in-jquery - if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { - $("#gcode, a[href='#gcode']").remove(); - } - //~~ Initialize view models var loginStateViewModel = new LoginStateViewModel(); var usersViewModel = new UsersViewModel(loginStateViewModel); From 592f3dce9a4e808c3e0c3287af89093a4454d55d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sat, 15 Feb 2014 10:26:39 +0100 Subject: [PATCH 8/9] Bugfix: Do not run gcode analyzer when a print is ongoing Evaluate active flag on gcode analyzer AFTER fetching an item from the work queue, otherwise it will always start working once it finds something if the active flag was true once but then switched to false while the queue was still empty. Thanks to @Salandora for spotting this. Fixes #357 --- src/octoprint/gcodefiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/octoprint/gcodefiles.py b/src/octoprint/gcodefiles.py index 34860bad..a6cf1fe4 100644 --- a/src/octoprint/gcodefiles.py +++ b/src/octoprint/gcodefiles.py @@ -560,8 +560,6 @@ class MetadataAnalyzer: def _work(self): aborted = None while True: - self._active.wait() - if aborted is not None: filename = aborted aborted = None @@ -570,6 +568,8 @@ class MetadataAnalyzer: (priority, filename) = self._queue.get() self._logger.debug("Processing file %s from queue (priority %d)" % (filename, priority)) + self._active.wait() + try: self._analyzeGcode(filename) self._queue.task_done() From b115b6f66ca80c2c38e1aa214e278416ea3cda0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 17 Feb 2014 10:25:40 +0100 Subject: [PATCH 9/9] Only list those SD files that have a ASCII filename According to the RepRap protocol we should actually not ever get anything other than those anyways, as the protocol is defined as ASCII-only. In the future there might be a way to somehow handle such files too, for the time being this fixes issues though where non-ascii files on the SD made the whole SD file handling not work. Closes #381 --- src/octoprint/util/__init__.py | 18 ++++++++++++++++++ src/octoprint/util/comm.py | 10 +++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/octoprint/util/__init__.py b/src/octoprint/util/__init__.py index 437af118..0c5e66d2 100644 --- a/src/octoprint/util/__init__.py +++ b/src/octoprint/util/__init__.py @@ -191,6 +191,24 @@ def silentRemove(file): pass +def sanitizeAscii(line): + return unicode(line, 'ascii', 'replace').encode('ascii', 'replace').rstrip() + + +def filterNonAscii(line): + """ + Returns True if the line contains non-ascii characters, false otherwise + + @param line the line to test + """ + + try: + unicode(line, 'ascii').encode('ascii') + return False + except ValueError: + return True + + def getJsonCommandFromRequest(request, valid_commands): if not "application/json" in request.headers["Content-Type"]: return None, None, make_response("Expected content-type JSON", 400) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 6a805d7e..091bbddf 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -23,7 +23,7 @@ from octoprint.settings import settings from octoprint.events import eventManager, Events from octoprint.filemanager.destinations import FileDestinations from octoprint.gcodefiles import isGcodeFileName -from octoprint.util import getExceptionString, getNewTimeout +from octoprint.util import getExceptionString, getNewTimeout, sanitizeAscii, filterNonAscii from octoprint.util.virtual import VirtualPrinter try: @@ -605,7 +605,11 @@ class MachineCom(object): ##~~ SD file list # if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing if self._sdFileList and isGcodeFileName(line.strip().lower()) and not 'End file list' in line: - self._sdFiles.append(line.strip().lower()) + filename = line.strip().lower() + if filterNonAscii(filename): + self._logger.warn("Got a file from printer's SD that has a non-ascii filename (%s), that shouldn't happen according to the protocol" % filename) + else: + self._sdFiles.append(filename) continue ##~~ Temperature processing @@ -920,7 +924,7 @@ class MachineCom(object): if ret == '': #self._log("Recv: TIMEOUT") return '' - self._log("Recv: %s" % (unicode(ret, 'ascii', 'replace').encode('ascii', 'replace').rstrip())) + self._log("Recv: %s" % sanitizeAscii(ret)) return ret def _sendNext(self):