Compare commits
4 Commits
savelastsp
...
commandloc
Author | SHA1 | Date | |
---|---|---|---|
02211eb475 | |||
84dcad7b08 | |||
78dd50ffb1 | |||
212f6a7cf8 |
@ -16,6 +16,8 @@ Slide the slider, click the button. There really isn't much else to do :)
|
||||
|
||||
* The maximum fan speed setting will limit how fast the fan runs, this is useful if your fan is too strong, or you wish to limit the speed post-slice without having to re-slice your file.
|
||||
|
||||
* "Disable M106 / M107" will disable the controls and reject all M106/M107 commands before they're sent to the printer. This setting has a corresponding padlock button beside the off button, both the padlock button and this setting in the settings page do exactly the same thing. This setting is here only as a convenience.
|
||||
|
||||
* Notification autohide delay controls how long any notifications will remain on the screen for. If the user manually sets a speed outside of the set range, a notification will be displayed informing the user the fan speed has been modified. Print jobs shouldn't trigger these notifications, and so popup spam shouldn't occur, however if a user wishes not to receive notifications when setting fan speeds outside of the set range, this value can be set to 0 (zero) to disable notifications. (this setting won't / shouldn't affect OctoPrint's global notifications, it only applies to info popups generated by this plugin).
|
||||
|
||||
*Note: Slider does __not__ follow the speed of the fan. If the fan speed is set via gcode or an LCD panel on the printer, the slider will not respond to the change. It is a __setting__, not an indicator, and functions the same way the feedrate and flowrate sliders do.*
|
||||
|
BIN
image/slider.JPG
BIN
image/slider.JPG
Binary file not shown.
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@ -22,7 +22,8 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
|
||||
defaultFanSpeed=100,
|
||||
minSpeed=0,
|
||||
maxSpeed=100,
|
||||
notifyDelay=4000
|
||||
notifyDelay=4000,
|
||||
lockfan=False
|
||||
)
|
||||
|
||||
def on_settings_save(self, data):
|
||||
@ -35,6 +36,8 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
|
||||
s.setInt(["maxSpeed"], data["maxSpeed"])
|
||||
if "notifyDelay" in data.keys():
|
||||
s.setInt(["notifyDelay"], data["notifyDelay"])
|
||||
if "lockfan" in data.keys():
|
||||
s.set(["lockfan"], data["lockfan"])
|
||||
self.get_settings_updates()
|
||||
#clean up settings if everything's default
|
||||
self.on_settings_cleanup()
|
||||
@ -80,24 +83,28 @@ class FanSliderPlugin(octoprint.plugin.StartupPlugin,
|
||||
self.defaultFanSpeed = self._settings.getInt(["defaultFanSpeed"])
|
||||
self.minSpeed = self._settings.getInt(["minSpeed"])
|
||||
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?
|
||||
self.minPWM = round( Decimal(self.minSpeed) * 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):
|
||||
if gcode and gcode.startswith('M106'):
|
||||
if gcode and gcode.startswith('M106') and not self.lockfan:
|
||||
fanPwm = re.search("S(\d+\.?\d*)", cmd)
|
||||
if fanPwm and fanPwm.group(1):
|
||||
fanPwm = fanPwm.group(1)
|
||||
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) + "%)")
|
||||
cmd = "M106 S" + str(self.minPWM)
|
||||
cmd = "M106 S" + str(self.minPWM)
|
||||
return cmd,
|
||||
elif Decimal(fanPwm) > self.maxPWM:
|
||||
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)
|
||||
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):
|
||||
return dict(
|
||||
|
@ -17,7 +17,11 @@ $(function () {
|
||||
self.settings.minFanSpeed = new ko.observable(0); //this,
|
||||
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.lockfan = new ko.observable(false); //ignore fan inputs from gcode and lock the fan buttons
|
||||
|
||||
self.control.lockTitle = new ko.observable(gettext("Unlocked")); //will set the hover title info for the fan lock button
|
||||
|
||||
//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.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());
|
||||
@ -25,10 +29,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.showNotify = function (self, options) {
|
||||
options.hide = true;
|
||||
options.title = "Fan Speed Control";
|
||||
options.delay = self.settings.notifyDelay();
|
||||
options.type = "info";
|
||||
options.delay = options.delay || self.settings.notifyDelay();
|
||||
options.type = options.type || "info";
|
||||
if (options.delay != "0") {
|
||||
new PNotify(options);
|
||||
}
|
||||
@ -44,6 +47,7 @@ $(function () {
|
||||
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());
|
||||
var options = {
|
||||
hide: true,
|
||||
text: gettext('Fan speed increased to meet minimum speed requirement.'),
|
||||
addclass: 'fan_speed_notice_low',
|
||||
}
|
||||
@ -55,6 +59,7 @@ $(function () {
|
||||
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());
|
||||
var options = {
|
||||
hide: true,
|
||||
text: gettext('Fan speed decreased to meet maximum speed requirement.'),
|
||||
addclass: 'fan_speed_notice_high',
|
||||
}
|
||||
@ -70,6 +75,27 @@ $(function () {
|
||||
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
|
||||
try {
|
||||
//for some reason touchui uses "jog general" for the fan controls? Oh well, makes my job easier
|
||||
@ -84,8 +110,13 @@ $(function () {
|
||||
//add new fan controls
|
||||
$("#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'}\">\
|
||||
<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-off\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.sendCustomCommand({ type: 'command', commands: ['M106 S0'] }) }\">" + gettext("Fan off") + "</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>\
|
||||
<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-lock\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.lockFanInput() }, attr: { title: lockTitle } \">\
|
||||
<i class=\"fa fa-unlock\" data-bind=\"css: {'fa-lock': islocked(), 'fa-unlock': !islocked()}\"></i>\
|
||||
</button>\
|
||||
</div>\
|
||||
");
|
||||
} else {
|
||||
//replace touch UI's fan on button with one that sends whatever speed is set in this plugin
|
||||
@ -96,8 +127,11 @@ $(function () {
|
||||
//also add spin box + button below in its own section, button is redundant but convenient
|
||||
$("#control-jog-feedrate").append("\
|
||||
<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-lock\" data-bind=\"enable: isOperational() && loginState.isUser(), click: function() { $root.lockFanInput() }, attr: { title: lockTitle } \">\
|
||||
Fan Control Lock: <i class=\"fa fa-unlock\" data-bind=\"css: {'fa-lock': islocked(), 'fa-unlock': !islocked()}\"></i>\
|
||||
</button>\
|
||||
");
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@ -109,6 +143,14 @@ $(function () {
|
||||
self.settings.minFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.minSpeed()));
|
||||
self.settings.maxFanSpeed(parseInt(self.settings.settings.plugins.fanspeedslider.maxSpeed()));
|
||||
self.settings.notifyDelay(parseInt(self.settings.settings.plugins.fanspeedslider.notifyDelay()));
|
||||
self.settings.lockfan(self.settings.settings.plugins.fanspeedslider.lockfan());
|
||||
|
||||
if (self.settings.lockfan()) {
|
||||
self.control.lockTitle( gettext("Lock or unlock the cooling fan controls. When locked, no cooling fan commands will be sent to the printer. \n\n Fan controls are locked."));
|
||||
}
|
||||
else if (!self.settings.lockfan()) {
|
||||
self.control.lockTitle( gettext("Lock or unlock the cooling fan controls. When locked, no cooling fan commands will be sent to the printer. \n\n Fan controls are unlocked"))
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
|
@ -33,6 +33,16 @@
|
||||
</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>
|
||||
<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>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Notification Autohide Delay') }}</label>
|
||||
|
Reference in New Issue
Block a user