Skip to content

Commit

Permalink
1.1.3 (#189)
Browse files Browse the repository at this point in the history
* added `@TASMOTAON <ip> <indx>` and `@TASMOTAOFF <ip> <indx>` 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
  • Loading branch information
jneilliii authored Oct 15, 2022
1 parent 6ae0536 commit b4f528a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 19 deletions.
31 changes: 26 additions & 5 deletions octoprint_tasmota/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
26 changes: 26 additions & 0 deletions octoprint_tasmota/static/css/tasmota.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
65 changes: 53 additions & 12 deletions octoprint_tasmota/static/js/tasmota.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand All @@ -248,7 +282,7 @@ $(function() {
displayModeBar: false,
editable: false,
showTips: false
}
};

Plotly.react('tasmota_graph', traces, layout, options);
});
Expand Down Expand Up @@ -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 += '<br>' + k + ': ' + data.sensor_data[k]

var tooltip = '';
if (data.sensor_data || data.energy_data) {
tooltip += '<table style="width: 100%"><thead></thead><tbody>';
if(data.sensor_data) {
for(let k in data.sensor_data) {
tooltip += '<tr><td>' + k + ':</td><td>' + data.sensor_data[k] + '</td></tr>';
}
}
}
if(data.energy_data) {
for(let k in data.energy_data) {
tooltip += '<br>' + k + ': ' + data.energy_data[k]
if(data.energy_data) {
for(let k in data.energy_data) {
tooltip += '<tr><td>' + k + ':</td><td>' + data.energy_data[k] + '</td></tr>';
}
}
tooltip += '</tbody></table>';
$(('#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) {
Expand Down
2 changes: 1 addition & 1 deletion octoprint_tasmota/templates/tasmota_navbar.jinja2
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- ko foreach: settings.settings.plugins.tasmota.arrSmartplugs -->
<a class="tasmota_button" href="#" data-toggle="tooltip" data-html="true" data-bind="click: $root.toggleRelay,visible: $root.loginState.loggedIn(), tooltip: {title: $root.arrSmartplugsTooltips.get(ip()+'_'+idx()), placement: 'bottom'}" style="display: none;"><i class="icon" data-bind="css: [$root.arrSmartplugsStates.get(ip()+'_'+idx())(), icon(),(($root.processing().indexOf(ip()) > -1) ? 'icon-spin' : '')].join(' '), style: {color: $root.get_color($data)}" aria-hidden="true"></i><div class="tasmota_label" data-bind="text: $data.label_extended"></div></a>
<a class="tasmota_button hide_popover_content" href="#" data-bind="click: $root.toggleRelay,visible: $root.loginState.loggedIn(), popover: {title: $data.label, html: true, content: $root.arrSmartplugsTooltips.get(ip()+'_'+idx()), placement: 'bottom', trigger: 'hover'}, attr: { id: ('tasmota_button_link_'+ip()+'_'+idx()).replace(/[.:]/g, '_')}" style="display: none;"><i class="icon" data-bind="css: [$root.arrSmartplugsStates.get(ip()+'_'+idx())(), icon(),(($root.processing().indexOf(ip()) > -1) ? 'icon-spin' : '')].join(' '), style: {color: $root.get_color($data)}" aria-hidden="true"></i><div class="tasmota_label" data-bind="text: $data.label_extended"></div></a>
<!-- /ko -->
<div id="TasmotaWarning" data-bind="with: selectedPlug" class="modal hide fade">
<div class="modal-header">
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
plugin_name = "OctoPrint-Tasmota"

# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
plugin_version = "1.1.2"
plugin_version = "1.1.3"

# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
# module
Expand Down

0 comments on commit b4f528a

Please sign in to comment.