diff --git a/README.md b/README.md index c916947..98923ac 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ The Printer WebUI provides a responsive web interface for controlling a 3D print allows * uploading .gcode files to the server and managing them via the UI -* selecting a file for printing, getting the usual stats regarding filament length etc +* selecting a file for printing, getting the usual stats regarding filament length etc (stats can be disabled for + faster initial processing) * starting, pausing and canceling a print job * while connected to the printer, gaining information regarding the current temperature of both head and bed (if available) in a nice shiny javascript-y temperature graph * while printing, gaining information regarding the current progress of the print job (height, percentage etc) @@ -49,40 +50,54 @@ Alternatively, the host and port on which to bind can be defined via the configu Configuration ------------- -The config-file `config.ini` for Printer WebUI is expected at `~/.printerwebui` for Linux, at `%APPDATA%/PrinterWebUI` -for Windows and at `~/Library/Application Support` for MacOS X. +The config-file `config.ini` for Printer WebUI is expected in its settings folder, which is located at `~/.printerwebui` +on Linux, at `%APPDATA%/PrinterWebUI` on Windows and at `~/Library/Application Support` on MacOS X. The following example config should explain the available options: [serial] - # use the following option to define the default serial port, defaults to unset (= AUTO) + # Use the following option to define the default serial port, defaults to unset (= AUTO) port = /dev/ttyACM0 - # use the following option to define the default baudrate, defaults to unset (= AUTO) + + # Use the following option to define the default baudrate, defaults to unset (= AUTO) baudrate = 115200 [server] - # use this option to define the host to which to bind the server, defaults to "0.0.0.0" (= all interfaces) + # Use this option to define the host to which to bind the server, defaults to "0.0.0.0" (= all interfaces) host = 0.0.0.0 - # use this option to define the port to which to bind the server, defaults to 5000 + + # Use this option to define the port to which to bind the server, defaults to 5000 port = 5000 [webcam] - # use this option to enable display of a webcam stream in the UI, e.g. via MJPG-Streamer. + # Use this option to enable display of a webcam stream in the UI, e.g. via MJPG-Streamer. # Webcam support will be disabled if not set stream = http://:/?action=stream - # use this option to enable timelapse support via snapshot, e.g. via MJPG-Streamer. + + # Use this option to enable timelapse support via snapshot, e.g. via MJPG-Streamer. # Timelapse support will be disabled if not set snapshot = http://:/?action=snapshot - # path to ffmpeg binary to use for creating timelapse recordings. + + # Path to ffmpeg binary to use for creating timelapse recordings. # Timelapse support will be disabled if not set ffmpeg = /path/to/ffmpeg + [feature] + # Whether to enable gcode analysis for displaying needed filament and estimated print time. Disabling this (set + # to False) will speed up the loading of gcode files before printing significantly, but the mentioned statistical + # data will not be available + analyzeGcode = True + [folder] - # absolute path where to store gcode uploads. Defaults to the uploads folder in the Printer WebUI settings dir + # Absolute path where to store gcode uploads. Defaults to the uploads folder in the Printer WebUI settings folder uploads = /path/to/upload/folder - # absolute path where to store finished timelapse recordings. Defaults to the timelapse folder in the Printer WebUI settings dir + + # Absolute path where to store finished timelapse recordings. Defaults to the timelapse folder in the Printer WebUI + # settings dir timelapse = /path/to/timelapse/folder - # absolute path where to store temporary timelapse files. Defaults to the timelapse/tmp folder in the Printer WebUI settings dir + + # Absolute path where to store temporary timelapse files. Defaults to the timelapse/tmp folder in the Printer WebUI + # settings dir timelapse_tmp = /path/timelapse/tmp/folder Setup on a Raspberry Pi running Raspbian diff --git a/printer_webui/printer.py b/printer_webui/printer.py index b9c16f5..7524d89 100644 --- a/printer_webui/printer.py +++ b/printer_webui/printer.py @@ -295,6 +295,9 @@ class Printer(): formattedPrintTimeEstimation = _getFormattedTimeDelta(datetime.timedelta(minutes=self._gcode.totalMoveTimeMinute)) if self._gcode.extrusionAmount: formattedFilament = "%.2fm" % (self._gcode.extrusionAmount / 1000) + elif not settings().getBoolean("feature", "analyzeGcode"): + formattedPrintTimeEstimation = "unknown" + formattedFilament = "unknown" formattedFilename = None if self._filename: @@ -385,12 +388,12 @@ class Printer(): #~~ callbacks triggered by gcodeLoader - def _onGcodeLoadingProgress(self, filename, progress): + def _onGcodeLoadingProgress(self, filename, progress, mode): formattedFilename = None if filename is not None: formattedFilename = os.path.basename(filename) - self._stateMonitor.setGcodeData({"filename": formattedFilename, "progress": progress}) + self._stateMonitor.setGcodeData({"filename": formattedFilename, "progress": progress, "mode": mode}) def _onGcodeLoaded(self, filename, gcode, gcodeList): formattedFilename = None @@ -464,8 +467,6 @@ class GcodeLoader(threading.Thread): self._loadedCallback = loadedCallback self._filename = filename - self._progress = None - self._gcode = None self._gcodeList = None @@ -473,6 +474,7 @@ class GcodeLoader(threading.Thread): #Send an initial M110 to reset the line counter to zero. prevLineType = lineType = "CUSTOM" gcodeList = ["M110"] + filesize = os.stat(self._filename).st_size with open(self._filename, "r") as file: for line in file: if line.startswith(";TYPE:"): @@ -486,17 +488,21 @@ class GcodeLoader(threading.Thread): else: gcodeList.append(line) prevLineType = lineType + self._onLoadingProgress(float(file.tell()) / float(filesize)) self._gcodeList = gcodeList - self._gcode = gcodeInterpreter.gcode() - self._gcode.progressCallback = self.onProgress - self._gcode.loadList(self._gcodeList) + if settings().getBoolean("feature", "analyzeGcode"): + self._gcode = gcodeInterpreter.gcode() + self._gcode.progressCallback = self._onParsingProgress + self._gcode.loadList(self._gcodeList) self._loadedCallback(self._filename, self._gcode, self._gcodeList) - def onProgress(self, progress): - self._progress = progress - self._progressCallback(self._filename, self._progress) + def _onLoadingProgress(self, progress): + self._progressCallback(self._filename, progress, "loading") + + def _onParsingProgress(self, progress): + self._progressCallback(self._filename, progress, "parsing") class PrinterCallback(object): def sendCurrentData(self, data): diff --git a/printer_webui/server.py b/printer_webui/server.py index 3b51dc4..bbf3fc7 100644 --- a/printer_webui/server.py +++ b/printer_webui/server.py @@ -27,7 +27,8 @@ def index(): return render_template( "index.html", webcamStream=settings().get("webcam", "stream"), - enableTimelapse=(settings().get("webcam", "snapshot") is not None and settings().get("webcam", "ffmpeg") is not None) + enableTimelapse=(settings().get("webcam", "snapshot") is not None and settings().get("webcam", "ffmpeg") is not None), + enableEstimations=(settings().getBoolean("feature", "analyzeGcode")) ) #~~ Printer state diff --git a/printer_webui/settings.py b/printer_webui/settings.py index 054bd5c..97fc40c 100644 --- a/printer_webui/settings.py +++ b/printer_webui/settings.py @@ -34,6 +34,9 @@ default_settings = { "uploads": None, "timelapse": None, "timelapse_tmp": None + }, + "feature": { + "analyzeGcode": True } } @@ -87,16 +90,13 @@ class Settings(object): if section not in default_settings.keys(): return None - value = None if self._config.has_option(section, key): - value = self._config.get(section, key) - if value is None: - if default_settings.has_key(section) and default_settings[section].has_key(key): - return default_settings[section][key] - else: - return None - else: - return value + return self._config.get(section, key) + + if default_settings.has_key(section) and default_settings[section].has_key(key): + return default_settings[section][key] + + return None def getInt(self, section, key): value = self.get(section, key) @@ -108,6 +108,14 @@ class Settings(object): except ValueError: return None + def getBoolean(self, section, key): + value = self.get(section, key) + if value is None: + return None + if isinstance(value, bool): + return value + return value.lower() in ["true", "yes", "y", "1"] + def getBaseFolder(self, type): if type not in default_settings["folder"].keys(): return None diff --git a/printer_webui/static/js/ui.js b/printer_webui/static/js/ui.js index b400878..73125e1 100644 --- a/printer_webui/static/js/ui.js +++ b/printer_webui/static/js/ui.js @@ -182,7 +182,12 @@ function PrinterStateViewModel() { self._processGcodeData = function(data) { if (self.isLoading()) { - self.filename("Loading... (" + Math.round(data.progress * 100) + "%)"); + var progress = Math.round(data.progress * 100); + if (data.mode == "loading") { + self.filename("Loading... (" + progress + "%)"); + } else if (data.mode == "parsing") { + self.filename("Parsing... (" + progress + "%)"); + } } } diff --git a/printer_webui/templates/index.html b/printer_webui/templates/index.html index 587ec0f..d311bb6 100644 --- a/printer_webui/templates/index.html +++ b/printer_webui/templates/index.html @@ -52,8 +52,10 @@
Machine State:
File:
- Filament:
- Estimated Print Time:
+ {% if enableEstimations %} + Filament:
+ Estimated Print Time:
+ {% endif %} Line:
Height:
Print Time: