1
0
mirror of https://github.com/beestat/app.git synced 2025-05-24 02:14:03 -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:
Jon Ziebell 2020-02-22 14:39:24 -05:00
parent a84417b8d4
commit 2efcb60fcc
5 changed files with 32 additions and 131 deletions

View File

@ -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.
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_();
// 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.
var current_m = begin_m;
while (
@ -137,13 +115,10 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
return;
}
var temperature_moving = beestat.temperature(
beestat.runtime_sensor.get_average_(moving, sensor.sensor_id)
);
data.series['temperature_' + runtime_sensor.sensor_id].push(temperature_moving);
y_min_max(temperature_moving);
var temperature = beestat.temperature(runtime_sensor.temperature);
data.series['temperature_' + runtime_sensor.sensor_id].push(temperature);
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) {
let swimlane_properties =
@ -181,14 +156,6 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
}
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;
@ -212,34 +179,3 @@ beestat.runtime_sensor.get_runtime_sensors_by_date_ = function() {
}
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;
};

View File

@ -152,12 +152,8 @@ beestat.runtime_thermostat.get_data = function(thermostat_id, range) {
// Initialize moving average.
var moving = [];
var moving_count;
if (beestat.setting('runtime_thermostat_detail_smoothing') === true) {
moving_count = 10;
} else {
moving_count = 1;
}
var moving_count = 15;
var offset;
for (var i = 0; i < moving_count; i++) {
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) {
/**
* 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(
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);
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
* heat setpoint line when the heat is actually on.

View File

@ -12,7 +12,6 @@ beestat.setting = function(key, opt_value, opt_callback) {
var user = beestat.user.get();
var defaults = {
'runtime_thermostat_detail_smoothing': true,
'runtime_thermostat_detail_range_type': 'dynamic',
'runtime_thermostat_detail_range_static_begin': moment()
.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_dynamic': 3,
'runtime_sensor_detail_smoothing': true,
'runtime_sensor_detail_range_type': 'dynamic',
'runtime_sensor_detail_range_static_begin': moment()
.subtract(3, 'day')

View File

@ -24,7 +24,6 @@ beestat.component.card.runtime_sensor_detail = function(thermostat_id) {
beestat.dispatcher.addEventListener(
[
'setting.runtime_sensor_detail_smoothing',
'setting.runtime_sensor_detail_range_type',
'setting.runtime_sensor_detail_range_dynamic',
'cache.runtime_thermostat',
@ -305,22 +304,6 @@ beestat.component.card.runtime_sensor_detail.prototype.decorate_top_right_ = fun
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()
.set_text('Help')
.set_icon('help_circle')

View File

@ -24,7 +24,6 @@ beestat.component.card.runtime_thermostat_detail = function(thermostat_id) {
beestat.dispatcher.addEventListener(
[
'setting.runtime_thermostat_detail_smoothing',
'setting.runtime_thermostat_detail_range_type',
'setting.runtime_thermostat_detail_range_dynamic',
'cache.runtime_thermostat'
@ -291,22 +290,6 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_top_right_ =
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()
.set_text('Help')
.set_icon('help_circle')