From b4f528a7fc1d8a01cb78f68bb7cf62b198f473aa Mon Sep 17 00:00:00 2001 From: jneilliii Date: Sat, 15 Oct 2022 16:45:50 -0400 Subject: [PATCH] 1.1.3 (#189) * added `@TASMOTAON ` and `@TASMOTAOFF ` gcode commands to resolve issues with firmware that errors with M80/M81 commands, resolves #178 * make polling_interval float to allow for sub-minute polling * change from tooltip to popover, thanks to @ManuelMcLure * added theme support to power graph --- octoprint_tasmota/__init__.py | 31 +++++++-- octoprint_tasmota/static/css/tasmota.css | 26 ++++++++ octoprint_tasmota/static/js/tasmota.js | 65 +++++++++++++++---- .../templates/tasmota_navbar.jinja2 | 2 +- setup.py | 2 +- 5 files changed, 107 insertions(+), 19 deletions(-) diff --git a/octoprint_tasmota/__init__.py b/octoprint_tasmota/__init__.py index 92e156d..634c455 100644 --- a/octoprint_tasmota/__init__.py +++ b/octoprint_tasmota/__init__.py @@ -148,8 +148,8 @@ def on_startup(self, host, port): def on_after_startup(self): self._logger.info("Tasmota loaded!") - if self._settings.get_boolean(["polling_enabled"]) and self._settings.get_int(["polling_interval"]) > 0: - self.poll_status = RepeatedTimer(int(self._settings.get_int(["polling_interval"])) * 60, + if self._settings.get_boolean(["polling_enabled"]) and self._settings.get_float(["polling_interval"]) > 0: + self.poll_status = RepeatedTimer(float(self._settings.get_float(["polling_interval"])) * 60, self.check_statuses) self.poll_status.start() @@ -226,7 +226,7 @@ def on_settings_save(self, data): self.poll_status.cancel() if new_polling_value: - self.poll_status = RepeatedTimer(int(self._settings.get(["pollingInterval"])) * 60, self.check_statuses) + self.poll_status = RepeatedTimer(self._settings.get_float(["pollingInterval"]) * 60, self.check_statuses) self.poll_status.start() def get_settings_version(self): @@ -304,7 +304,7 @@ def get_assets(self): def get_template_configs(self): return [ - {'type': "navbar", 'custom_bindings': True}, + {'type': "navbar", 'custom_bindings': True, 'classes': ["hide_popover_content"]}, {'type': "settings", 'custom_bindings': True}, {'type': "tab", 'custom_bindings': True}, {'type': "sidebar", 'icon': "plug", 'custom_bindings': True, 'data_bind': "visible: show_sidebar", @@ -841,13 +841,34 @@ def processAtCommand(self, comm_instance, phase, command, parameters, tags=None, if command == 'TASMOTAIDLEON': self.powerOffWhenIdle = True self._reset_idle_timer() - if command == 'TASMOTAIDLEOFF': + elif command == 'TASMOTAIDLEOFF': self.powerOffWhenIdle = False self._stop_idle_timer() if self._abort_timer is not None: self._abort_timer.cancel() self._abort_timer = None self._timeout_value = None + elif command == 'TASMOTAON': + plugip, plugidx = parameters.split(" ") + self._tasmota_logger.debug("Received TASMOTAON command, attempting power on of %s:%s." % (plugip, plugidx)) + plug = self.plug_search(self._settings.get(["arrSmartplugs"]), "ip", plugip, "idx", plugidx) + self._tasmota_logger.debug(plug) + if plug and plug["gcodeEnabled"]: + t = threading.Timer(int(plug["gcodeOnDelay"]), self.gcode_on, [plug]) + t.daemon = True + t.start() + return None + elif command == 'TASMOTAOFF': + plugip, plugidx = parameters.split(" ") + self._tasmota_logger.debug("Received TASMOTAOFF command, attempting power off of %s:%s." % (plugip, plugidx)) + plug = self.plug_search(self._settings.get(["arrSmartplugs"]), "ip", plugip, "idx", plugidx) + self._tasmota_logger.debug(plug) + if plug and plug["gcodeEnabled"]: + t = threading.Timer(int(plug["gcodeOffDelay"]), self.gcode_off, [plug]) + t.daemon = True + t.start() + return None + if command in ["TASMOTAIDLEON", "TASMOTAIDLEOFF"]: self._plugin_manager.send_plugin_message(self._identifier, dict(powerOffWhenIdle=self.powerOffWhenIdle, type="timeout", diff --git a/octoprint_tasmota/static/css/tasmota.css b/octoprint_tasmota/static/css/tasmota.css index 49b38fd..35c49ad 100644 --- a/octoprint_tasmota/static/css/tasmota.css +++ b/octoprint_tasmota/static/css/tasmota.css @@ -81,3 +81,29 @@ input[type="datetime-local"].alert-error { .navbar .nav > li > a.tasmota_button { float: left; } + +/* For popover */ +#navbar_plugin_tasmota div.popover { + width: auto !important; + max-width: 100em; +} +#navbar_plugin_tasmota div.popover table { + width: auto !important; + table-layout: auto !important; +} +#navbar_plugin_tasmota div.popover td { + width: auto !important; + white-space: nowrap; +} +#navbar_plugin_tasmota div.popover td:last-child { + padding-left: 1em; +} +#navbar_plugin_tasmota div.popover h3.popover-title { + white-space: nowrap; +} +#navbar_plugin_tasmota a.hide_popover_content + div.popover > h3.popover-title { + border: none; +} +#navbar_plugin_tasmota a.hide_popover_content + div.popover > div.popover-content { + display: none; +} diff --git a/octoprint_tasmota/static/js/tasmota.js b/octoprint_tasmota/static/js/tasmota.js index a334b4b..4b72773 100644 --- a/octoprint_tasmota/static/js/tasmota.js +++ b/octoprint_tasmota/static/js/tasmota.js @@ -187,6 +187,34 @@ $(function() { } }; + self.getDefaultBackground = function() { + // have to add to the document in order to use getComputedStyle + var div = document.createElement("div"); + document.head.appendChild(div); + var bg = window.getComputedStyle(div).backgroundColor; + document.head.removeChild(div); + return bg; + }; + + self.getInheritedBackgroundColor = function(el) { + // get default style for current browser + if (!self.defaultStyle) { + self.defaultStyle = self.getDefaultBackground(); // typically "rgba(0, 0, 0, 0)" + } + + // get computed color for el + var backgroundColor = window.getComputedStyle(el).backgroundColor; + + // if we got a real value, return it + if (backgroundColor !== self.defaultStyle) return backgroundColor; + + // if we've reached the top parent el without getting an explicit color, return default + if (!el.parentElement) return self.defaultStyle; + + // otherwise, recurse and try again on parent element + return self.getInheritedBackgroundColor(el.parentElement); + }; + self.plotEnergyData = function(){ $.ajax({ url: API_BASEURL + "plugin/tasmota", @@ -232,14 +260,20 @@ $(function() { } } + var background_color = (self.getInheritedBackgroundColor(document.getElementById('tab_plugin_tasmota')) == 'rgba(0, 0, 0, 0)') ? '#FFFFFF' : self.getInheritedBackgroundColor(document.getElementById('tab_plugin_tasmota')); + var foreground_color = ($('.tab-content').css('color') == 'rgba(0, 0, 0, 0)') ? '#FFFFFF' : $('#tabs_content').css('color'); + var layout = { autosize: true, showlegend: false, /* legend: {"orientation": "h"}, */ xaxis: { type:"date", /* tickformat:"%H:%M:%S", */ automargin: true, title: {standoff: 0},linecolor: 'black', linewidth: 2, mirror: true}, yaxis: { type:"linear", automargin: true, title: {standoff: 0},linecolor: 'black', linewidth: 2, mirror: true }, - margin: {l:35,r:30,b:0,t:20,pad:5} - } + margin: {l:35,r:30,b:0,t:20,pad:5}, + plot_bgcolor: background_color, + paper_bgcolor: background_color, + font: {color: foreground_color} + }; var options = { showLink: false, @@ -248,7 +282,7 @@ $(function() { displayModeBar: false, editable: false, showTips: false - } + }; Plotly.react('tasmota_graph', traces, layout, options); }); @@ -391,18 +425,25 @@ $(function() { console.log('plug data:'+ko.toJSON(plug)); } - var tooltip = plug.label(); - if(data.sensor_data) { - for(let k in data.sensor_data) { - tooltip += '
' + k + ': ' + data.sensor_data[k] + + var tooltip = ''; + if (data.sensor_data || data.energy_data) { + tooltip += ''; + if(data.sensor_data) { + for(let k in data.sensor_data) { + tooltip += ''; + } } - } - if(data.energy_data) { - for(let k in data.energy_data) { - tooltip += '
' + k + ': ' + data.energy_data[k] + if(data.energy_data) { + for(let k in data.energy_data) { + tooltip += ''; + } } + tooltip += '
' + k + ':' + data.sensor_data[k] + '
' + k + ':' + data.energy_data[k] + '
'; + $(('#tasmota_button_link_'+data.ip+'_'+data.idx).replace(/[.:]/g,'_')).removeClass('hide_popover_content'); + } else { + $(('#tasmota_button_link_'+data.ip+'_'+data.idx).replace(/[.:]/g,'_')).addClass('hide_popover_content'); } - //plug.label_extended = ko.observable(tooltip); try { self.arrSmartplugsTooltips.set(data.ip+'_'+data.idx, tooltip); } catch (error) { diff --git a/octoprint_tasmota/templates/tasmota_navbar.jinja2 b/octoprint_tasmota/templates/tasmota_navbar.jinja2 index 752535a..a53bfe7 100644 --- a/octoprint_tasmota/templates/tasmota_navbar.jinja2 +++ b/octoprint_tasmota/templates/tasmota_navbar.jinja2 @@ -1,5 +1,5 @@ - +