mirror of
https://github.com/beestat/app.git
synced 2025-05-31 04:06:32 -04:00
Fixed #254 - Smoothed data often terribly misrepresents real data
Smoothing is now automatically done for outdoor temperature and humidity. Removed smoothing option; disabled by default for all indoor series.
This commit is contained in:
parent
a84417b8d4
commit
2efcb60fcc
@ -23,14 +23,6 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A couple private helper functions for manipulating the min/max y values.
|
|
||||||
var y_min_max = function(value) {
|
|
||||||
if (value !== null) {
|
|
||||||
data.metadata.chart.y_min = Math.min(data.metadata.chart.y_min, value);
|
|
||||||
data.metadata.chart.y_max = Math.max(data.metadata.chart.y_max, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Duration objects. These are passed by reference into the metadata.
|
// Duration objects. These are passed by reference into the metadata.
|
||||||
var durations = {};
|
var durations = {};
|
||||||
|
|
||||||
@ -102,20 +94,6 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
|
|||||||
|
|
||||||
var runtime_sensors = beestat.runtime_sensor.get_runtime_sensors_by_date_();
|
var runtime_sensors = beestat.runtime_sensor.get_runtime_sensors_by_date_();
|
||||||
|
|
||||||
// Initialize moving average.
|
|
||||||
var moving = [];
|
|
||||||
var moving_count;
|
|
||||||
if (beestat.setting('runtime_sensor_detail_smoothing') === true) {
|
|
||||||
moving_count = 5;
|
|
||||||
} else {
|
|
||||||
moving_count = 1;
|
|
||||||
}
|
|
||||||
var offset;
|
|
||||||
for (var i = 0; i < moving_count; i++) {
|
|
||||||
offset = (i - Math.floor(moving_count / 2)) * 300000;
|
|
||||||
moving.push(runtime_sensors[begin_m.valueOf() + offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop.
|
// Loop.
|
||||||
var current_m = begin_m;
|
var current_m = begin_m;
|
||||||
while (
|
while (
|
||||||
@ -137,13 +115,10 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var temperature_moving = beestat.temperature(
|
var temperature = beestat.temperature(runtime_sensor.temperature);
|
||||||
beestat.runtime_sensor.get_average_(moving, sensor.sensor_id)
|
data.series['temperature_' + runtime_sensor.sensor_id].push(temperature);
|
||||||
);
|
|
||||||
data.series['temperature_' + runtime_sensor.sensor_id].push(temperature_moving);
|
|
||||||
y_min_max(temperature_moving);
|
|
||||||
data.metadata.series['temperature_' + runtime_sensor.sensor_id].active = true;
|
data.metadata.series['temperature_' + runtime_sensor.sensor_id].active = true;
|
||||||
data.metadata.series['temperature_' + runtime_sensor.sensor_id].data[current_m.valueOf()] = temperature_moving;
|
data.metadata.series['temperature_' + runtime_sensor.sensor_id].data[current_m.valueOf()] = temperature;
|
||||||
|
|
||||||
if (runtime_sensor.occupancy === true) {
|
if (runtime_sensor.occupancy === true) {
|
||||||
let swimlane_properties =
|
let swimlane_properties =
|
||||||
@ -181,14 +156,6 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
current_m.add(5, 'minute');
|
current_m.add(5, 'minute');
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the first row in the moving average and add the next one. Yes
|
|
||||||
* this could introduce undefined values; that's ok. Those are handled in
|
|
||||||
* the get_average_ function.
|
|
||||||
*/
|
|
||||||
moving.shift();
|
|
||||||
moving.push(runtime_sensors[current_m.valueOf() + offset]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -212,34 +179,3 @@ beestat.runtime_sensor.get_runtime_sensors_by_date_ = function() {
|
|||||||
}
|
}
|
||||||
return runtime_sensors;
|
return runtime_sensors;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an array of runtime_sensors, get the average value of one of the
|
|
||||||
* keys. Allows and ignores undefined values in order to keep a more accurate
|
|
||||||
* moving average.
|
|
||||||
*
|
|
||||||
* @param {array} runtime_sensors
|
|
||||||
* @param {string} sensor_id The index in the sub-array
|
|
||||||
*
|
|
||||||
* @return {number} The average.
|
|
||||||
*/
|
|
||||||
beestat.runtime_sensor.get_average_ = function(runtime_sensors, sensor_id) {
|
|
||||||
var average = 0;
|
|
||||||
var count = 0;
|
|
||||||
for (var i = 0; i < runtime_sensors.length; i++) {
|
|
||||||
if (
|
|
||||||
runtime_sensors[i] !== undefined &&
|
|
||||||
runtime_sensors[i][sensor_id] !== undefined &&
|
|
||||||
runtime_sensors[i][sensor_id].temperature !== null
|
|
||||||
) {
|
|
||||||
average += runtime_sensors[i][sensor_id].temperature;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return average / count;
|
|
||||||
};
|
|
||||||
|
@ -152,12 +152,8 @@ beestat.runtime_thermostat.get_data = function(thermostat_id, range) {
|
|||||||
|
|
||||||
// Initialize moving average.
|
// Initialize moving average.
|
||||||
var moving = [];
|
var moving = [];
|
||||||
var moving_count;
|
var moving_count = 15;
|
||||||
if (beestat.setting('runtime_thermostat_detail_smoothing') === true) {
|
|
||||||
moving_count = 10;
|
|
||||||
} else {
|
|
||||||
moving_count = 1;
|
|
||||||
}
|
|
||||||
var offset;
|
var offset;
|
||||||
for (var i = 0; i < moving_count; i++) {
|
for (var i = 0; i < moving_count; i++) {
|
||||||
offset = (i - Math.floor(moving_count / 2)) * 300000;
|
offset = (i - Math.floor(moving_count / 2)) * 300000;
|
||||||
@ -181,29 +177,8 @@ beestat.runtime_thermostat.get_data = function(thermostat_id, range) {
|
|||||||
|
|
||||||
if (runtime_thermostat !== undefined) {
|
if (runtime_thermostat !== undefined) {
|
||||||
/**
|
/**
|
||||||
* Things that use the moving average.
|
* Outdoor temp/humidity (moving average).
|
||||||
*/
|
*/
|
||||||
var indoor_humidity_moving = beestat.runtime_thermostat.get_average_(moving, 'indoor_humidity');
|
|
||||||
data.series.indoor_humidity.push(indoor_humidity_moving);
|
|
||||||
data.metadata.series.indoor_humidity.data[current_m.valueOf()] =
|
|
||||||
runtime_thermostat.indoor_humidity;
|
|
||||||
data.metadata.series.indoor_humidity.active = true;
|
|
||||||
|
|
||||||
var outdoor_humidity_moving = beestat.runtime_thermostat.get_average_(moving, 'outdoor_humidity');
|
|
||||||
data.series.outdoor_humidity.push(outdoor_humidity_moving);
|
|
||||||
data.metadata.series.outdoor_humidity.data[current_m.valueOf()] =
|
|
||||||
runtime_thermostat.outdoor_humidity;
|
|
||||||
data.metadata.series.outdoor_humidity.active = true;
|
|
||||||
|
|
||||||
var indoor_temperature_moving = beestat.temperature(
|
|
||||||
beestat.runtime_thermostat.get_average_(moving, 'indoor_temperature')
|
|
||||||
);
|
|
||||||
data.series.indoor_temperature.push(indoor_temperature_moving);
|
|
||||||
data.metadata.series.indoor_temperature.data[current_m.valueOf()] =
|
|
||||||
beestat.temperature(runtime_thermostat.indoor_temperature);
|
|
||||||
y_min_max(indoor_temperature_moving);
|
|
||||||
data.metadata.series.indoor_temperature.active = true;
|
|
||||||
|
|
||||||
var outdoor_temperature_moving = beestat.temperature(
|
var outdoor_temperature_moving = beestat.temperature(
|
||||||
beestat.runtime_thermostat.get_average_(moving, 'outdoor_temperature')
|
beestat.runtime_thermostat.get_average_(moving, 'outdoor_temperature')
|
||||||
);
|
);
|
||||||
@ -213,6 +188,32 @@ beestat.runtime_thermostat.get_data = function(thermostat_id, range) {
|
|||||||
y_min_max(outdoor_temperature_moving);
|
y_min_max(outdoor_temperature_moving);
|
||||||
data.metadata.series.outdoor_temperature.active = true;
|
data.metadata.series.outdoor_temperature.active = true;
|
||||||
|
|
||||||
|
var outdoor_humidity_moving = beestat.runtime_thermostat.get_average_(
|
||||||
|
moving,
|
||||||
|
'outdoor_humidity'
|
||||||
|
);
|
||||||
|
data.series.outdoor_humidity.push(outdoor_humidity_moving);
|
||||||
|
data.metadata.series.outdoor_humidity.data[current_m.valueOf()] =
|
||||||
|
runtime_thermostat.outdoor_humidity;
|
||||||
|
data.metadata.series.outdoor_humidity.active = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indoor temp/humidity.
|
||||||
|
*/
|
||||||
|
data.series.indoor_humidity.push(runtime_thermostat.indoor_humidity);
|
||||||
|
data.metadata.series.indoor_humidity.data[current_m.valueOf()] =
|
||||||
|
runtime_thermostat.indoor_humidity;
|
||||||
|
data.metadata.series.indoor_humidity.active = true;
|
||||||
|
|
||||||
|
var indoor_temperature = beestat.temperature(
|
||||||
|
runtime_thermostat.indoor_temperature
|
||||||
|
);
|
||||||
|
data.series.indoor_temperature.push(indoor_temperature);
|
||||||
|
data.metadata.series.indoor_temperature.data[current_m.valueOf()] =
|
||||||
|
indoor_temperature;
|
||||||
|
y_min_max(indoor_temperature);
|
||||||
|
data.metadata.series.indoor_temperature.active = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add setpoints, but only when relevant. For example: Only show the
|
* Add setpoints, but only when relevant. For example: Only show the
|
||||||
* heat setpoint line when the heat is actually on.
|
* heat setpoint line when the heat is actually on.
|
||||||
|
@ -12,7 +12,6 @@ beestat.setting = function(key, opt_value, opt_callback) {
|
|||||||
var user = beestat.user.get();
|
var user = beestat.user.get();
|
||||||
|
|
||||||
var defaults = {
|
var defaults = {
|
||||||
'runtime_thermostat_detail_smoothing': true,
|
|
||||||
'runtime_thermostat_detail_range_type': 'dynamic',
|
'runtime_thermostat_detail_range_type': 'dynamic',
|
||||||
'runtime_thermostat_detail_range_static_begin': moment()
|
'runtime_thermostat_detail_range_static_begin': moment()
|
||||||
.subtract(3, 'day')
|
.subtract(3, 'day')
|
||||||
@ -20,7 +19,6 @@ beestat.setting = function(key, opt_value, opt_callback) {
|
|||||||
'runtime_thermostat_detail_range_static_end': moment().format('MM/DD/YYYY'),
|
'runtime_thermostat_detail_range_static_end': moment().format('MM/DD/YYYY'),
|
||||||
'runtime_thermostat_detail_range_dynamic': 3,
|
'runtime_thermostat_detail_range_dynamic': 3,
|
||||||
|
|
||||||
'runtime_sensor_detail_smoothing': true,
|
|
||||||
'runtime_sensor_detail_range_type': 'dynamic',
|
'runtime_sensor_detail_range_type': 'dynamic',
|
||||||
'runtime_sensor_detail_range_static_begin': moment()
|
'runtime_sensor_detail_range_static_begin': moment()
|
||||||
.subtract(3, 'day')
|
.subtract(3, 'day')
|
||||||
|
@ -24,7 +24,6 @@ beestat.component.card.runtime_sensor_detail = function(thermostat_id) {
|
|||||||
|
|
||||||
beestat.dispatcher.addEventListener(
|
beestat.dispatcher.addEventListener(
|
||||||
[
|
[
|
||||||
'setting.runtime_sensor_detail_smoothing',
|
|
||||||
'setting.runtime_sensor_detail_range_type',
|
'setting.runtime_sensor_detail_range_type',
|
||||||
'setting.runtime_sensor_detail_range_dynamic',
|
'setting.runtime_sensor_detail_range_dynamic',
|
||||||
'cache.runtime_thermostat',
|
'cache.runtime_thermostat',
|
||||||
@ -305,22 +304,6 @@ beestat.component.card.runtime_sensor_detail.prototype.decorate_top_right_ = fun
|
|||||||
self.charts_.temperature.reset_zoom();
|
self.charts_.temperature.reset_zoom();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (beestat.setting('runtime_sensor_detail_smoothing') === true) {
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
|
||||||
.set_text('Disable Smothing')
|
|
||||||
.set_icon('chart_line')
|
|
||||||
.set_callback(function() {
|
|
||||||
beestat.setting('runtime_sensor_detail_smoothing', false);
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
|
||||||
.set_text('Enable Smoothing')
|
|
||||||
.set_icon('chart_bell_curve')
|
|
||||||
.set_callback(function() {
|
|
||||||
beestat.setting('runtime_sensor_detail_smoothing', true);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
menu.add_menu_item(new beestat.component.menu_item()
|
||||||
.set_text('Help')
|
.set_text('Help')
|
||||||
.set_icon('help_circle')
|
.set_icon('help_circle')
|
||||||
|
@ -24,7 +24,6 @@ beestat.component.card.runtime_thermostat_detail = function(thermostat_id) {
|
|||||||
|
|
||||||
beestat.dispatcher.addEventListener(
|
beestat.dispatcher.addEventListener(
|
||||||
[
|
[
|
||||||
'setting.runtime_thermostat_detail_smoothing',
|
|
||||||
'setting.runtime_thermostat_detail_range_type',
|
'setting.runtime_thermostat_detail_range_type',
|
||||||
'setting.runtime_thermostat_detail_range_dynamic',
|
'setting.runtime_thermostat_detail_range_dynamic',
|
||||||
'cache.runtime_thermostat'
|
'cache.runtime_thermostat'
|
||||||
@ -291,22 +290,6 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_top_right_ =
|
|||||||
self.charts_.temperature.reset_zoom();
|
self.charts_.temperature.reset_zoom();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (beestat.setting('runtime_thermostat_detail_smoothing') === true) {
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
|
||||||
.set_text('Disable Smothing')
|
|
||||||
.set_icon('chart_line')
|
|
||||||
.set_callback(function() {
|
|
||||||
beestat.setting('runtime_thermostat_detail_smoothing', false);
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
|
||||||
.set_text('Enable Smoothing')
|
|
||||||
.set_icon('chart_bell_curve')
|
|
||||||
.set_callback(function() {
|
|
||||||
beestat.setting('runtime_thermostat_detail_smoothing', true);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.add_menu_item(new beestat.component.menu_item()
|
menu.add_menu_item(new beestat.component.menu_item()
|
||||||
.set_text('Help')
|
.set_text('Help')
|
||||||
.set_icon('help_circle')
|
.set_icon('help_circle')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user