[feature] Parameterized macros (#16)
Adds the option to have parameters in Macros and show a dialog to the user on execution to change them. Here's and example: PID_CALIBRATE HEATER={label:Heater, default:extruder, options:extruder|extruder1} TARGET={label:Temperature, unit:°C, default:190} WRITE_FILE={label:WriteFile, default:0, options:0|1}
This commit is contained in:
parent
33ae991612
commit
769b8a53ed
|
@ -209,6 +209,12 @@ class KlipperPlugin(
|
|||
name="Performance Graph",
|
||||
template="klipper_graph_dialog.jinja2",
|
||||
custom_bindings=True
|
||||
),
|
||||
dict(
|
||||
type="generic",
|
||||
name="Macro Dialog",
|
||||
template="klipper_param_macro_dialog.jinja2",
|
||||
custom_bindings=True
|
||||
)
|
||||
]
|
||||
|
||||
|
@ -221,6 +227,7 @@ class KlipperPlugin(
|
|||
"js/klipper_leveling.js",
|
||||
"js/klipper_pid_tuning.js",
|
||||
"js/klipper_offset.js",
|
||||
"js/klipper_param_macro.js",
|
||||
"js/klipper_graph.js"
|
||||
],
|
||||
css=["css/klipper.css"],
|
||||
|
|
|
@ -12,6 +12,7 @@ $(function() {
|
|||
self.loginState = parameters[1];
|
||||
self.connectionState = parameters[2];
|
||||
self.levelingViewModel = parameters[3];
|
||||
self.paramMacroViewModel = parameters[4];
|
||||
|
||||
self.shortStatus = ko.observable();
|
||||
self.logMessages = ko.observableArray();
|
||||
|
@ -53,7 +54,21 @@ $(function() {
|
|||
}
|
||||
|
||||
self.executeMacro = function(macro) {
|
||||
OctoPrint.control.sendGcode(macro.macro());
|
||||
var paramObjRegex = /{(.*?)}/g;
|
||||
|
||||
if (macro.macro().match(paramObjRegex) == null) {
|
||||
OctoPrint.control.sendGcode(
|
||||
macro.macro().replace(/(?:\r\n|\r|\n)/g, " ")
|
||||
);
|
||||
} else {
|
||||
self.paramMacroViewModel.process(macro);
|
||||
|
||||
var dialog = $("#klipper_macro_dialog");
|
||||
dialog.modal({
|
||||
show: 'true',
|
||||
backdrop: 'static'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.onGetStatus = function() {
|
||||
|
@ -97,7 +112,13 @@ $(function() {
|
|||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperViewModel,
|
||||
dependencies: ["settingsViewModel", "loginStateViewModel", "connectionViewModel", "klipperLevelingViewModel"],
|
||||
dependencies: [
|
||||
"settingsViewModel",
|
||||
"loginStateViewModel",
|
||||
"connectionViewModel",
|
||||
"klipperLevelingViewModel",
|
||||
"klipperMacroDialogViewModel"
|
||||
],
|
||||
elements: ["#tab_plugin_klipper_main", "#sidebar_plugin_klipper", "#navbar_plugin_klipper"]
|
||||
});
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
// OctoPrint Klipper Plugin
|
||||
//
|
||||
// Copyright (C) 2018 Martin Muehlhaeuser <github@mmone.de>
|
||||
//
|
||||
// This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
|
||||
$(function() {
|
||||
function KlipperMacroDialogViewModel(parameters) {
|
||||
var self = this;
|
||||
|
||||
self.parameters = ko.observableArray();
|
||||
self.interpolatedCmd;
|
||||
self.macro;
|
||||
self.macroName = ko.observable();
|
||||
|
||||
var paramObjRegex = /{(.*?)}/g;
|
||||
var keyValueRegex = /(\w*)\s*:\s*([\w°"|]*)/g;
|
||||
|
||||
self.process = function(macro) {
|
||||
self.macro = macro.macro();
|
||||
self.macroName(macro.name());
|
||||
|
||||
var matches = self.macro.match(paramObjRegex);
|
||||
var params = [];
|
||||
|
||||
for (var i=0; i < matches.length; i++) {
|
||||
var obj = {};
|
||||
var res = keyValueRegex.exec(matches[i]);
|
||||
|
||||
while (res != null) {
|
||||
if("options" == res[1]) {
|
||||
obj["options"] = res[2].split("|");
|
||||
} else {
|
||||
obj[res[1]] = res[2];
|
||||
}
|
||||
res = keyValueRegex.exec(matches[i]);
|
||||
}
|
||||
|
||||
if(!("label" in obj)) {
|
||||
obj["label"] = "Input " + (i+1);
|
||||
}
|
||||
|
||||
if(!("unit" in obj)) {
|
||||
obj["unit"] = "";
|
||||
}
|
||||
|
||||
if("default" in obj) {
|
||||
obj["value"] = obj["default"];
|
||||
}
|
||||
|
||||
params.push(obj);
|
||||
}
|
||||
self.parameters(params);
|
||||
}
|
||||
|
||||
self.executeMacro = function() {
|
||||
var i=-1;
|
||||
|
||||
function replaceParams(match) {
|
||||
i++;
|
||||
return self.parameters()[i]["value"];
|
||||
}
|
||||
|
||||
expanded = self.macro.replace(paramObjRegex, replaceParams)
|
||||
expanded = expanded.replace(/(?:\r\n|\r|\n)/g, " ");
|
||||
|
||||
OctoPrint.control.sendGcode(expanded);
|
||||
}
|
||||
}
|
||||
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: KlipperMacroDialogViewModel,
|
||||
dependencies: [],
|
||||
elements: ["#klipper_macro_dialog"]
|
||||
});
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
<div id="klipper_macro_dialog" class="modal hide fade small" tabindex="-1" role="dialog" aria-labelledby="klipper_macro_dialog_label" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h3 id="klipper_pid_tuning_dialog_label">{{ _('Run - ') }}<span data-bind="text: macroName"></span></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="control-group" data-bind="foreach: parameters">
|
||||
<label class="control-label" data-bind="text: label"></label>
|
||||
<div class="controls">
|
||||
<!-- ko if: $data.hasOwnProperty("options") -->
|
||||
<div class="input-append">
|
||||
<select data-bind="options: options, value: value"></select>
|
||||
<span class="add-on" data-bind="text: unit"></span>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: !$data.hasOwnProperty("options") -->
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level span2" data-bind="value: value">
|
||||
<span class="add-on" data-bind="text: unit"></span>
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button class="btn btn-block" data-bind="click: executeMacro" data-dismiss="modal">
|
||||
<i class="icon-cross"></i> {{ _('OK') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -6,6 +6,7 @@
|
|||
<li><a href="#conf" data-toggle="tab">Klipper Configuration</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<!-- Basics -->
|
||||
<div class="tab-pane active" id="basic">
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Serial Port') }}</label>
|
||||
|
@ -38,6 +39,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Macros -->
|
||||
<div class="tab-pane" id="macros">
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
|
@ -69,7 +71,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="control-label">{{ _('GCODE') }}</label>
|
||||
<label class="control-label">{{ _('Command') }}</label>
|
||||
<div class="controls">
|
||||
<div class="row-fluid">
|
||||
<div class="span8">
|
||||
|
@ -86,7 +88,21 @@
|
|||
<a href='#' data-bind='click: addMacro' class="fa fa-plus-circle"></a> {{ _('Add Macro') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
To show a dialog that asks for parameters you can write your macro like in the following example:<br>
|
||||
</span>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<pre>
|
||||
PID_CALIBRATE
|
||||
HEATER={label:Heater, default:extruder, options:extruder|extruder1}
|
||||
TARGET={label:Temperature, unit:°C, default:190}
|
||||
WRITE_FILE={label:WriteFile, default:0, options:0|1}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Leveling -->
|
||||
<div class="tab-pane" id="level">
|
||||
<div class="control-group">
|
||||
<span class="help-block">
|
||||
|
@ -164,6 +180,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Klipper Conf -->
|
||||
<div class="tab-pane" id="conf">
|
||||
<div class="control-group">
|
||||
<textarea id="plugin-klipper-config" rows="31" class="block" data-bind="value: settings.settings.plugins.klipper.config"></textarea>
|
||||
|
|
Loading…
Reference in New Issue