Merge branch 'fix/optionToIgnoreFirmwareErrors' into devel

Conflicts:
	src/octoprint/server/api/settings.py
	src/octoprint/settings.py
	src/octoprint/static/js/app/dataupdater.js
	src/octoprint/static/js/app/viewmodels/settings.js
	src/octoprint/templates/dialogs/settings/serialconnection.jinja2
This commit is contained in:
Gina Häußge 2016-02-01 18:07:13 +01:00
commit adb77654f6
7 changed files with 59 additions and 6 deletions

View file

@ -454,6 +454,8 @@ class VirtualPrinter(object):
self._triggerResend(expected=self.lastN)
elif data == "drop_connection":
self._debug_drop_connection = True
elif data == "maxtemp_error":
self.outgoing.put("Error: MAXTEMP triggered!")
else:
try:
sleep_match = VirtualPrinter.sleep_regex.match(data)

View file

@ -90,7 +90,9 @@ def getSettings():
"additionalBaudrates": s.get(["serial", "additionalBaudrates"]),
"longRunningCommands": s.get(["serial", "longRunningCommands"]),
"checksumRequiringCommands": s.get(["serial", "checksumRequiringCommands"]),
"helloCommand": s.get(["serial", "helloCommand"])
"helloCommand": s.get(["serial", "helloCommand"]),
"ignoreErrorsFromFirmware": s.getBoolean(["serial", "ignoreErrorsFromFirmware"]),
"disconnectOnErrors": s.getBoolean(["serial", "disconnectOnErrors"]),
},
"folder": {
"uploads": s.getBaseFolder("uploads"),
@ -242,6 +244,8 @@ def _saveSettings(data):
if "longRunningCommands" in data["serial"] and isinstance(data["serial"]["longRunningCommands"], (list, tuple)): s.set(["serial", "longRunningCommands"], data["serial"]["longRunningCommands"])
if "checksumRequiringCommands" in data["serial"] and isinstance(data["serial"]["checksumRequiringCommands"], (list, tuple)): s.set(["serial", "checksumRequiringCommands"], data["serial"]["checksumRequiringCommands"])
if "helloCommand" in data["serial"]: s.set(["serial", "helloCommand"], data["serial"]["helloCommand"])
if "ignoreErrorsFromFirmware" in data["serial"]: s.setBoolean(["serial", "ignoreErrorsFromFirmware"], data["serial"]["ignoreErrorsFromFirmware"])
if "disconnectOnErrors" in data["serial"]: s.setBoolean(["serial", "disconnectOnErrors"], data["serial"]["disconnectOnErrors"])
oldLog = s.getBoolean(["serial", "log"])
if "log" in data["serial"].keys(): s.setBoolean(["serial", "log"], data["serial"]["log"])

View file

@ -90,6 +90,8 @@ default_settings = {
"longRunningCommands": ["G4", "G28", "G29", "G30", "G32", "M400", "M226"],
"checksumRequiringCommands": ["M110"],
"helloCommand": "M110 N0",
"disconnectOnErrors": True,
"ignoreErrorsFromFirmware": False
},
"server": {
"host": "0.0.0.0",

View file

@ -231,6 +231,22 @@ function DataUpdater(allViewModels) {
text: _.sprintf(gettext("Streamed %(local)s to %(remote)s on SD, took %(time).2f seconds"), payload),
type: "success"
});
} else if (type == "PrintCancelled") {
if (payload.firmwareError) {
new PNotify({
title: gettext("Unhandled firmware error"),
text: _.sprintf(gettext("The firmware reported an unhandled error. Due to that the ongoing print job was cancelled. Error: %(firmwareError)s"), payload),
type: "error",
hide: false
});
}
} else if (type == "Error") {
new PNotify({
title: gettext("Unhandled firmware error"),
text: _.sprintf(gettext("The firmware reported an unhandled error. Due to that OctoPrint disconnected. Error: %(error)s"), payload),
type: "error",
hide: false
});
}
var legacyEventHandlers = {

View file

@ -143,6 +143,8 @@ $(function() {
self.serial_longRunningCommands = ko.observable(undefined);
self.serial_checksumRequiringCommands = ko.observable(undefined);
self.serial_helloCommand = ko.observable(undefined);
self.serial_ignoreErrorsFromFirmware = ko.observable(undefined);
self.serial_disconnectOnErrors = ko.observable(undefined);
self.folder_uploads = ko.observable(undefined);
self.folder_timelapse = ko.observable(undefined);

View file

@ -92,6 +92,20 @@
<span class="help-inline">{{ _('Use this to define additional serial port baud rates to list for connecting with, e.g. <code>123456</code>. Comma separated.')|format(glob_url="http://docs.python.org/2/library/glob.html") }}</span>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: serial_disconnectOnErrors" id="settings-disconnectOnErrors"> {{ _('Not only cancel ongoing prints but also disconnect on unhandled errors from the firmware.') }}</span>
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: serial_ignoreErrorsFromFirmware" id="settings-ignoreErrorsFromFirmware"> {{ _('Ignore any unhandled errors from the firmware. Only use this if your firmware sends stuff prefixed with "Error" that is not an actual error. Might mask printer issues, be careful!') }} <span class="label label-important">{{ _('Warning') }}</span>
</label>
</div>
</div>
<div>
<div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'icon-caret-right icon-caret-down', container: '#settings_serialConnection .hide' }"><i class="icon-caret-right"></i> {{ _('Advanced options') }}</a></small></div>

View file

@ -256,6 +256,9 @@ class MachineCom(object):
self._resendSwallowRepetitionsCounter = 0
self._checksum_requiring_commands = settings().get(["serial", "checksumRequiringCommands"])
self._disconnect_on_errors = settings().getBoolean(["serial", "disconnectOnErrors"])
self._ignore_errors = settings().getBoolean(["serial", "ignoreErrorsFromFirmware"])
self._clear_to_send = CountedEvent(max=10, name="comm.clear_to_send")
self._send_queue = TypedQueue()
self._temperature_timer = None
@ -704,7 +707,7 @@ class MachineCom(object):
eventManager().fire(Events.FILE_DESELECTED)
self._callback.on_comm_file_selected(None, None, False)
def cancelPrint(self):
def cancelPrint(self, firmware_error=None):
if not self.isOperational() or self.isStreaming():
return
@ -722,7 +725,8 @@ class MachineCom(object):
payload = {
"file": self._currentFile.getFilename(),
"filename": os.path.basename(self._currentFile.getFilename()),
"origin": self._currentFile.getFileLocation()
"origin": self._currentFile.getFileLocation(),
"firmwareError": firmware_error
}
self.sendGcodeScript("afterPrintCancelled", replacements=dict(event=payload))
@ -1443,9 +1447,18 @@ class MachineCom(object):
#Ignore unkown command errors, it could be a typo or some missing feature
pass
elif not self.isError():
self._errorValue = line[6:] if line.startswith("Error:") else line[2:]
self._changeState(self.STATE_ERROR)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
error_text = line[6:] if line.startswith("Error:") else line[2:]
if not self._ignore_errors:
if self._disconnect_on_errors:
self._errorValue = error_text
self._changeState(self.STATE_ERROR)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
elif self.isPrinting():
self.cancelPrint(firmware_error=error_text)
self._clear_to_send.set()
else:
self._log("WARNING! Received an error from the printer's firmware, ignoring that as configured but you might want to investigate what happened here! Error: {}".format(error_text))
self._clear_to_send.set()
return line
def _readline(self):