diff --git a/Cura/util/machineCom.py b/Cura/util/machineCom.py index da268c0..a2298bf 100644 --- a/Cura/util/machineCom.py +++ b/Cura/util/machineCom.py @@ -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]) diff --git a/Cura/webui/__init__.py b/Cura/webui/__init__.py index 4e18197..79a7ba9 100644 --- a/Cura/webui/__init__.py +++ b/Cura/webui/__init__.py @@ -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() diff --git a/Cura/webui/printer.py b/Cura/webui/printer.py index 6d4419f..68964a3 100644 --- a/Cura/webui/printer.py +++ b/Cura/webui/printer.py @@ -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. diff --git a/Cura/webui/static/css/ui.css b/Cura/webui/static/css/ui.css index 09290d6..0eff96e 100644 --- a/Cura/webui/static/css/ui.css +++ b/Cura/webui/static/css/ui.css @@ -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%; } \ No newline at end of file diff --git a/Cura/webui/static/js/ui.js b/Cura/webui/static/js/ui.js index 857a8b4..02f2650 100644 --- a/Cura/webui/static/js/ui.js +++ b/Cura/webui/static/js/ui.js @@ -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({ diff --git a/Cura/webui/templates/index.html b/Cura/webui/templates/index.html index 0823551..d8adf29 100644 --- a/Cura/webui/templates/index.html +++ b/Cura/webui/templates/index.html @@ -175,7 +175,35 @@
- Here be speed settings +
+ +
+ + % + +
+ + +
+ + % + +
+ + +
+ + % + +
+ + +
+ + % + +
+