From fc4f2340fe704764115511058731448656cd0756 Mon Sep 17 00:00:00 2001 From: Teja Date: Tue, 7 Jul 2015 18:44:29 +0200 Subject: [PATCH] fixed limit hit warning and reconnect after. --- src/octoprint/events.py | 3 + src/octoprint/static/js/app/dataupdater.js | 9 + .../static/js/app/viewmodels/connection.js | 4 +- .../static/js/app/viewmodels/control.js | 291 +++--------------- .../static/js/app/viewmodels/printerstate.js | 1 - src/octoprint/templates/mrbeam_index.jinja2 | 2 +- src/octoprint/util/comm_acc.py | 133 +------- 7 files changed, 61 insertions(+), 382 deletions(-) diff --git a/src/octoprint/events.py b/src/octoprint/events.py index 82886233..bcd80527 100644 --- a/src/octoprint/events.py +++ b/src/octoprint/events.py @@ -86,6 +86,9 @@ class Events(object): # Settings SETTINGS_UPDATED = "SettingsUpdated" + + # GRBL + LIMITS_HIT = "LimitsHit" def eventManager(): diff --git a/src/octoprint/static/js/app/dataupdater.js b/src/octoprint/static/js/app/dataupdater.js index 8332c6db..63382bbc 100644 --- a/src/octoprint/static/js/app/dataupdater.js +++ b/src/octoprint/static/js/app/dataupdater.js @@ -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.
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 = { diff --git a/src/octoprint/static/js/app/viewmodels/connection.js b/src/octoprint/static/js/app/viewmodels/connection.js index 62ab6622..a9fc1e42 100644 --- a/src/octoprint/static/js/app/viewmodels/connection.js +++ b/src/octoprint/static/js/app/viewmodels/connection.js @@ -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"); } } }; diff --git a/src/octoprint/static/js/app/viewmodels/control.js b/src/octoprint/static/js/app/viewmodels/control.js index 0ff58998..e4bc53a7 100644 --- a/src/octoprint/static/js/app/viewmodels/control.js +++ b/src/octoprint/static/js/app/viewmodels/control.js @@ -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']}); }; diff --git a/src/octoprint/static/js/app/viewmodels/printerstate.js b/src/octoprint/static/js/app/viewmodels/printerstate.js index 1d3d36ce..3af36bb6 100644 --- a/src/octoprint/static/js/app/viewmodels/printerstate.js +++ b/src/octoprint/static/js/app/viewmodels/printerstate.js @@ -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); diff --git a/src/octoprint/templates/mrbeam_index.jinja2 b/src/octoprint/templates/mrbeam_index.jinja2 index 7e8f8d9d..8925ddfe 100644 --- a/src/octoprint/templates/mrbeam_index.jinja2 +++ b/src/octoprint/templates/mrbeam_index.jinja2 @@ -119,7 +119,7 @@ -
+
diff --git a/src/octoprint/util/comm_acc.py b/src/octoprint/util/comm_acc.py index 2fca0e0b..6ce10f79 100644 --- a/src/octoprint/util/comm_acc.py +++ b/src/octoprint/util/comm_acc.py @@ -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()