- Added speed controls

- Bugfix for getConnectionOptions under *nix
master
Gina Häußge 2012-12-29 15:41:23 +01:00
parent cd04fb705f
commit 39b3639d69
6 changed files with 175 additions and 16 deletions

View File

@ -546,6 +546,11 @@ class MachineCom(object):
def setFeedrateModifier(self, type, value):
self._feedRateModifier[type] = value
def getFeedrateModifiers(self):
result = {}
result.update(self._feedRateModifier)
return result
def getExceptionString():
locationInfo = traceback.extract_tb(sys.exc_info()[2])[0]
return "%s: '%s' @ %s:%s:%d" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]), os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])

View File

@ -50,6 +50,7 @@ def printerState():
bedTargetTemp = printer.currentBedTargetTemp
jobData = printer.jobData()
gcodeState = printer.gcodeState()
feedrateState = printer.feedrateState()
result = {
"state": printer.getStateString(),
@ -74,6 +75,9 @@ def printerState():
gcodeState["filename"] = gcodeState["filename"].replace(UPLOAD_FOLDER + os.sep, "")
result["gcode"] = gcodeState
if feedrateState is not None:
result["feedrate"] = feedrateState
if request.values.has_key("temperatures"):
result["temperatures"] = printer.temps
@ -184,6 +188,18 @@ def jog():
return jsonify(SUCCESS)
@app.route(BASEURL + "control/speed", methods=["POST"])
def speed():
if not printer.isOperational():
return jsonify(SUCCESS)
for key in ["outerWall", "innerWall", "fill", "support"]:
if request.values.has_key(key):
value = int(request.values[key])
printer.setFeedrateModifier(key, value)
return jsonify(feedrate = printer.feedrateState())
#~~ GCODE file handling
@app.route(BASEURL + "gcodefiles", methods=["GET"])
@ -194,7 +210,7 @@ def readGcodeFiles():
continue
files.append({
"name": osFile,
"size": sizeof_fmt(os.stat(UPLOAD_FOLDER + os.sep + osFile).st_size)
"size": sizeof_fmt(os.stat(os.path.join(UPLOAD_FOLDER, osFile)).st_size)
})
return jsonify(files=files)
@ -210,7 +226,7 @@ def uploadGcodeFile():
@app.route(BASEURL + "gcodefiles/load", methods=["POST"])
def loadGcodeFile():
filename = request.values["filename"]
printer.loadGcode(UPLOAD_FOLDER + os.sep + filename)
printer.loadGcode(os.path.join(UPLOAD_FOLDER, filename))
return jsonify(SUCCESS)
@app.route(BASEURL + "gcodefiles/delete", methods=["POST"])
@ -218,7 +234,7 @@ def deleteGcodeFile():
if request.values.has_key("filename"):
filename = request.values["filename"]
if allowed_file(filename):
secure = UPLOAD_FOLDER + os.sep + secure_filename(filename)
secure = os.path.join(UPLOAD_FOLDER, secure_filename(filename))
if os.path.exists(secure):
os.remove(secure)
return readGcodeFiles()

View File

@ -13,11 +13,17 @@ def getConnectionOptions():
"""
Retrieves the available ports, baudrates, prefered port and baudrate for connecting to the printer.
"""
baudratePref = None
try:
baudratePref = int(profile.getPreference('serial_baud_auto'))
except ValueError:
pass
return {
"ports": sorted(machineCom.serialList(), key=str.lower),
"baudrates": sorted(machineCom.baudrateList(), key=int, reverse=True),
"ports": machineCom.serialList(),
"baudrates": machineCom.baudrateList(),
"portPreference": profile.getPreference('serial_port_auto'),
"baudratePreference": int(profile.getPreference('serial_baud_auto'))
"baudratePreference": baudratePref
}
class Printer():
@ -47,6 +53,8 @@ class Printer():
self.gcodeLoader = None
self.feedrateModifierMapping = {"outerWall": "WALL-OUTER", "innerWall": "WALL_INNER", "fill": "FILL", "support": "SUPPORT"}
# comm
self.comm = None
@ -80,6 +88,12 @@ class Printer():
for command in commands:
self.comm.sendCommand(command)
def setFeedrateModifier(self, structure, percentage):
if (not self.feedrateModifierMapping.has_key(structure)) or percentage < 0:
return
self.comm.setFeedrateModifier(self.feedrateModifierMapping[structure], percentage / 100.0)
def mcLog(self, message):
"""
Callback method for the comm object, called upon log output.
@ -200,6 +214,19 @@ class Printer():
else:
return None
def feedrateState(self):
if self.comm is not None:
feedrateModifiers = self.comm.getFeedrateModifiers()
result = {}
for structure in self.feedrateModifierMapping.keys():
if (feedrateModifiers.has_key(self.feedrateModifierMapping[structure])):
result[structure] = int(round(feedrateModifiers[self.feedrateModifierMapping[structure]] * 100))
else:
result[structure] = 100
return result
else:
return None
def getStateString(self):
"""
Returns a human readable string corresponding to the current communication state.

View File

@ -48,10 +48,11 @@ table th.gcode_files_action, table td.gcode_files_action {
overflow: hidden;
}
#temp_newTemp {
#temp_newTemp, #temp_newBedTemp, #speed_innerWall, #speed_outerWall, #speed_fill, #speed_support {
text-align: right;
}
#connection_ports, #connection_baudrates {
width: 100%;
}

