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.
parent
c2858200eb
commit
574961ceac
41
README.md
41
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://<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
|
||||
|
|
|
@ -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
|
||||
if settings().getBoolean("feature", "analyzeGcode"):
|
||||
self._gcode = gcodeInterpreter.gcode()
|
||||
self._gcode.progressCallback = self.onProgress
|
||||
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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
return self._config.get(section, key)
|
||||
|
||||
if default_settings.has_key(section) and default_settings[section].has_key(key):
|
||||
return default_settings[section][key]
|
||||
else:
|
||||
|
||||
return None
|
||||
else:
|
||||
return value
|
||||
|
||||
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
|
||||
|
|
|
@ -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 + "%)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
{% 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>
|
||||
|
|
Loading…
Reference in New Issue