parent
8c038a6829
commit
ee7a1f9615
119
README.md
119
README.md
|
@ -12,7 +12,6 @@ allows
|
|||
* while printing, gaining information regarding the current progress of the print job (height, percentage etc)
|
||||
* reading the communication log and send arbitrary codes to be executed by the printer
|
||||
* moving the X, Y and Z axis (jog controls, although very ugly ones right now)
|
||||
* changing the speed modifiers for inner & outer wall, fill and support
|
||||
* optional: visual monitoring of the printer via webcam stream integrated into the UI (using e.g. MJPG-Streamer)
|
||||
* optional: creation of timelapse recordings of the printjob via webcam stream (using e.g. MJPG-Streamer) -- currently two timelaspe methods are implemented, triggering a shot on z-layer change or every "n" seconds
|
||||
|
||||
|
@ -66,50 +65,81 @@ on Linux, at `%APPDATA%/OctoPrint` on Windows and at `~/Library/Application Supp
|
|||
|
||||
The following example config should explain the available options:
|
||||
|
||||
[serial]
|
||||
# Use the following option to define the default serial port, defaults to unset (= AUTO)
|
||||
port = /dev/ttyACM0
|
||||
# Use the following settings to configure the serial connection to the printer
|
||||
serial:
|
||||
# Use the following option to define the default serial port, defaults to unset (= AUTO)
|
||||
port: /dev/ttyACM0
|
||||
|
||||
# Use the following option to define the default baudrate, defaults to unset (= AUTO)
|
||||
baudrate = 115200
|
||||
# Use the following option to define the default baudrate, defaults to unset (= AUTO)
|
||||
baudrate: 115200
|
||||
|
||||
[server]
|
||||
# Use this option to define the host to which to bind the server, defaults to "0.0.0.0" (= all interfaces)
|
||||
host = 0.0.0.0
|
||||
# Use the following settings to configure the web server
|
||||
server:
|
||||
# Use this option to define the host to which to bind the server, defaults to "0.0.0.0" (= all interfaces)
|
||||
host: 0.0.0.0
|
||||
|
||||
# Use this option to define the port to which to bind the server, defaults to 5000
|
||||
port = 5000
|
||||
# Use this option to define the port to which to bind the server, defaults to 5000
|
||||
port: 5000
|
||||
|
||||
[webcam]
|
||||
# Use this option to enable display of a webcam stream in the UI, e.g. via MJPG-Streamer.
|
||||
# Webcam support will be disabled if not set
|
||||
stream = http://<stream host>:<stream port>/?action=stream
|
||||
# Use the following settings to configure webcam support
|
||||
webcam:
|
||||
# Use this option to enable display of a webcam stream in the UI, e.g. via MJPG-Streamer.
|
||||
# Webcam support will be disabled if not set
|
||||
stream: http://<stream host>:<stream port>/?action=stream
|
||||
|
||||
# Use this option to enable timelapse support via snapshot, e.g. via MJPG-Streamer.
|
||||
# Timelapse support will be disabled if not set
|
||||
snapshot = http://<stream host>:<stream port>/?action=snapshot
|
||||
# Use this option to enable timelapse support via snapshot, e.g. via MJPG-Streamer.
|
||||
# Timelapse support will be disabled if not set
|
||||
snapshot: http://<stream host>:<stream port>/?action=snapshot
|
||||
|
||||
# Path to ffmpeg binary to use for creating timelapse recordings.
|
||||
# Timelapse support will be disabled if not set
|
||||
ffmpeg = /path/to/ffmpeg
|
||||
# Path to ffmpeg binary to use for creating timelapse recordings.
|
||||
# Timelapse support will be disabled if not set
|
||||
ffmpeg: /path/to/ffmpeg
|
||||
|
||||
[feature]
|
||||
# Whether to enable gcode analysis for displaying needed filament and estimated print time. Disabling this (set
|
||||
# to False) will speed up the loading of gcode files before printing significantly, but the mentioned statistical
|
||||
# data will not be available
|
||||
analyzeGcode = True
|
||||
# Use the following settings to enable or disable OctoPrint features
|
||||
feature:
|
||||
# Whether to enable gcode analysis for displaying needed filament and estimated print time. Disabling this (set
|
||||
# to false) will speed up the loading of gcode files before printing significantly, but the mentioned statistical
|
||||
# data will not be available
|
||||
analyzeGcode: true
|
||||
|
||||
[folder]
|
||||
# Absolute path where to store gcode uploads. Defaults to the uploads folder in the OctoPrint settings folder
|
||||
uploads = /path/to/upload/folder
|
||||
# Use the following settings to set custom paths for folders used by OctoPrint
|
||||
folder:
|
||||
# Absolute path where to store gcode uploads. Defaults to the uploads folder in the OctoPrint settings folder
|
||||
uploads: /path/to/upload/folder
|
||||
|
||||
# Absolute path where to store finished timelapse recordings. Defaults to the timelapse folder in the OctoPrint
|
||||
# settings dir
|
||||
timelapse = /path/to/timelapse/folder
|
||||
# Absolute path where to store finished timelapse recordings. Defaults to the timelapse folder in the OctoPrint
|
||||
# settings dir
|
||||
timelapse: /path/to/timelapse/folder
|
||||
|
||||
# Absolute path where to store temporary timelapse files. Defaults to the timelapse/tmp folder in the OctoPrint
|
||||
# settings dir
|
||||
timelapse_tmp: /path/timelapse/tmp/folder
|
||||
|
||||
# Use the following settings to add custom controls to the "Controls" tab within OctoPrint
|
||||
#
|
||||
# Controls consist at least of a name, a type and type-specific further attributes. Currently recognized types are
|
||||
# - section: Creates a visual section in the UI, you can use this to separate functional blocks
|
||||
# - command: Creates a button that sends a defined GCODE command to the printer when clicked
|
||||
# - parametrized_command: Creates a button that sends a parametrized GCODE command to the printer, parameters
|
||||
# needed for the command are added to the UI as input fields and are named
|
||||
#
|
||||
# The following example defines a control for enabling the cooling fan with a variable speed defined by the user
|
||||
# (default 255) and a control for disabling the fan, all within a section named "Fan".
|
||||
controls:
|
||||
- name: Fan
|
||||
type: section
|
||||
children:
|
||||
- name: Enable Fan
|
||||
type: parametrized_command
|
||||
command: M106 S%(speed)s
|
||||
input:
|
||||
- name: Speed (0-255)
|
||||
parameter: speed
|
||||
default: 255
|
||||
- name: Disable Fan
|
||||
type: command
|
||||
command: M107
|
||||
|
||||
# Absolute path where to store temporary timelapse files. Defaults to the timelapse/tmp folder in the OctoPrint
|
||||
# settings dir
|
||||
timelapse_tmp = /path/timelapse/tmp/folder
|
||||
|
||||
Setup on a Raspberry Pi running Raspbian
|
||||
----------------------------------------
|
||||
|
@ -158,10 +188,10 @@ This should hopefully run through without any compilation errors. You should the
|
|||
If you now point your browser to `http://<your Raspi's IP>:8080/?action=stream`, you should see a moving picture at 5fps.
|
||||
Open `~/.octoprint/config.ini` and add the following lines to it:
|
||||
|
||||
[webcam]
|
||||
stream = http://<your Raspi's IP>:8080/?action=stream
|
||||
snapshot = http://127.0.0.1:8080/?action=snapshot
|
||||
ffmpeg = /usr/bin/avconv
|
||||
webcam:
|
||||
stream: http://<your Raspi's IP>:8080/?action=stream
|
||||
snapshot: http://127.0.0.1:8080/?action=snapshot
|
||||
ffmpeg: /usr/bin/avconv
|
||||
|
||||
Restart the OctoPrint server and reload its frontend. You should now see a Webcam tab with content.
|
||||
|
||||
|
@ -179,6 +209,7 @@ It also uses the following libraries and frameworks for backend and frontend:
|
|||
* Flask: http://flask.pocoo.org/
|
||||
* Tornado: http://www.tornadoweb.org/
|
||||
* Tornadio2: https://github.com/MrJoes/tornadio2
|
||||
* PyYAML: http://pyyaml.org/
|
||||
* Socket.io: http://socket.io/
|
||||
* jQuery: http://jquery.com/
|
||||
* Bootstrap: http://twitter.github.com/bootstrap/
|
||||
|
@ -201,14 +232,14 @@ What do I have to do after the rename from Printer WebUI to OctoPrint?
|
|||
----------------------------------------------------------------------
|
||||
|
||||
If you did checkout OctoPrint from its previous location at https://github.com/foosel/PrinterWebUI.git, you'll have to
|
||||
update your so-called remote references in git in order to make 'git pull' use the new repository location as origin.
|
||||
update your so-called remote references in git in order to make `git pull` use the new repository location as origin.
|
||||
|
||||
To do so you'll only need to execute the following command in your OctoPrint/PrinterWebUI folder:
|
||||
|
||||
git remote set-url origin https://github.com/foosel/OctoPrint.git
|
||||
|
||||
After that you might also want to rename your base directory (which probably still is called 'PrinterWebUI') to 'OctoPrint'
|
||||
and delete the folder 'printer_webui' in your base folder (which stays there thanks to Python's compiled bytecode files
|
||||
even after a rename of the Python package to 'octoprint').
|
||||
After that you might also want to rename your base directory (which probably still is called `PrinterWebUI`) to `OctoPrint`
|
||||
and delete the folder `printer_webui` in your base folder (which stays there thanks to Python's compiled bytecode files
|
||||
even after a rename of the Python package to `octoprint`).
|
||||
|
||||
After that you are set, the configuration files are migrated automatically :)
|
||||
After that you are set, the configuration files are migrated automatically.
|
|
@ -120,6 +120,19 @@ def disconnect():
|
|||
@app.route(BASEURL + "control/command", methods=["POST"])
|
||||
def printerCommand():
|
||||
command = request.form["command"]
|
||||
|
||||
# if parameters for the command are given, retrieve them from the request and format the command string with them
|
||||
parameters = {}
|
||||
for requestParameter in request.values.keys():
|
||||
if not requestParameter.startswith("parameter_"):
|
||||
continue
|
||||
|
||||
parameterName = requestParameter[len("parameter_"):]
|
||||
parameterValue = request.values[requestParameter]
|
||||
parameters[parameterName] = parameterValue
|
||||
if len(parameters) > 0:
|
||||
command = command % parameters
|
||||
|
||||
printer.command(command)
|
||||
return jsonify(SUCCESS)
|
||||
|
||||
|
@ -182,6 +195,10 @@ def jog():
|
|||
|
||||
return jsonify(SUCCESS)
|
||||
|
||||
@app.route(BASEURL + "control/speed", methods=["GET"])
|
||||
def getSpeedValues():
|
||||
return jsonify(feedrate = printer.feedrateState())
|
||||
|
||||
@app.route(BASEURL + "control/speed", methods=["POST"])
|
||||
def speed():
|
||||
if not printer.isOperational():
|
||||
|
@ -192,12 +209,11 @@ def speed():
|
|||
value = int(request.values[key])
|
||||
printer.setFeedrateModifier(key, value)
|
||||
|
||||
return jsonify(feedrate = printer.feedrateState())
|
||||
return getSpeedValues()
|
||||
|
||||
@app.route(BASEURL + "control/custom", methods=["GET"])
|
||||
def getCustomControls():
|
||||
customControls = settings().getObject("controls")
|
||||
print("custom controls: %r" % customControls)
|
||||
return jsonify(controls = customControls)
|
||||
|
||||
#~~ GCODE file handling
|
||||
|
|
|
@ -45,46 +45,7 @@ old_default_settings = {
|
|||
|
||||
default_settings = old_default_settings.copy()
|
||||
default_settings.update({
|
||||
"controls": [
|
||||
{
|
||||
"name": "Motors",
|
||||
"type": "section",
|
||||
"children": [
|
||||
{
|
||||
"name": "Enable Motors",
|
||||
"type": "command",
|
||||
"command": "M17"
|
||||
},
|
||||
{
|
||||
"name": "Disable Motors",
|
||||
"type": "command",
|
||||
"command": "M18"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Fan",
|
||||
"type": "section",
|
||||
"children": [
|
||||
{
|
||||
"name": "Enable Fan",
|
||||
"type": "parameterized_command",
|
||||
"command": "M106 S%(speed)",
|
||||
"input": [{
|
||||
"name": "Speed (0-255)",
|
||||
"parameter": "speed",
|
||||
"type": "integer",
|
||||
"range": [0, 255]
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Disable Fan",
|
||||
"type": "command",
|
||||
"command": "M107"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"controls": []
|
||||
})
|
||||
|
||||
class Settings(object):
|
||||
|
@ -128,7 +89,7 @@ class Settings(object):
|
|||
self._config[section][option] = config.get(section, option)
|
||||
self._dirty = True
|
||||
self.save(force=True)
|
||||
#os.rename(oldFilename, oldFilename + ".bck")
|
||||
os.rename(oldFilename, oldFilename + ".bck")
|
||||
else:
|
||||
self._config = {}
|
||||
|
||||
|
@ -195,7 +156,7 @@ class Settings(object):
|
|||
|
||||
def set(self, section, key, value):
|
||||
if section not in default_settings.keys():
|
||||
return None
|
||||
return
|
||||
|
||||
if self._config.has_key(section):
|
||||
sectionConfig = self._config[section]
|
||||
|
@ -204,6 +165,14 @@ class Settings(object):
|
|||
|
||||
sectionConfig[key] = value
|
||||
self._config[section] = sectionConfig
|
||||
self._dirty = True
|
||||
|
||||
def setObject(self, key, value):
|
||||
if key not in default_settings.keys():
|
||||
return
|
||||
|
||||
self._config[key] = value
|
||||
self._dirty = True
|
||||
|
||||
def _resolveSettingsDir(applicationName):
|
||||
# taken from http://stackoverflow.com/questions/1084697/how-do-i-store-desktop-application-data-in-a-cross-platform-way-for-python
|
||||
|
|
|
@ -387,16 +387,66 @@ function ControlsViewModel() {
|
|||
}
|
||||
|
||||
self._fromResponse = function(response) {
|
||||
self.controls(response.controls);
|
||||
self.controls(self._enhanceControls(response.controls));
|
||||
}
|
||||
|
||||
self._enhanceControls = function(controls) {
|
||||
for (var i = 0; i < controls.length; i++) {
|
||||
controls[i] = self._enhanceControl(controls[i]);
|
||||
}
|
||||
return controls;
|
||||
}
|
||||
|
||||
self._enhanceControl = function(control) {
|
||||
if (control.type == "parametrized_command") {
|
||||
for (var i = 0; i < control.input.length; i++) {
|
||||
control.input[i].value = control.input[i].default;
|
||||
}
|
||||
} else if (control.type == "section") {
|
||||
control.children = self._enhanceControls(control.children);
|
||||
}
|
||||
return control;
|
||||
}
|
||||
|
||||
self.sendJogCommand = function(axis, distance) {
|
||||
$.ajax({
|
||||
url: AJAX_BASEURL + "control/jog",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: axis + "=" + distance
|
||||
})
|
||||
}
|
||||
|
||||
self.sendHomeCommand = function(axis) {
|
||||
$.ajax({
|
||||
url: AJAX_BASEURL + "control/jog",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: "home" + axis
|
||||
})
|
||||
}
|
||||
|
||||
self.sendCustomCommand = function(command) {
|
||||
if (command) {
|
||||
if (!command)
|
||||
return;
|
||||
|
||||
if (command.type == "command") {
|
||||
$.ajax({
|
||||
url: AJAX_BASEURL + "control/command",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: "command=" + command
|
||||
data: "command=" + command.command
|
||||
})
|
||||
} else if (command.type="parametrized_command") {
|
||||
var data = {"command": command.command};
|
||||
for (var i = 0; i < command.input.length; i++) {
|
||||
data["parameter_" + command.input[i].parameter] = command.input[i].value;
|
||||
}
|
||||
$.ajax({
|
||||
url: AJAX_BASEURL + "control/command",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -406,8 +456,9 @@ function ControlsViewModel() {
|
|||
case "section":
|
||||
return "customControls_sectionTemplate";
|
||||
case "command":
|
||||
case "parameterized_command":
|
||||
return "customControls_commandTemplate";
|
||||
case "parametrized_command":
|
||||
return "customControls_parametrizedCommandTemplate";
|
||||
default:
|
||||
return "customControls_emptyTemplate";
|
||||
}
|
||||
|
@ -449,19 +500,28 @@ function SpeedViewModel() {
|
|||
self.isLoading(data.flags.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);
|
||||
self.requestData = function() {
|
||||
$.ajax({
|
||||
url: AJAX_BASEURL + "control/speed",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: self._fromResponse
|
||||
});
|
||||
}
|
||||
|
||||
self._fromResponse = function(response) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function TerminalViewModel() {
|
||||
|
@ -667,6 +727,7 @@ function WebcamViewModel() {
|
|||
dataType: "json",
|
||||
success: self.fromResponse
|
||||
});
|
||||
$("#webcam_image").attr("src", CONFIG_WEBCAM_STREAM + "?" + new Date().getTime());
|
||||
}
|
||||
|
||||
self.fromResponse = function(response) {
|
||||
|
@ -847,33 +908,6 @@ $(function() {
|
|||
temperatureViewModel.updatePlot();
|
||||
});
|
||||
|
||||
//~~ Jog controls
|
||||
|
||||
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")});
|
||||
|
||||
//~~ Speed controls
|
||||
|
||||
function speedCommand(structure) {
|
||||
|
@ -932,7 +966,7 @@ $(function() {
|
|||
ko.applyBindings(printerStateViewModel, document.getElementById("state"));
|
||||
ko.applyBindings(gcodeFilesViewModel, document.getElementById("files"));
|
||||
ko.applyBindings(temperatureViewModel, document.getElementById("temp"));
|
||||
ko.applyBindings(controlsViewModel, document.getElementById("jog"));
|
||||
ko.applyBindings(controlsViewModel, document.getElementById("controls"));
|
||||
ko.applyBindings(terminalViewModel, document.getElementById("term"));
|
||||
ko.applyBindings(speedViewModel, document.getElementById("speed"));
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@
|
|||
<link href="{{ url_for('static', filename='css/ui.css') }}" rel="stylesheet" media="screen">
|
||||
|
||||
<script lang="javascript">
|
||||
var AJAX_BASEURL = '/ajax/';
|
||||
var AJAX_BASEURL = "/ajax/";
|
||||
var CONFIG_FILESPERPAGE = 5;
|
||||
var CONFIG_WEBCAM_STREAM = "{{ webcamStream }}";
|
||||
|
||||
var WEB_SOCKET_SWF_LOCATION = "{{ url_for('static', filename='js/WebSocketMain.swf') }}";
|
||||
var WEB_SOCKET_DEBUG = true;
|
||||
|
@ -124,7 +125,7 @@
|
|||
<div class="tabbable span8">
|
||||
<ul class="nav nav-tabs" id="tabs">
|
||||
<li class="active"><a href="#temp" data-toggle="tab">Temperature</a></li>
|
||||
<li><a href="#jog" data-toggle="tab">Controls</a></li>
|
||||
<li><a href="#controls" data-toggle="tab">Controls</a></li>
|
||||
<!--<li><a href="#speed" data-toggle="tab">Speed</a></li>-->
|
||||
<li><a href="#term" data-toggle="tab">Terminal</a></li>
|
||||
{% if webcamStream %}<li><a href="#webcam" data-toggle="tab">Webcam</a></li>{% endif %}
|
||||
|
@ -166,24 +167,24 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="jog">
|
||||
<div class="tab-pane" id="controls">
|
||||
<div style="width: 350px; height: 70px">
|
||||
<div style="width: 70px; float: left;"> </div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" id="jog_y_inc" data-bind="enable: isOperational() && !isPrinting()">Y+</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('y', 10) }">Y+</button></div>
|
||||
<div style="width: 70px; float: left;"> </div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" id="jog_z_inc" data-bind="enable: isOperational() && !isPrinting()">Z+</button></div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('z', 10) }">Z+</button></div>
|
||||
</div>
|
||||
<div style="width: 350px; height: 70px">
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" id="jog_x_dec" data-bind="enable: isOperational() && !isPrinting()">X-</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" id="jog_xy_home" data-bind="enable: isOperational() && !isPrinting()">Home</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" id="jog_x_inc" data-bind="enable: isOperational() && !isPrinting()">X+</button></div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" id="jog_z_home" data-bind="enable: isOperational() && !isPrinting()">Home</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('x', -10) }">X-</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendHomeCommand('XY') }">Home</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('x', 10) }">X+</button></div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" id="jog_z_home" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendHomeCommand('Z') }">Home</button></div>
|
||||
</div>
|
||||
<div style="width: 350px; height: 70px">
|
||||
<div style="width: 70px; float: left;"> </div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" id="jog_y_dec" data-bind="enable: isOperational() && !isPrinting()">Y-</button></div>
|
||||
<div style="width: 70px; float: left;"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('y', -10) }">Y-</button></div>
|
||||
<div style="width: 70px; float: left;"> </div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" id="jog_z_dec" data-bind="enable: isOperational() && !isPrinting()">Z-</button></div>
|
||||
<div style="width: 70px; float: left; margin-left: 20px"><button class="btn btn-block" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('z', -10) }">Z-</button></div>
|
||||
</div>
|
||||
|
||||
<div data-bind="template: { name: $root.displayMode, foreach: controls }"></div>
|
||||
|
@ -195,9 +196,20 @@
|
|||
<div data-bind="template: { name: $root.displayMode, foreach: children }"></div>
|
||||
</script>
|
||||
<script type="text/html" id="customControls_commandTemplate">
|
||||
<button class="btn" data-bind="text: name, enable: $root.isOperational(), click: function() { $root.sendCustomCommand($data.command) }"></button>
|
||||
<form class="form-inline">
|
||||
<button class="btn" data-bind="text: name, enable: $root.isOperational(), click: function() { $root.sendCustomCommand($data) }"></button>
|
||||
</form>
|
||||
</script>
|
||||
<script type="text/html" id="customControls_emptyTemplate"></script>
|
||||
<script type="text/html" id="customControls_parametrizedCommandTemplate">
|
||||
<form class="form-inline">
|
||||
<!-- ko foreach: input -->
|
||||
<label data-bind="text: name"></label>
|
||||
<input type="text" class="input-small" data-bind="attr: {placeholder: name}, value: value">
|
||||
<!-- /ko -->
|
||||
<button class="btn" data-bind="text: name, enable: $root.isOperational(), click: function() { $root.sendCustomCommand($data) }"></button>
|
||||
</form>
|
||||
</script>
|
||||
<script type="text/html" id="customControls_emptyTemplate"><div></div></script>
|
||||
<!-- End of templates for custom controls -->
|
||||
</div>
|
||||
<div class="tab-pane" id="speed">
|
||||
|
|
Loading…
Reference in New Issue