View File

@ -228,6 +228,46 @@ function TemperatureViewModel() {
}
var temperatureViewModel = new TemperatureViewModel();
function SpeedViewModel() {
var self = this;
self.outerWall = ko.observable(undefined);
self.innerWall = ko.observable(undefined);
self.fill = ko.observable(undefined);
self.support = 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.isLoading = ko.observable(undefined);
self.fromResponse = function(response) {
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.isLoading(response.loading);
if (response.feedrate) {
self.outerWall(response.feedrate.outerWall);
self.innerWall(response.feedrate.innerWall);
self.fill(response.feedrate.fill);
self.support(response.feedrate.support);
} else {
self.outerWall(undefined);
self.innerWall(undefined);
self.fill(undefined);
self.support(undefined);
}
}
}
var speedViewModel = new SpeedViewModel();
function TerminalViewModel() {
var self = this;
@ -293,7 +333,7 @@ function GcodeFilesViewModel() {
}
var gcodeFilesViewModel = new GcodeFilesViewModel();
function DataUpdater(connectionViewModel, printerStateViewModel, temperatureViewModel, terminalViewModel) {
function DataUpdater(connectionViewModel, printerStateViewModel, temperatureViewModel, speedViewModel, terminalViewModel) {
var self = this;
self.updateInterval = 500;
@ -304,6 +344,7 @@ function DataUpdater(connectionViewModel, printerStateViewModel, temperatureView
self.printerStateViewModel = printerStateViewModel;
self.temperatureViewModel = temperatureViewModel;
self.terminalViewModel = terminalViewModel;
self.speedViewModel = speedViewModel;
self.requestData = function() {
var parameters = {};
@ -321,6 +362,7 @@ function DataUpdater(connectionViewModel, printerStateViewModel, temperatureView
success: function(response) {
self.printerStateViewModel.fromResponse(response);
self.connectionViewModel.fromStateResponse(response);
self.speedViewModel.fromResponse(response);
if (response.temperatures)
self.temperatureViewModel.fromResponse(response);
@ -336,9 +378,12 @@ function DataUpdater(connectionViewModel, printerStateViewModel, temperatureView
setTimeout(self.requestData, self.updateInterval);
}
}
var dataUpdater = new DataUpdater(connectionViewModel, printerStateViewModel, temperatureViewModel, terminalViewModel);
var dataUpdater = new DataUpdater(connectionViewModel, printerStateViewModel, temperatureViewModel, speedViewModel, terminalViewModel);
$(function() {
//~~ Print job control
$("#job_print").click(function() {
$.ajax({
url: AJAX_BASEURL + "control/print",
@ -363,6 +408,8 @@ $(function() {
})
})
//~~ Temperature control
$("#temp_newTemp_set").click(function() {
var newTemp = $("#temp_newTemp").val();
$.ajax({
@ -384,6 +431,8 @@ $(function() {
})
})
//~~ Jog controls
function jogCommand(axis, distance) {
$.ajax({
url: AJAX_BASEURL + "control/jog",
@ -409,16 +458,44 @@ $(function() {
$("#jog_xy_home").click(function() {homeCommand("XY")});
$("#jog_z_home").click(function() {homeCommand("Z")});
//~~ Speed controls
function speedCommand(structure) {
var speedSetting = $("#speed_" + structure).val();
if (speedSetting) {
$.ajax({
url: AJAX_BASEURL + "control/speed",
type: "POST",
dataType: "json",
data: structure + "=" + speedSetting,
success: function(response) {
$("#speed_" + structure).val("")
speedViewModel.fromResponse(response);
}
})
}
}
$("#speed_outerWall_set").click(function() {speedCommand("outerWall")});
$("#speed_innerWall_set").click(function() {speedCommand("innerWall")});
$("#speed_support_set").click(function() {speedCommand("support")});
$("#speed_fill_set").click(function() {speedCommand("fill")});
//~~ Terminal
$("#terminal-send").click(function () {
var command = $("#terminal-command").val();
$.ajax({
url: AJAX_BASEURL + "control/command",
type: "POST",
dataType: "json",
data: "command=" + command
})
if (command) {
$.ajax({
url: AJAX_BASEURL + "control/command",
type: "POST",
dataType: "json",
data: "command=" + command
})
}
})
//~~ Gcode upload
$("#gcode_upload").fileupload({
dataType: "json",
done: function (e, data) {
@ -430,12 +507,17 @@ $(function() {
}
});
//~~ knockout.js bindings
ko.applyBindings(connectionViewModel, document.getElementById("connection"));
ko.applyBindings(printerStateViewModel, document.getElementById("state"));
ko.applyBindings(gcodeFilesViewModel, document.getElementById("files"));
ko.applyBindings(temperatureViewModel, document.getElementById("temp"));
ko.applyBindings(printerStateViewModel, document.getElementById("jog"));
ko.applyBindings(terminalViewModel, document.getElementById("term"));
ko.applyBindings(speedViewModel, document.getElementById("speed"));
//~~ startup commands
dataUpdater.requestData();
$.ajax({

View File

@ -175,7 +175,35 @@
</div>
</div>
<div class="tab-pane" id="speed">
Here be speed settings
<div class="form-horizontal" style="margin-bottom: 20px">
<label for="speed_outerWall">Outer Wall</label>
<div class="input-append">
<input type="text" id="speed_outerWall" class="input-mini" data-bind="enable: isOperational(), attr: {placeholder: outerWall}">
<span class="add-on">%</span>
<button type="submit" class="btn" id="speed_outerWall_set" data-bind="enable: isOperational()">Set</button>
</div>
<label for="speed_innerWall">Inner Wall</label>
<div class="input-append">
<input type="text" id="speed_innerWall" class="input-mini" data-bind="enable: isOperational(), attr: {placeholder: innerWall}">
<span class="add-on">%</span>
<button type="submit" class="btn" id="speed_innerWall_set" data-bind="enable: isOperational()">Set</button>
</div>
<label for="speed_fill">Fill</label>
<div class="input-append">
<input type="text" id="speed_fill" class="input-mini" data-bind="enable: isOperational(), attr: {placeholder: fill}">
<span class="add-on">%</span>
<button type="submit" class="btn" id="speed_fill_set" data-bind="enable: isOperational()">Set</button>
</div>
<label for="speed_support">Support</label>
<div class="input-append">
<input type="text" id="speed_support" class="input-mini" data-bind="enable: isOperational(), attr: {placeholder: support}">
<span class="add-on">%</span>
<button type="submit" class="btn" id="speed_support_set" data-bind="enable: isOperational()">Set</button>
</div>
</div>
</div>
<div class="tab-pane" id="term">
<pre id="terminal-output" class="pre-scrollable"></pre>