Add lock button

https://github.com/ntoff/OctoPrint-FanSpeedSlider/issues/10
This commit is contained in:
ntoff 2018-12-05 02:10:11 +10:00
parent 5dc813fb7b
commit 212f6a7cf8
3 changed files with 57 additions and 11 deletions

View File

@ -22,7 +22,8 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
defaultFanSpeed=100, defaultFanSpeed=100,
minSpeed=0, minSpeed=0,
maxSpeed=100, maxSpeed=100,
notifyDelay=4000 notifyDelay=4000,
lockfan=False
) )
def on_settings_save(self, data): def on_settings_save(self, data):
@ -35,6 +36,8 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
s.setInt(["maxSpeed"], data["maxSpeed"]) s.setInt(["maxSpeed"], data["maxSpeed"])
if "notifyDelay" in data.keys(): if "notifyDelay" in data.keys():
s.setInt(["notifyDelay"], data["notifyDelay"]) s.setInt(["notifyDelay"], data["notifyDelay"])
if "lockfan" in data.keys():
s.set(["lockfan"], data["lockfan"])
self.get_settings_updates() self.get_settings_updates()
#clean up settings if everything's default #clean up settings if everything's default
self.on_settings_cleanup() self.on_settings_cleanup()
@ -80,24 +83,28 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
self.defaultFanSpeed = self._settings.getInt(["defaultFanSpeed"]) self.defaultFanSpeed = self._settings.getInt(["defaultFanSpeed"])
self.minSpeed = self._settings.getInt(["minSpeed"]) self.minSpeed = self._settings.getInt(["minSpeed"])
self.maxSpeed = self._settings.getInt(["maxSpeed"]) self.maxSpeed = self._settings.getInt(["maxSpeed"])
self.lockfan = self._settings.get(["lockfan"])
getcontext().prec=5 #sets precision for "Decimal" not sure if this'll cause conflicts, ideas? getcontext().prec=5 #sets precision for "Decimal" not sure if this'll cause conflicts, ideas?
self.minPWM = round( Decimal(self.minSpeed) * Decimal(2.55), 2 ) self.minPWM = round( Decimal(self.minSpeed) * Decimal(2.55), 2 )
self.maxPWM = round( Decimal(self.maxSpeed) * Decimal(2.55), 2 ) self.maxPWM = round( Decimal(self.maxSpeed) * Decimal(2.55), 2 )
def rewrite_m106(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs): def rewrite_m106(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
if gcode and gcode.startswith('M106'): if gcode and gcode.startswith('M106') and not self.lockfan:
fanPwm = re.search("S(\d+\.?\d*)", cmd) fanPwm = re.search("S(\d+\.?\d*)", cmd)
if fanPwm and fanPwm.group(1): if fanPwm and fanPwm.group(1):
fanPwm = fanPwm.group(1) fanPwm = fanPwm.group(1)
if Decimal(fanPwm) < self.minPWM and Decimal(fanPwm) != 0: if Decimal(fanPwm) < self.minPWM and Decimal(fanPwm) != 0:
self._logger.info("fan pwm value " + str(fanPwm) + " is below threshold, increasing to " + str(self.minPWM) + " (" + str(self.minSpeed) + "%)") self._logger.info("fan pwm value " + str(fanPwm) + " is below threshold, increasing to " + str(self.minPWM) + " (" + str(self.minSpeed) + "%)")
cmd = "M106 S" + str(self.minPWM) cmd = "M106 S" + str(self.minPWM)
return cmd, return cmd,
elif Decimal(fanPwm) > self.maxPWM: elif Decimal(fanPwm) > self.maxPWM:
self._logger.info("fan pwm value " + str(fanPwm) + " is above threshold, decreasing to " + str(self.maxPWM) + " (" + str(self.maxSpeed) + "%)") self._logger.info("fan pwm value " + str(fanPwm) + " is above threshold, decreasing to " + str(self.maxPWM) + " (" + str(self.maxSpeed) + "%)")
cmd = "M106 S" + str(self.maxPWM) cmd = "M106 S" + str(self.maxPWM)
return cmd, return cmd,
elif self.lockfan and gcode and gcode.startswith(('M106', 'M107')):
self._logger.info("A cooling fan control command was seen, but fanspeedslider is locked. Control command " + str(cmd) + " removed from queue.")
return None,
def get_update_information(self): def get_update_information(self):
return dict( return dict(

View File

@ -17,7 +17,9 @@ $(function () {
self.settings.minFanSpeed = new ko.observable(0); //this, self.settings.minFanSpeed = new ko.observable(0); //this,
self.settings.maxFanSpeed = new ko.observable(100); //and this are percents 0 - 100% self.settings.maxFanSpeed = new ko.observable(100); //and this are percents 0 - 100%
self.settings.notifyDelay = new ko.observable(4000); //time in milliseconds self.settings.notifyDelay = new ko.observable(4000); //time in milliseconds
self.settings.lockfan = new ko.observable(false); //ignore fan inputs from gcode and lock the fan buttons
//Not sure why I put these here, I swear I had a plan when I did it, something about dynamic text? I dunno, should move it back to the settings page
self.settings.commonTitle = ko.observable(gettext("\n\nThis allows limiting the cooling fan without having to re-slice your model.\n\nLimited to prints controlled by OctoPrint.")); self.settings.commonTitle = ko.observable(gettext("\n\nThis allows limiting the cooling fan without having to re-slice your model.\n\nLimited to prints controlled by OctoPrint."));
self.settings.defaultTitle = ko.observable(gettext("This is the value the slider will default to when the UI is loaded / refreshed.")); self.settings.defaultTitle = ko.observable(gettext("This is the value the slider will default to when the UI is loaded / refreshed."));
self.settings.minTitle = ko.observable(gettext("Set this to the lowest value at which your fan will spin.") + self.settings.commonTitle()); self.settings.minTitle = ko.observable(gettext("Set this to the lowest value at which your fan will spin.") + self.settings.commonTitle());
@ -25,10 +27,9 @@ $(function () {
self.settings.noticeTitle = ko.observable(gettext("Notifications only apply when setting the speed via the slider + button in the UI. Set to 0 (zero) to disable notifications.")); self.settings.noticeTitle = ko.observable(gettext("Notifications only apply when setting the speed via the slider + button in the UI. Set to 0 (zero) to disable notifications."));
self.showNotify = function (self, options) { self.showNotify = function (self, options) {
options.hide = true;
options.title = "Fan Speed Control"; options.title = "Fan Speed Control";
options.delay = self.settings.notifyDelay(); options.delay = options.delay || self.settings.notifyDelay();
options.type = "info"; options.type = options.type || "info";
if (options.delay != "0") { if (options.delay != "0") {
new PNotify(options); new PNotify(options);
} }
@ -44,6 +45,7 @@ $(function () {
console.log("Fan Speed Control Plugin: " + self.control.fanSpeed() + "% is less than the minimum speed (" + self.settings.minFanSpeed() + "%), increasing."); console.log("Fan Speed Control Plugin: " + self.control.fanSpeed() + "% is less than the minimum speed (" + self.settings.minFanSpeed() + "%), increasing.");
self.control.fanSpeed(self.settings.minFanSpeed()); self.control.fanSpeed(self.settings.minFanSpeed());
var options = { var options = {
hide: true,
text: gettext('Fan speed increased to meet minimum speed requirement.'), text: gettext('Fan speed increased to meet minimum speed requirement.'),
addclass: 'fan_speed_notice_low', addclass: 'fan_speed_notice_low',
} }
@ -55,6 +57,7 @@ $(function () {
console.log("Fan Speed Control Plugin: " + self.control.fanSpeed() + "% is more than the maximum speed (" + self.settings.maxFanSpeed() + "%), decreasing."); console.log("Fan Speed Control Plugin: " + self.control.fanSpeed() + "% is more than the maximum speed (" + self.settings.maxFanSpeed() + "%), decreasing.");
self.control.fanSpeed(self.settings.maxFanSpeed()); self.control.fanSpeed(self.settings.maxFanSpeed());
var options = { var options = {
hide: true,
text: gettext('Fan speed decreased to meet maximum speed requirement.'), text: gettext('Fan speed decreased to meet maximum speed requirement.'),
addclass: 'fan_speed_notice_high', addclass: 'fan_speed_notice_high',
} }
@ -70,6 +73,27 @@ $(function () {
self.control.sendCustomCommand({ command: "M106 S" + self.control.fanSpeedToPwm() }); self.control.sendCustomCommand({ command: "M106 S" + self.control.fanSpeedToPwm() });
}; };
self.control.lockFanInput = function () {
self.settings.settings.plugins.fanspeedslider.lockfan(!self.settings.settings.plugins.fanspeedslider.lockfan());
self.settings.saveData();
self.updateSettings();
var options = {
type: "info",
hide: true,
delay: 1000*60,
text: gettext('CAUTION!! Fan speed commands are now being ignored! \n This includes commands sent via gcode and the terminal!'),
addclass: 'fan_speed_notice_fanlocked',
}
if (self.settings.lockfan() && $(".fan_speed_notice_fanlocked").length <1) {
self.showNotify(self, options);
}
}
//disables the on/off buttons if the lock is enabled
self.control.islocked = ko.pureComputed(function () {
return self.settings.settings.plugins.fanspeedslider.lockfan();
});
//ph34r //ph34r
try { try {
//for some reason touchui uses "jog general" for the fan controls? Oh well, makes my job easier //for some reason touchui uses "jog general" for the fan controls? Oh well, makes my job easier
@ -84,8 +108,11 @@ $(function () {
//add new fan controls //add new fan controls
$("#control-jog-general").find("button").eq(0).before("\ $("#control-jog-general").find("button").eq(0).before("\
<input type=\"number\" style=\"width: 95px\" data-bind=\"slider: {min: 00, max: 100, step: 1, value: fanSpeed, tooltip: 'hide'}\">\ <input type=\"number\" style=\"width: 95px\" data-bind=\"slider: {min: 00, max: 100, step: 1, value: fanSpeed, tooltip: 'hide'}\">\
<button class=\"btn btn-block control-box\" id=\"fan-on\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.sendFanSpeed() }\">" + gettext("Fan speed") + ":<span data-bind=\"text: fanSpeed() + '%'\"></span></button>\ <button class=\"btn btn-block control-box\" id=\"fan-on\" data-bind=\"enable: isOperational() && loginState.isUser() && !islocked(), click: function() { $root.sendFanSpeed() }\">" + gettext("Fan speed") + ":<span data-bind=\"text: fanSpeed() + '%'\"></span></button>\
<button class=\"btn btn-block control-box\" id=\"fan-off\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.sendCustomCommand({ type: 'command', commands: ['M106 S0'] }) }\">" + gettext("Fan off") + "</button>\ <div class=\"btn-group\">\
<button class=\"btn \" id=\"fan-off\" data-bind=\"enable: isOperational() && loginState.isUser() && !islocked(), click: function() { $root.sendCustomCommand({ type: 'command', commands: ['M106 S0'] }) }\">" + gettext("Fan off") + "</button>\
<button class=\"btn \" id=\"fan-off\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.lockFanInput() }\" title=\"" + gettext("Lock or unlock the fan controls. When locked, OctoPrint will NOT send ANY M106 / M107 commands to the printer, including those found in the gcode. Use with caution.") + "\"><i class=\"fa fa-unlock\" data-bind=\"css: {'fa-lock': islocked(), 'fa-unlock': !islocked()}\"></i></button>\
</div>\
"); ");
} else { } else {
//replace touch UI's fan on button with one that sends whatever speed is set in this plugin //replace touch UI's fan on button with one that sends whatever speed is set in this plugin
@ -96,8 +123,9 @@ $(function () {
//also add spin box + button below in its own section, button is redundant but convenient //also add spin box + button below in its own section, button is redundant but convenient
$("#control-jog-feedrate").append("\ $("#control-jog-feedrate").append("\
<input type=\"number\" style=\"width: 150px\" data-bind=\"slider: {min: 00, max: 100, step: 1, value: fanSpeed, tooltip: 'hide'}\">\ <input type=\"number\" style=\"width: 150px\" data-bind=\"slider: {min: 00, max: 100, step: 1, value: fanSpeed, tooltip: 'hide'}\">\
<button class=\"btn btn-block\" style=\"width: 169px\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.sendFanSpeed() }\">" + gettext("Fan speed:") + "<span data-bind=\"text: fanSpeed() + '%'\"></span></button>\ <button class=\"btn btn-block\" style=\"width: 169px\" data-bind=\"enable: isOperational() && loginState.isUser() && !islocked(), click: function() { $root.sendFanSpeed() }\">" + gettext("Fan speed:") + "<span data-bind=\"text: fanSpeed() + '%'\"></span></button>\
"); <button class=\"btn \" id=\"fan-off\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.lockFanInput() }\" title=\"" + gettext("Lock or unlock the fan controls. When locked, OctoPrint will NOT send ANY M106 / M107 commands to the printer, including those found in the gcode. Use with caution.") + "\">" + gettext('Fan Controls ') + "<i class=\"fa fa-unlock\" data-bind=\"css: {'fa-lock': islocked(), 'fa-unlock': !islocked()}\"></i></button>\
");
} }
} }
catch (error) { catch (error) {
@ -109,6 +137,7 @@ $(function () {
self.settings.minFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.minSpeed())); self.settings.minFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.minSpeed()));
self.settings.maxFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.maxSpeed())); self.settings.maxFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.maxSpeed()));
self.settings.notifyDelay(parseInt(self.settings.settings.plugins.fanspeedslider.notifyDelay())); self.settings.notifyDelay(parseInt(self.settings.settings.plugins.fanspeedslider.notifyDelay()));
self.settings.lockfan(self.settings.settings.plugins.fanspeedslider.lockfan());
} }
catch (error) { catch (error) {
console.log(error); console.log(error);

View File

@ -33,6 +33,16 @@
</div> </div>
</div> </div>
<p><i>{{ _('NOTE: The min/max setting has no effect when you are printing from an SD card that is attached directly to the printer as the gcode does not pass through OctoPrint.') }}</i></p> <p><i>{{ _('NOTE: The min/max setting has no effect when you are printing from an SD card that is attached directly to the printer as the gcode does not pass through OctoPrint.') }}</i></p>
<div class="control-group">
<label class="control-label">{{ _('Disable M106 / M107') }}</label>
<div class="controls">
<div class="input-append">
<input type="checkbox" class="input-mini" data-bind="attr: { title: maxTitle }, checked: settings.plugins.fanspeedslider.lockfan">
</div>
<span class="help-block">{{ _('Disables cooling fan commands from reaching the printer. Use with caution. (This performs the same function as the padlock button in the fan section of the controls page)') }}</span>
</div>
</div>
<h3>{{ _('Notification Auto Hide Delay') }}</h3> <h3>{{ _('Notification Auto Hide Delay') }}</h3>
<div class="control-group"> <div class="control-group">
<label class="control-label">{{ _('Notification Autohide Delay') }}</label> <label class="control-label">{{ _('Notification Autohide Delay') }}</label>