Added option to disable analysis of gcode upon loading a file for print. Disabling this allows for a faster loading time (especially on a Raspberry Pi) but with the disadvantage of losing information regarding estimated filament length and print time.

master
Gina Häußge 2013-01-13 00:58:54 +01:00
parent c2858200eb
commit 574961ceac
6 changed files with 73 additions and 36 deletions

View File

@ -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://<stream host>:<stream port>/?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://<stream host>:<stream port>/?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

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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 + "%)");
}
}
}

View File

@ -52,8 +52,10 @@
<div class="accordion-inner">
Machine State: <strong data-bind="text: stateString"></strong><br>
File: <strong data-bind="text: filename"></strong><br>
Filament: <strong data-bind="text: filament"></strong><br>
Estimated Print Time: <strong data-bind="text: estimatedPrintTime"></strong><br>
{% if enableEstimations %}
Filament: <strong data-bind="text: filament"></strong><br>
Estimated Print Time: <strong data-bind="text: estimatedPrintTime"></strong><br>
{% endif %}
Line: <strong data-bind="text: lineString"></strong><br>
Height: <strong data-bind="text: currentHeight"></strong><br>
Print Time: <strong data-bind="text: printTime"></strong><br>