Navigation Menu

Skip to content

Commit

Permalink
Base cut off point for temperature graph on timestamps instead of dat…
Browse files Browse the repository at this point in the history
…a points

Cut off of the temperature graph is now not based on the number of data points any more but on the actual time of the data points. Anything older than ``n`` minutes will be cut off, with ``n`` defaulting to 30min. This value can be changed under "Temperatures" in the Settings

Closes #343
  • Loading branch information
foosel committed May 5, 2015
1 parent ede2e8c commit f19d0f0
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -124,6 +124,9 @@
* Made baudrate detection a bit more solid, still can't perform wonders.
* Only show configuration options for additional extruders if more than one is available, and don't include offset
configuration for first nozzle which acts as reference for the other offsets ([#677](https://github.com/foosel/OctoPrint/issues/677)).
* Cut off of the temperature graph is now not based on the number of data points any more but on the actual time of the
data points. Anything older than ``n`` minutes will be cut off, with ``n`` defaulting to 30min. This value can be
changed under "Temperatures" in the Settings ([#343](https://github.com/foosel/OctoPrint/issues/343)).

### Bug Fixes

Expand Down
12 changes: 11 additions & 1 deletion src/octoprint/printer/standard.py
Expand Up @@ -23,6 +23,7 @@
from octoprint.printer.estimation import TimeEstimationHelper
from octoprint.settings import settings
from octoprint.util import comm as comm
from octoprint.util import InvariantContainer


class Printer(PrinterInterface, comm.MachineComPrintCallback):
Expand All @@ -46,7 +47,7 @@ def __init__(self, fileManager, analysisQueue, printerProfileManager):
self._bedTemp = None
self._targetTemp = None
self._targetBedTemp = None
self._temps = deque([], 300)
self._temps = TemperatureHistory(cutoff=settings().getInt(["temperature", "cutoff"])*60)
self._tempBacklog = []

self._latestMessage = None
Expand Down Expand Up @@ -937,3 +938,12 @@ def get_current_data(self):
}


class TemperatureHistory(InvariantContainer):
def __init__(self, cutoff=30 * 60):

def temperature_invariant(data):
data.sort(key=lambda x: x["time"])
now = int(time.time())
return [item for item in data if item["time"] >= now - cutoff]

InvariantContainer.__init__(self, guarantee_invariant=temperature_invariant)
4 changes: 3 additions & 1 deletion src/octoprint/server/api/settings.py
Expand Up @@ -89,7 +89,8 @@ def getSettings():
"watched": s.getBaseFolder("watched")
},
"temperature": {
"profiles": s.get(["temperature", "profiles"])
"profiles": s.get(["temperature", "profiles"]),
"cutoff": s.getInt(["temperature", "cutoff"])
},
"system": {
"actions": s.get(["system", "actions"]),
Expand Down Expand Up @@ -210,6 +211,7 @@ def setSettings():

if "temperature" in data.keys():
if "profiles" in data["temperature"].keys(): s.set(["temperature", "profiles"], data["temperature"]["profiles"])
if "cutoff" in data["temperature"].keys(): s.setInt(["temperature", "cutoff"], data["temperature"]["cutoff"])

if "terminalFilters" in data.keys():
s.set(["terminalFilters"], data["terminalFilters"])
Expand Down
3 changes: 2 additions & 1 deletion src/octoprint/settings.py
Expand Up @@ -157,7 +157,8 @@ def settings(init=False, basedir=None, configfile=None):
"profiles": [
{"name": "ABS", "extruder" : 210, "bed" : 100 },
{"name": "PLA", "extruder" : 180, "bed" : 60 }
]
],
"cutoff": 30
},
"printerProfiles": {
"default": None,
Expand Down
7 changes: 4 additions & 3 deletions src/octoprint/static/js/app/viewmodels/settings.js
Expand Up @@ -109,8 +109,7 @@ $(function() {
self.scripts_gcode_afterPrinterConnected = ko.observable(undefined);

self.temperature_profiles = ko.observableArray(undefined);

self.temperature_profiles = ko.observableArray(undefined);
self.temperature_cutoff = ko.observable(undefined);

self.system_actions = ko.observableArray([]);

Expand Down Expand Up @@ -260,6 +259,7 @@ $(function() {
self.scripts_gcode_afterPrinterConnected(response.scripts.gcode.afterPrinterConnected);

self.temperature_profiles(response.temperature.profiles);
self.temperature_cutoff(response.temperature.cutoff);

self.system_actions(response.system.actions);

Expand Down Expand Up @@ -334,7 +334,8 @@ $(function() {
"watched": self.folder_watched()
},
"temperature": {
"profiles": self.temperature_profiles()
"profiles": self.temperature_profiles(),
"cutoff": self.temperature_cutoff()
},
"system": {
"actions": self.system_actions()
Expand Down
16 changes: 11 additions & 5 deletions src/octoprint/static/js/app/viewmodels/temperature.js
Expand Up @@ -32,6 +32,7 @@ $(function() {
self.isLoading = ko.observable(undefined);

self.temperature_profiles = self.settingsViewModel.temperature_profiles;
self.temperature_cutoff = self.settingsViewModel.temperature_cutoff;

self.heaterOptions = ko.observable({});

Expand Down Expand Up @@ -161,11 +162,6 @@ $(function() {
if (!CONFIG_TEMPERATURE_GRAPH) return;

self.temperatures = self._processTemperatureData(data, self.temperatures);
_.each(_.keys(self.heaterOptions()), function(d) {
self.temperatures[d].actual = self.temperatures[d].actual.slice(-300);
self.temperatures[d].target = self.temperatures[d].target.slice(-300);
});

self.updatePlot();
};

Expand Down Expand Up @@ -215,6 +211,16 @@ $(function() {
})
});

var now = Date.now();
var filterOld = function(item) {
return item[0] >= now - self.temperature_cutoff() * 60 * 1000;
};

_.each(_.keys(self.heaterOptions()), function(d) {
result[d].actual = _.filter(result[d].actual, filterOld);
result[d].target = _.filter(result[d].target, filterOld);
});

return result;
};

Expand Down
12 changes: 12 additions & 0 deletions src/octoprint/templates/dialogs/settings/temperatures.jinja2
@@ -1,4 +1,16 @@
<form class="form-horizontal">
<h3>{{ _('Temperature Graph') }}</h3>
<div class="control-group">
<label class="control-label">{{ _('Graph cutoff') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" class="input-mini text-right" data-bind="value: temperature_cutoff">
<span class="add-on">min</span>
</div>
<span class="help-block">{{ _('Needs a restart of OctoPrint to become active.') }}</span>
</div>
</div>
<h3>{{ _('Temperature Presets') }}</h3>
<div class="row-fluid">
<div class="offset4 span3"><h4>{{ _('Extruder') }}</h4></div>
<div class="span3"><h4>{{ _('Bed') }}</h4></div>
Expand Down
33 changes: 33 additions & 0 deletions src/octoprint/util/__init__.py
Expand Up @@ -649,3 +649,36 @@ def _internal_set(self, value):
self._counter = self._max
self._event.set()
self._logger.debug("Set event")


class InvariantContainer(object):
def __init__(self, initial_data=None, guarantee_invariant=None):
from collections import Iterable
from threading import RLock

if guarantee_invariant is None:
guarantee_invariant = lambda data: data

self._data = []
self._mutex = RLock()
self._invariant = guarantee_invariant

if initial_data is not None and isinstance(initial_data, Iterable):
for item in initial_data:
self.append(item)

def append(self, item):
with self._mutex:
self._data.append(item)
self._data = self._invariant(self._data)

def remove(self, item):
with self._mutex:
self._data.remove(item)
self._data = self._invariant(self._data)

def __len__(self):
return len(self._data)

def __iter__(self):
return self._data.__iter__()

0 comments on commit f19d0f0

Please sign in to comment.