fixed limit hit warning and reconnect after.

This commit is contained in:
Teja 2015-07-07 18:44:29 +02:00
parent 4469f69cab
commit fc4f2340fe
7 changed files with 61 additions and 382 deletions

View file

@ -86,6 +86,9 @@ class Events(object):
# Settings
SETTINGS_UPDATED = "SettingsUpdated"
# GRBL
LIMITS_HIT = "LimitsHit"
def eventManager():

View file

@ -173,6 +173,7 @@ function DataUpdater(allViewModels) {
break;
}
case "event": {
console.log("Event", data);
var type = data["type"];
var payload = data["payload"];
var html = "";
@ -226,6 +227,14 @@ function DataUpdater(allViewModels) {
type: "success"
});
gcodeFilesViewModel.requestData(payload.remote, "sdcard");
} else if (type === "LimitsHit") {
var msg = gettext("Mr Beam has hit the limits of the working area.<br/> Please do a homing cycle get the coordinate origin again.");
new PNotify({
title: gettext("Working Area Limits Hit"),
type: "error",
hide: false,
text: msg
});
}
var legacyEventHandlers = {

View file

@ -215,10 +215,10 @@ $(function() {
if (self.previousIsOperational != self.isOperational()) {
if (self.isOperational() && connectionTab.hasClass("in")) {
// connection just got established, close connection tab for now
connectionTab.collapse("hide");
// connectionTab.collapse("hide");
} else if (!connectionTab.hasClass("in")) {
// connection just dropped, make sure connection tab is open
connectionTab.collapse("show");
// connectionTab.collapse("show");
}
}
};

View file

@ -1,55 +1,3 @@
//<<<<<<< HEAD
//function ControlViewModel(loginStateViewModel, settingsViewModel, printerStateViewModel) {
// var self = this;
//
//
// self._createToolEntry = function() {
// return {
// name: ko.observable(),
// key: ko.observable()
// }
// };
//
// self.isErrorOrClosed = ko.observable(undefined);
// self.isOperational = ko.observable(undefined);
// self.isLocked = ko.observable(undefined);
// self.isPrinting = ko.observable(undefined);
// self.isPaused = ko.observable(undefined);
// self.isError = ko.observable(undefined);
// self.isReady = ko.observable(undefined);
// self.isLoading = ko.observable(undefined);
//
// self.extrusionAmount = ko.observable(undefined);
// self.controls = ko.observableArray([]);
//
// self.tools = ko.observableArray([]);
//
// self.feedbackControlLookup = {};
//
// self.keycontrolActive = ko.observable(false);
// self.keycontrolHelpActive = ko.observable(false);
// self.keycontrolPossible = ko.computed(function() {
// return self.isOperational() && !self.isPrinting() && self.loginState.isUser() && !$.browser.mobile;
// });
// self.showKeycontrols = ko.computed(function() {
// return self.keycontrolActive() && self.keycontrolPossible();
// });
//
// self.settings.printerProfiles.currentProfileData.subscribe(function() {
// self._updateExtruderCount();
// self.settings.printerProfiles.currentProfileData().extruder.count.subscribe(self._updateExtruderCount);
// });
// self._updateExtruderCount = function() {
// var tools = [];
//
// var numExtruders = self.settings.printerProfiles.currentProfileData().extruder.count();
// if (numExtruders > 1) {
// // multiple extruders
// for (var extruder = 0; extruder < numExtruders; extruder++) {
// tools[extruder] = self._createToolEntry();
// tools[extruder]["name"](gettext("Tool") + " " + extruder);
// tools[extruder]["key"]("tool" + extruder);
//=======
$(function() {
function ControlViewModel(parameters) {
var self = this;
@ -62,32 +10,10 @@ $(function() {
return {
name: ko.observable(),
key: ko.observable()
//>>>>>>> upstream/maintenance
}
};
//<<<<<<< HEAD
// self.tools(tools);
// };
//
// self.fromCurrentData = function(data) {
// self._processStateData(data.state);
// };
//
// self.fromHistoryData = function(data) {
// self._processStateData(data.state);
// };
//
// self._processStateData = function(data) {
// self.isErrorOrClosed(data.flags.closedOrError);
// self.isOperational(data.flags.operational);
// self.isLocked(data.flags.locked);
// self.isPaused(data.flags.paused);
// self.isPrinting(data.flags.printing);
// self.isError(data.flags.error);
// self.isReady(data.flags.ready);
// self.isLoading(data.flags.loading);
// };
//
// self.fromFeedbackCommandData = function(data) {
// if (data.name in self.feedbackControlLookup) {
@ -95,14 +21,7 @@ $(function() {
// }
// };
//
// self.requestData = function() {
// $.ajax({
// url: API_BASEURL + "printer/command/custom",
// method: "GET",
// dataType: "json",
// success: function(response) {
// self._fromResponse(response);
// }
//=======
self.isErrorOrClosed = ko.observable(undefined);
self.isOperational = ko.observable(undefined);
@ -135,7 +54,6 @@ $(function() {
});
self.showKeycontrols = ko.computed(function () {
return self.keycontrolActive() && self.keycontrolPossible();
//>>>>>>> upstream/maintenance
});
self.settings.printerProfiles.currentProfileData.subscribe(function () {
@ -195,6 +113,7 @@ $(function() {
}
});
}
};
//<<<<<<< HEAD
// } else if (control.type == "feedback_command" || control.type == "feedback") {
// control.output = ko.observable("");
@ -209,22 +128,15 @@ $(function() {
//
//
// self.sendJogCommand = function(axis, multiplier, distance) {
// if (typeof distance === "undefined")
// distance = self.jogDistanceInMM();
// if (self.settings.printerProfiles.currentProfileData() && self.settings.printerProfiles.currentProfileData()["axes"] && self.settings.printerProfiles.currentProfileData()["axes"][axis] && self.settings.printerProfiles.currentProfileData()["axes"][axis]["inverted"]()) {
// multiplier *= -1;
// }
//=======
};
//>>>>>>> upstream/maintenance
self.rerenderControls = function () {
var allControls = self.controlsFromServer.concat(self.additionalControls);
self.controls(self._processControls(allControls))
};
self.requestData = function () {
self.requestData = function () {
$.ajax({
url: API_BASEURL + "printer/command/custom",
method: "GET",
@ -361,21 +273,10 @@ $(function() {
}
};
//<<<<<<< HEAD
// $.ajax({
// url: API_BASEURL + "printer/tool",
// type: "POST",
// dataType: "json",
// contentType: "application/json; charset=UTF-8",
// data: JSON.stringify(data)
// });
// };
//
//=======
self.sendJogCommand = function (axis, multiplier, distance) {
if (typeof distance === "undefined")
distance = $('#jog_distance button.active').data('distance');
// distance = $('#jog_distance button.active').data('distance');
distance = self.jogDistanceInMM();
if (self.settings.printerProfiles.currentProfileData() && self.settings.printerProfiles.currentProfileData()["axes"] && self.settings.printerProfiles.currentProfileData()["axes"][axis] && self.settings.printerProfiles.currentProfileData()["axes"][axis]["inverted"]()) {
multiplier *= -1;
}
@ -405,7 +306,6 @@ $(function() {
self.sendExtrudeCommand = function () {
self._sendECommand(1);
};
//>>>>>>> upstream/maintenance
self.sendRetractCommand = function () {
self._sendECommand(-1);
@ -495,7 +395,7 @@ $(function() {
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data)
})
});
};
self.displayMode = function (customControl) {
@ -524,9 +424,10 @@ $(function() {
self.onStartup = function () {
self.requestData();
self._configureJogDistanceSlider();
};
self.updateRotatorWidth = function() {
self.updateRotatorWidth = function() {
var webcamImage = $("#webcam_image");
if (self.settings.webcam_rotate90()) {
if (webcamImage.width() > 0) {
@ -585,155 +486,36 @@ $(function() {
self.rerenderControls();
}
};
self._jogDistanceMapping = [0.1, 1, 5, 10, 50, 100];
self._configureJogDistanceSlider = function () {
self.layerSlider = $("#jogDistance").slider({
id: "jogDistanceSlider",
reversed: false,
selection: "after",
orientation: "horizontal",
min: 0,
max: self._jogDistanceMapping.length - 1,
step: 1,
value: 3,
enabled: true,
formatter: function (value) {
return self._jogDistanceMapping[value] + "mm";
}
}).on("slide", self.updateJogDistance);
self.updateJogDistance();
};
self.updateJogDistance = function () {
var val = self._jogDistanceMapping[$("#jogDistance").slider('getValue')];
self.jogDistanceInMM(val);
};
//<<<<<<< HEAD
// };
//
// self.displayMode = function(customControl) {
// switch (customControl.type) {
// case "section":
// return "customControls_sectionTemplate";
// case "command":
// case "commands":
// return "customControls_commandTemplate";
// case "parametric_command":
// case "parametric_commands":
// return "customControls_parametricCommandTemplate";
// case "feedback_command":
// return "customControls_feedbackCommandTemplate";
// case "feedback":
// return "customControls_feedbackTemplate";
// default:
// return "customControls_emptyTemplate";
// }
// };
//
// self.onStartup = function() {
// self.requestData();
// self._configureJogDistanceSlider();
// };
//
// self._jogDistanceMapping = [0.1, 1, 5, 10, 50, 100];
// self._configureJogDistanceSlider = function() {
// self.layerSlider = $("#jogDistance").slider({
// id: "jogDistanceSlider",
// reversed: false,
// selection: "after",
// orientation: "horizontal",
// min: 0,
// max: self._jogDistanceMapping.length-1,
// step: 1,
// value: 3,
// enabled: true,
// formatter: function(value) { return self._jogDistanceMapping[value] +"mm"; }
// }).on("slide", self.updateJogDistance);
// self.updateJogDistance();
//
// };
//
// self.updateJogDistance = function(){
// var val = self._jogDistanceMapping[$("#jogDistance").slider('getValue')];
// self.jogDistanceInMM(val);
// };
//
//
//
// self.onFocus = function(data, event) {
// if (!self.settings.feature_keyboardControl()) return;
// self.keycontrolActive(true);
// };
//
// self.onMouseOver = function(data, event) {
// if (!self.settings.feature_keyboardControl()) return;
// $("#webcam_container").focus();
// self.keycontrolActive(true);
// };
//
// self.onMouseOut = function(data, event) {
// if (!self.settings.feature_keyboardControl()) return;
// $("#webcam_container").blur();
// self.keycontrolActive(false);
// };
//
// self.toggleKeycontrolHelp = function() {
// self.keycontrolHelpActive(!self.keycontrolHelpActive());
// };
//
// self.onKeyDown = function(data, event) {
// if (!self.settings.feature_keyboardControl()) return;
//
// var button = undefined;
// var visualizeClick = true;
//
// switch(event.which) {
// case 37: // left arrow key
// // X-
// button = $("#control-xdec");
// break;
// case 38: // up arrow key
// // Y+
// button = $("#control-yinc");
// break;
// case 39: // right arrow key
// // X+
// button = $("#control-xinc");
// break;
// case 40: // down arrow key
// // Y-
// button = $("#control-ydec");
// break;
// case 49: // number 1
// case 97: // numpad 1
// // Distance 0.1
// button = $("#control-distance01");
// visualizeClick = false;
// break;
// case 50: // number 2
// case 98: // numpad 2
// // Distance 1
// button = $("#control-distance1");
// visualizeClick = false;
// break;
// case 51: // number 3
// case 99: // numpad 3
// // Distance 10
// button = $("#control-distance10");
// visualizeClick = false;
// break;
// case 52: // number 4
// case 100: // numpad 4
// // Distance 100
// button = $("#control-distance100");
// visualizeClick = false;
// break;
// case 33: // page up key
// case 87: // w key
// // z lift up
// button = $("#control-zinc");
// break;
// case 34: // page down key
// case 83: // s key
// // z lift down
// button = $("#control-zdec");
// break;
// case 36: // home key
// // xy home
// button = $("#control-xyhome");
// break;
// case 35: // end key
// // z home
// button = $("#control-zhome");
// break;
// default:
// event.preventDefault();
// return false;
// }
//=======
self.onFocus = function (data, event) {
if (!self.settings.feature_keyboardControl()) return;
self.keycontrolActive(true);
};
//>>>>>>> upstream/maintenance
self.onMouseOver = function (data, event) {
if (!self.settings.feature_keyboardControl()) return;
@ -756,7 +538,6 @@ $(function() {
var button = undefined;
var visualizeClick = true;
switch (event.which) {
case 37: // left arrow key
// X-
@ -857,7 +638,7 @@ $(function() {
function (e) {
e.preventDefault();
$("#confirmation_dialog").modal("hide");
self.sendCustomCommand({type: 'commands', commands: ['M8', 'M3S7']});
self.sendCustomCommand({type: 'commands', commands: ['M8', 'M3S10']});
setTimeout(function () { // switch focus off after 30 seconds for safety reasons.
self.focus_off();
}, 30000);
@ -866,7 +647,7 @@ $(function() {
};
self.focus_off = function () {
// self.sendCustomCommand({type:'command',command:'M5'});
// self.sendCustomCommand({type:'command',command:'M5'});
self.sendCustomCommand({type: 'commands', commands: ['M5', 'M9']});
};

View file

@ -128,7 +128,6 @@ $(function() {
};
self._processStateData = function(data) {
var prevPaused = self.isPaused();
self.stateString(gettext(data.text));
self.isErrorOrClosed(data.flags.closedOrError);
self.isOperational(data.flags.operational);

View file

@ -119,7 +119,7 @@
</div>
</div>
<div class="accordion-body collapse in" id="connection_wrapper" data-bind="visible: (isErrorOrClosed()) && loginState.isUser()">
<div class="accordion-body in" id="connection_wrapper" data-bind="visible: (isErrorOrClosed()) && loginState.isUser()">
<div class="accordion-inner">
<label for="connection_ports" data-bind="css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed() && loginState.isUser()">{{ _('Serial Port') }}</label>
<select id="connection_ports" data-bind="options: portOptions, optionsCaption: 'AUTO', value: selectedPort, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed() && loginState.isUser()"></select>

View file

@ -720,69 +720,6 @@ class MachineCom(object):
##~~ Error handling
line = self._handleErrors(line)
##~~ 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 not "End file list" in line:
preprocessed_line = line.strip().lower()
fileinfo = preprocessed_line.rsplit(None, 1)
if len(fileinfo) > 1:
# we might have extended file information here, so let's split filename and size and try to make them a bit nicer
filename, size = fileinfo
try:
size = int(size)
except ValueError:
# whatever that was, it was not an integer, so we'll just use the whole line as filename and set size to None
filename = preprocessed_line
size = None
else:
# no extended file information, so only the filename is there and we set size to None
filename = preprocessed_line
size = None
if valid_file_type(filename, "gcode"):
if filter_non_ascii(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, size))
continue
##~~ Temperature processing
if ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:'):
self._processTemperatures(line)
self._callback.on_comm_temperature_update(self._temp, self._bedTemp)
#If we are waiting for an M109 or M190 then measure the time we lost during heatup, so we can remove that time from our printing time estimate.
if 'ok' in line and self._heatupWaitStartTime:
self._heatupWaitTimeLost = self._heatupWaitTimeLost + (time.time() - self._heatupWaitStartTime)
self._heatupWaitStartTime = None
elif supportRepetierTargetTemp and ('TargetExtr' in line or 'TargetBed' in line):
matchExtr = self._regex_repetierTempExtr.match(line)
matchBed = self._regex_repetierTempBed.match(line)
if matchExtr is not None:
toolNum = int(matchExtr.group(1))
try:
target = float(matchExtr.group(2))
if toolNum in self._temp.keys() and self._temp[toolNum] is not None and isinstance(self._temp[toolNum], tuple):
(actual, oldTarget) = self._temp[toolNum]
self._temp[toolNum] = (actual, target)
else:
self._temp[toolNum] = (None, target)
self._callback.on_comm_temperature_update(self._temp, self._bedTemp)
except ValueError:
pass
elif matchBed is not None:
try:
target = float(matchBed.group(1))
if self._bedTemp is not None and isinstance(self._bedTemp, tuple):
(actual, oldTarget) = self._bedTemp
self._bedTemp = (actual, target)
else:
self._bedTemp = (None, target)
self._callback.on_comm_temperature_update(self._temp, self._bedTemp)
except ValueError:
pass
# GRBL Position update
if self._grbl :
if 'MPos:' in line:
@ -819,16 +756,21 @@ class MachineCom(object):
errorMsg = "Machine Limit Hit. Please reset the machine and do a homing cycle"
self._log(errorMsg)
self._errorValue = errorMsg
self._changeState(self.STATE_ERROR)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
self.close()
eventManager().fire(Events.LIMITS_HIT, {"error": self.getErrorString()})
self._openSerial()
self._changeState(self.STATE_CONNECTING)
if("Invalid gcode" in line and self._state == self.STATE_PRINTING):
# TODO Pause machine instead of resetting it.
errorMsg = line
self._log(errorMsg)
self._errorValue = errorMsg
self._changeState(self.STATE_ERROR)
# self._changeState(self.STATE_ERROR)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
self._openSerial()
self._changeState(self.STATE_CONNECTING)
if("Grbl" in line and self._state == self.STATE_PRINTING):
errorMsg = "Machine reset."
@ -837,62 +779,6 @@ class MachineCom(object):
self._changeState(self.STATE_LOCKED)
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
##~~ SD Card handling
elif 'SD init fail' in line or 'volume.init failed' in line or 'openRoot failed' in line:
self._sdAvailable = False
self._sdFiles = []
self._callback.on_comm_sd_state_change(self._sdAvailable)
elif 'Not SD printing' in line:
if self.isSdFileSelected() and self.isPrinting():
# something went wrong, printer is reporting that we actually are not printing right now...
self._sdFilePos = 0
self._changeState(self.STATE_OPERATIONAL)
elif 'SD card ok' in line and not self._sdAvailable:
self._sdAvailable = True
self.refreshSdFiles()
self._callback.on_comm_sd_state_change(self._sdAvailable)
elif 'Begin file list' in line:
self._sdFiles = []
self._sdFileList = True
elif 'End file list' in line:
self._sdFileList = False
self._callback.on_comm_sd_files(self._sdFiles)
elif 'SD printing byte' in line:
# answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
match = self._regex_sdPrintingByte.search(line)
self._currentFile.setFilepos(int(match.group(1)))
self._callback.on_comm_progress()
elif 'File opened' in line:
# answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
match = self._regex_sdFileOpened.search(line)
self._currentFile = PrintingSdFileInformation(match.group(1), int(match.group(2)))
elif 'File selected' in line:
# final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
if self._currentFile is not None:
self._callback.on_comm_file_selected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True)
eventManager().fire(Events.FILE_SELECTED, {
"file": self._currentFile.getFilename(),
"origin": self._currentFile.getFileLocation()
})
elif 'Writing to file' in line:
# anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
self._printSection = "CUSTOM"
self._changeState(self.STATE_PRINTING)
line = "ok"
elif 'Done printing file' in line:
# printer is reporting file finished printing
self._sdFilePos = 0
self._callback.on_comm_print_job_done()
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": self.getPrintTime()
})
elif 'Done saving file' in line:
self.refreshSdFiles()
##~~ Message handling
elif line.strip() != '' \
and line.strip() != 'ok' and not line.startswith("wait") \
@ -1175,7 +1061,8 @@ class MachineCom(object):
ret = self._serial.readline()
if('ok' in ret or 'error' in ret):
self.gcode_line_counter += 1 # Iterate g-code counter
del self.line_lengths[0] # Delete the commands character count corresponding to the last 'ok'
if(len(self.line_lengths) > 0):
del self.line_lengths[0] # Delete the commands character count corresponding to the last 'ok'
except:
self._log("Unexpected error while reading serial port: %s" % (get_exception_string()))
self._errorValue = get_exception_string()