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 @@