From aa6e8886209acd64047b23d8152414574585bb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Wed, 26 Dec 2012 15:03:34 +0100 Subject: [PATCH] - implemented jog controls - finalized temperature tab - UI and code cleaning --- Cura/webui/__init__.py | 64 +++++++++++-- Cura/webui/printer.py | 28 +++++- Cura/webui/static/js/ui.js | 133 ++++++++++++++++++++++++--- Cura/webui/templates/index.html | 155 +++++++++++++++++--------------- 4 files changed, 286 insertions(+), 94 deletions(-) diff --git a/Cura/webui/__init__.py b/Cura/webui/__init__.py index 2a38251..2114d86 100644 --- a/Cura/webui/__init__.py +++ b/Cura/webui/__init__.py @@ -26,14 +26,22 @@ def index(): def printerState(): temp = printer.currentTemp bedTemp = printer.currentBedTemp + targetTemp = printer.currentTargetTemp + bedTargetTemp = printer.currentBedTargetTemp jobData = printer.jobData() result = { - 'state': printer.getStateString(), - 'temp': temp, - 'bedTemp': bedTemp, - 'operational': printer.isOperational(), - 'closedOrError': printer.isClosedOrError() + 'state': printer.getStateString(), + 'temp': temp, + 'bedTemp': bedTemp, + 'targetTemp': targetTemp, + 'targetBedTemp': bedTargetTemp, + 'operational': printer.isOperational(), + 'closedOrError': printer.isClosedOrError(), + 'error': printer.isError(), + 'printing': printer.isPrinting(), + 'paused': printer.isPaused(), + 'ready': printer.isReady() } if (jobData != None): @@ -95,6 +103,50 @@ def cancelPrint(): printer.cancelPrint() return jsonify(SUCCESS) +@app.route(BASEURL + 'control/temperature', methods=['POST']) +def setTargetTemperature(): + if not printer.isOperational(): + return jsonify(SUCCESS) + + if request.values.has_key("temp"): + # set target temperature + temp = request.values["temp"]; + printer.command("M104 S" + temp) + + if request.values.has_key("bedTemp"): + # set target bed temperature + bedTemp = request.values["bedTemp"] + printer.command("M140 S" + bedTemp) + + return jsonify(SUCCESS) + +@app.route(BASEURL + "control/jog", methods=["POST"]) +def jog(): + if not printer.isOperational() or printer.isPrinting(): + # do not jog when a print job is running or we don't have a connection + return jsonify(SUCCESS) + + if request.values.has_key("x"): + # jog x + x = request.values["x"] + printer.commands(["G91", "G1 X" + x + " F6000", "G90"]) + if request.values.has_key("y"): + # jog y + y = request.values["y"] + printer.commands(["G91", "G1 Y" + y + " F6000", "G90"]) + if request.values.has_key("z"): + # jog z + z = request.values["z"] + printer.commands(["G91", "G1 Z" + z + " F200", "G90"]) + if request.values.has_key("homeXY"): + # home x/y + printer.command("G28 X0 Y0") + if request.values.has_key("homeZ"): + # home z + printer.command("G28 Z0") + + return jsonify(SUCCESS) + #~~ GCODE file handling @app.route(BASEURL + 'gcodefiles', methods=['GET']) @@ -141,4 +193,4 @@ def sizeof_fmt(num): def run(): app.debug = True - app.run() + app.run(host="0.0.0.0") diff --git a/Cura/webui/printer.py b/Cura/webui/printer.py index 457dd39..2111107 100644 --- a/Cura/webui/printer.py +++ b/Cura/webui/printer.py @@ -25,6 +25,8 @@ class Printer(): self.printTimeLeft = None self.currentTemp = None self.currentBedTemp = None + self.currentTargetTemp = None + self.currentBedTargetTemp = None self.gcode = None self.gcodeList = None @@ -36,7 +38,7 @@ class Printer(): def connect(self): if self.comm != None: self.comm.close() - self.comm = machineCom.MachineCom(port='VIRTUAL', callbackObject=self) + self.comm = machineCom.MachineCom(port="COM4", baudrate=115200, callbackObject=self) def disconnect(self): if self.comm != None: @@ -44,14 +46,18 @@ class Printer(): self.comm = None def command(self, command): - self.comm.sendCommand(command) + self.commands([command]) + + def commands(self, commands): + for command in commands: + self.comm.sendCommand(command) def mcLog(self, message): self.log.append(message) self.log = self.log[-300:] def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp): - currentTime = time.time() + currentTime = int(time.time() * 1000) self.temps['actual'].append((currentTime, temp)) self.temps['actual'] = self.temps['actual'][-300:] @@ -66,14 +72,16 @@ class Printer(): self.temps['targetBed'] = self.temps['targetBed'][-300:] self.currentTemp = temp + self.currentTargetTemp = targetTemp self.currentBedTemp = bedTemp + self.currentBedTargetTemp = bedTargetTemp def mcStateChange(self, state): self.state = state def mcMessage(self, message): self.messages.append(message) - self.messages = self.message[-300:] + self.messages = self.messages[-300:] def mcProgress(self, lineNr): self.printTime = self.comm.getPrintTime() @@ -124,6 +132,18 @@ class Printer(): def isOperational(self): return self.comm != None and self.comm.isOperational() + def isPrinting(self): + return self.comm != None and self.comm.isPrinting() + + def isPaused(self): + return self.comm != None and self.comm.isPaused() + + def isError(self): + return self.comm != None and self.comm.isError() + + def isReady(self): + return self.gcodeList and len(self.gcodeList) > 0 + def loadGcode(self, file): if self.comm != None and self.comm.isPrinting(): return diff --git a/Cura/webui/static/js/ui.js b/Cura/webui/static/js/ui.js index 1e1793a..3b93ab1 100644 --- a/Cura/webui/static/js/ui.js +++ b/Cura/webui/static/js/ui.js @@ -4,6 +4,10 @@ function PrinterStateViewModel() { self.stateString = ko.observable(undefined); self.isErrorOrClosed = ko.observable(undefined); self.isOperational = ko.observable(undefined); + self.isPrinting = ko.observable(undefined); + self.isPaused = ko.observable(undefined); + self.isError = ko.observable(undefined); + self.isReady = ko.observable(undefined); self.filament = ko.observable(undefined); self.estimatedPrintTime = ko.observable(undefined); @@ -18,12 +22,18 @@ function PrinterStateViewModel() { return "-"; var currentLine = self.currentLine() ? self.currentLine() : "-"; return currentLine + " / " + self.totalLines(); - }) + }); self.progress = ko.computed(function() { if (!self.currentLine() || !self.totalLines()) return 0; return Math.round(self.currentLine() * 100 / self.totalLines()); }); + self.pauseString = ko.computed(function() { + if (self.isPaused()) + return "Continue"; + else + return "Pause"; + }); self.connect = function() { $.ajax({ @@ -37,6 +47,10 @@ function PrinterStateViewModel() { self.stateString(response.state); self.isErrorOrClosed(response.closedOrError); self.isOperational(response.operational); + self.isPaused(response.paused); + self.isPrinting(response.printing); + self.isError(response.error); + self.isReady(response.ready); if (response.job) { self.filament(response.job.filament); @@ -63,6 +77,35 @@ function TemperatureViewModel() { self.temp = ko.observable(undefined); self.bedTemp = ko.observable(undefined); + self.targetTemp = ko.observable(undefined); + self.bedTargetTemp = ko.observable(undefined); + self.isErrorOrClosed = ko.observable(undefined); + self.isOperational = ko.observable(undefined); + self.isPrinting = ko.observable(undefined); + self.isPaused = ko.observable(undefined); + self.isError = ko.observable(undefined); + self.isReady = ko.observable(undefined); + + self.tempString = ko.computed(function() { + if (!self.temp()) + return "-"; + return self.temp() + " °C"; + }); + self.bedTempString = ko.computed(function() { + if (!self.bedTemp()) + return "-"; + return self.bedTemp() + " °C"; + }); + self.targetTempString = ko.computed(function() { + if (!self.targetTemp()) + return "-"; + return self.targetTemp() + " °C"; + }); + self.bedTargetTempString = ko.computed(function() { + if (!self.bedTargetTemp()) + return "-"; + return self.bedTargetTemp() + " °C"; + }); self.temperatures = []; self.plotOptions = { @@ -72,7 +115,18 @@ function TemperatureViewModel() { ticks: 10 }, xaxis: { - mode: "time" + mode: "time", + timeformat: "%H:%M:%S", + minTickSize: [2, "minute"], + tickFormatter: function(val, axis) { + var now = new Date(); + var diff = now.getTime() - val; + var diffInMins = Math.round(diff / (60000)); + if (diffInMins == 0) + return "just now"; + else + return "- " + diffInMins + " min"; + } }, legend: { noColumns: 4 @@ -80,10 +134,19 @@ function TemperatureViewModel() { } self.fromResponse = function(response) { - self.temp(response.currentTemp); - self.bedTemp(response.currentBedTemp); + self.temp(response.temp); + self.bedTemp(response.bedTemp); + self.targetTemp(response.targetTemp); + self.bedTargetTemp(response.bedTargetTemp); self.temperatures = (response.temperatures); + self.isErrorOrClosed(response.closedOrError); + self.isOperational(response.operational); + self.isPaused(response.paused); + self.isPrinting(response.printing); + self.isError(response.error); + self.isReady(response.ready); + self.updatePlot(); } @@ -113,13 +176,13 @@ function TerminalViewModel() { self.updateOutput = function() { var output = ''; for (var i = 0; i < self.log.length; i++) { - output += self.log[i] + '
'; + output += self.log[i] + '\n'; } var container = $("#terminal-output"); var autoscroll = (container.scrollTop() == container[0].scrollHeight - container.height); - container.html(output); + container.text(output); if (autoscroll) { container.scrollTop(container[0].scrollHeight - container.height()) @@ -215,11 +278,11 @@ $(function() { }) }) $("#job_pause").click(function() { + $("#job_pause").button('toggle'); $.ajax({ url: AJAX_BASEURL + "control/pause", type: 'POST', dataType: 'json', - success: function(){} }) }) $("#job_cancel").click(function() { @@ -227,10 +290,55 @@ $(function() { url: AJAX_BASEURL + "control/cancel", type: 'POST', dataType: 'json', - success: function(){} }) }) + $("#temp_newTemp_set").click(function() { + var newTemp = $("#temp_newTemp").val(); + $.ajax({ + url: AJAX_BASEURL + "control/temperature", + type: "POST", + dataType: "json", + data: { temp: newTemp }, + success: function() {$("#temp_newTemp").val("")} + }) + }) + $("#temp_newBedTemp_set").click(function() { + var newBedTemp = $("#temp_newBedTemp").val(); + $.ajax({ + url: AJAX_BASEURL + "control/temperature", + type: "POST", + dataType: "json", + data: { bedTemp: newBedTemp }, + success: function() {$("#temp_newBedTemp").val("")} + }) + }) + + function jogCommand(axis, distance) { + $.ajax({ + url: AJAX_BASEURL + "control/jog", + type: "POST", + dataType: "json", + data: axis + "=" + distance + }) + } + function homeCommand(axis) { + $.ajax({ + url: AJAX_BASEURL + "control/jog", + type: "POST", + dataType: "json", + data: "home" + axis + }) + } + $("#jog_x_inc").click(function() {jogCommand("x", "10")}); + $("#jog_x_dec").click(function() {jogCommand("x", "-10")}); + $("#jog_y_inc").click(function() {jogCommand("y", "10")}); + $("#jog_y_dec").click(function() {jogCommand("y", "-10")}); + $("#jog_z_inc").click(function() {jogCommand("z", "10")}); + $("#jog_z_dec").click(function() {jogCommand("z", "-10")}); + $("#jog_xy_home").click(function() {homeCommand("XY")}); + $("#jog_z_home").click(function() {homeCommand("Z")}); + $("#terminal-send").click(function () { var command = $("#terminal-command").val(); $.ajax({ @@ -238,9 +346,6 @@ $(function() { type: 'POST', dataType: 'json', data: 'command=' + command, - success: function(response) { - // do nothing - } }) }) @@ -249,7 +354,6 @@ $(function() { done: function (e, data) { gcodeFilesViewModel.fromResponse(data.result); }, - acceptFileTypes: /(\.|\/)gcode$/i, progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); $('#gcode_upload_progress .bar').css( @@ -260,9 +364,10 @@ $(function() { }); ko.applyBindings(printerStateViewModel, document.getElementById("state")); - ko.applyBindings(temperatureViewModel, document.getElementById("temp")); - ko.applyBindings(terminalViewModel, document.getElementById("term")); ko.applyBindings(gcodeFilesViewModel, document.getElementById("files")); + ko.applyBindings(temperatureViewModel, document.getElementById("temp")); + ko.applyBindings(printerStateViewModel, document.getElementById("jog")); + ko.applyBindings(terminalViewModel, document.getElementById("term")); dataUpdater.requestData(); $.ajax({ diff --git a/Cura/webui/templates/index.html b/Cura/webui/templates/index.html index 1beb749..c0501b4 100644 --- a/Cura/webui/templates/index.html +++ b/Cura/webui/templates/index.html @@ -5,6 +5,7 @@ + @@ -19,25 +20,25 @@ -
-
-

Cura WebUI

+