From e9e1ea1b9bfda7943bac019263ab266247deaacb Mon Sep 17 00:00:00 2001 From: Jon Ziebell Date: Fri, 27 Jan 2023 06:35:52 -0500 Subject: [PATCH] Extended temperature profile lines --- api/user.php | 1 + js/component/card/temperature_profiles.js | 87 ++++++++++++++++++++-- js/component/chart/temperature_profiles.js | 87 ++++++++++++++++++++-- 3 files changed, 160 insertions(+), 15 deletions(-) diff --git a/api/user.php b/api/user.php index 0c4c8f9..506171e 100644 --- a/api/user.php +++ b/api/user.php @@ -128,6 +128,7 @@ class user extends cora\crud { */ public function force_log_in($user_id) { $this->session->request(null, null, $user_id); + header('Location: ' . $this->setting->get('beestat_root_uri')); } /** diff --git a/js/component/card/temperature_profiles.js b/js/component/card/temperature_profiles.js index d40994c..50f4310 100644 --- a/js/component/card/temperature_profiles.js +++ b/js/component/card/temperature_profiles.js @@ -89,9 +89,7 @@ beestat.component.card.temperature_profiles.prototype.get_data_ = function() { }) .send(); } else { - // Global x range. - var x_min = Infinity; - var x_max = -Infinity; + const profile_extremes = this.get_profile_extremes_(5); var y_min = Infinity; var y_max = -Infinity; @@ -118,14 +116,25 @@ beestat.component.card.temperature_profiles.prototype.get_data_ = function() { var min_max_keys = Object.keys(profile.deltas); + if (type.includes('heat') === true) { + min_max_keys.push(beestat.temperature(profile_extremes.heat.min)); + min_max_keys.push(beestat.temperature(profile_extremes.heat.max)); + } else if (type.includes('cool') === true) { + min_max_keys.push(beestat.temperature(profile_extremes.cool.min)); + min_max_keys.push(beestat.temperature(profile_extremes.cool.max)); + } else if (type.includes('resist') === true) { + min_max_keys.push(beestat.temperature(profile_extremes.resist.min)); + min_max_keys.push(beestat.temperature(profile_extremes.heat.min)); + min_max_keys.push(beestat.temperature(profile_extremes.resist.max)); + min_max_keys.push(beestat.temperature(profile_extremes.cool.max)); + } + // Filter out nulls + min_max_keys = min_max_keys.filter(Boolean); + // This specific trendline x range. var this_x_min = Math.min.apply(null, min_max_keys); var this_x_max = Math.max.apply(null, min_max_keys); - // Global x range. - x_min = Math.min(x_min, this_x_min); - x_max = Math.max(x_max, this_x_max); - data.series['trendline_' + type] = []; data.series['raw_' + type] = []; @@ -253,7 +262,7 @@ beestat.component.card.temperature_profiles.prototype.get_subtitle_ = function() // How much data was used to generate this. const duration_weeks = Math.round(thermostat.profile.metadata.duration / 7); - duration_text += ' from the past '; + duration_text += ' from the past'; if (duration_weeks === 0) { duration_text += ' few days'; } else if (duration_weeks === 1) { @@ -292,3 +301,65 @@ beestat.component.card.temperature_profiles.prototype.decorate_top_right_ = func window.open('https://doc.beestat.io/9c0fba6793dd4bc68f798c1516f0ea25'); })); }; + +/** + * Get the profile extremes for heat, cool, and resist. + * + * @param {number} padding How much extra to pad the extremes by. + * + * @return {object} + */ +beestat.component.card.temperature_profiles.prototype.get_profile_extremes_ = function(padding) { + const thermostat = beestat.cache.thermostat[this.thermostat_id_]; + + const extremes = { + 'heat': { + 'min': Infinity, + 'max': -Infinity + }, + 'cool': { + 'min': Infinity, + 'max': -Infinity + }, + 'resist': { + 'min': Infinity, + 'max': -Infinity + } + }; + + for (let type in thermostat.profile.temperature) { + const profile = thermostat.profile.temperature[type]; + + if (profile !== null) { + let parent_type; + if (type.includes('cool')) { + parent_type = 'cool'; + } else if (type.includes('heat')) { + parent_type = 'heat'; + } else if (type.includes('resist')) { + parent_type = 'resist'; + } + + extremes[parent_type].min = Math.min( + extremes[parent_type].min, + Math.min.apply(null, Object.keys(profile.deltas)) - 5 + ); + extremes[parent_type].max = Math.max( + extremes[parent_type].max, + Math.max.apply(null, Object.keys(profile.deltas)) + 5 + ); + } + } + + // Convert +/-Infinity to null + for (let parent_type in extremes) { + if (extremes[parent_type].min === Infinity) { + extremes[parent_type].min = null; + } + if (extremes[parent_type].max === -Infinity) { + extremes[parent_type].max = null; + } + } + + return extremes; +}; diff --git a/js/component/chart/temperature_profiles.js b/js/component/chart/temperature_profiles.js index 4c7ba87..a629fe6 100644 --- a/js/component/chart/temperature_profiles.js +++ b/js/component/chart/temperature_profiles.js @@ -39,8 +39,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_heat_1, + this.data_.series.raw_heat_1 + ) }); // Trendline data @@ -53,8 +59,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_heat_2, + this.data_.series.raw_heat_2 + ) }); // Trendline data @@ -67,8 +79,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_auxiliary_heat_1, + this.data_.series.raw_auxiliary_heat_1 + ) }); // Trendline data @@ -81,8 +99,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_auxiliary_heat_2, + this.data_.series.raw_auxiliary_heat_2 + ) }); // Trendline data @@ -95,8 +119,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_cool_1, + this.data_.series.raw_cool_1 + ) }); // Trendline data @@ -109,8 +139,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_cool_2, + this.data_.series.raw_cool_2 + ) }); // Trendline data @@ -123,8 +159,14 @@ beestat.component.chart.temperature_profiles.prototype.get_options_series_ = fun 'states': {'hover': {'enabled': false}} }, 'type': 'line', + 'dashStyle': 'ShortDash', 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} + 'states': {'hover': {'lineWidthPlus': 0}}, + 'zoneAxis': 'x', + 'zones': this.get_zones_( + this.data_.series.trendline_resist, + this.data_.series.raw_resist + ) }); // Raw data @@ -409,3 +451,34 @@ beestat.component.chart.temperature_profiles.prototype.get_options_chart_height_ beestat.component.chart.temperature_profiles.prototype.get_options_plotOptions_series_connectNulls_ = function() { return true; }; + +/** + * Get zones to make the trendlines dashed outside of where there is raw data. + * + * @param {object} trendline_data The trendline data. + * @param {object} raw_data The raw data. + * + * @return {object} + */ +beestat.component.chart.temperature_profiles.prototype.get_zones_ = function(trendline_data, raw_data) { + const zones = []; + + if ( + trendline_data === undefined || + raw_data === undefined + ) { + return zones; + } + + zones.push({ + 'value': raw_data[0][0], + 'dashStyle': 'ShortDash' + }); + + zones.push({ + 'value': raw_data[raw_data.length - 1][0], + 'dashStyle': 'Solid' + }); + + return zones; +};