mirror of
https://github.com/beestat/app.git
synced 2025-06-01 04:37:12 -04:00
Enabled metrics and new profiles for early access
This commit is contained in:
parent
154af5d89f
commit
8b57cfc227
@ -29,7 +29,7 @@ class thermostat_group extends cora\crud {
|
|||||||
'generate_profile' => 604800, // 7 Days
|
'generate_profile' => 604800, // 7 Days
|
||||||
'generate_profiles' => 604800, // 7 Days
|
'generate_profiles' => 604800, // 7 Days
|
||||||
'get_scores' => 604800, // 7 Days
|
'get_scores' => 604800, // 7 Days
|
||||||
'get_metrics' => 604800 // 7 Days
|
// 'get_metrics' => 604800 // 7 Days
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -565,7 +565,8 @@ class thermostat_group extends cora\crud {
|
|||||||
|
|
||||||
$metric_codes = [
|
$metric_codes = [
|
||||||
'setpoint_heat',
|
'setpoint_heat',
|
||||||
'setpoint_cool'
|
'setpoint_cool',
|
||||||
|
'runtime_per_heating_degree_day'
|
||||||
];
|
];
|
||||||
|
|
||||||
$metrics = [];
|
$metrics = [];
|
||||||
@ -636,6 +637,25 @@ class thermostat_group extends cora\crud {
|
|||||||
$metrics['setpoint_cool']['histogram'][$setpoint_cool]++;
|
$metrics['setpoint_cool']['histogram'][$setpoint_cool]++;
|
||||||
$metrics['setpoint_cool']['values'][] = $setpoint_cool;
|
$metrics['setpoint_cool']['values'][] = $setpoint_cool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runtime_per_heating_degree_day
|
||||||
|
if(
|
||||||
|
isset($other_thermostat_group['profile']) === true &&
|
||||||
|
isset($other_thermostat_group['profile']['runtime']) == true &&
|
||||||
|
$other_thermostat_group['profile']['runtime']['heat_1'] !== null &&
|
||||||
|
isset($other_thermostat_group['profile']['degree_days']) === true &&
|
||||||
|
$other_thermostat_group['profile']['degree_days']['heat'] !== null
|
||||||
|
) {
|
||||||
|
$runtime_per_heating_degree_day = round(
|
||||||
|
$other_thermostat_group['profile']['runtime']['heat_1'] / $other_thermostat_group['profile']['degree_days']['heat'],
|
||||||
|
1
|
||||||
|
);
|
||||||
|
if(isset($metrics['runtime_per_heating_degree_day']['histogram'][(string)$runtime_per_heating_degree_day]) === false) {
|
||||||
|
$metrics['runtime_per_heating_degree_day']['histogram'][(string)$runtime_per_heating_degree_day] = 0;
|
||||||
|
}
|
||||||
|
$metrics['runtime_per_heating_degree_day']['histogram'][(string)$runtime_per_heating_degree_day]++;
|
||||||
|
$metrics['runtime_per_heating_degree_day']['values'][] = $runtime_per_heating_degree_day;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,6 +676,13 @@ class thermostat_group extends cora\crud {
|
|||||||
$metrics['setpoint_cool']['median'] = array_median($metrics['setpoint_cool']['values']);
|
$metrics['setpoint_cool']['median'] = array_median($metrics['setpoint_cool']['values']);
|
||||||
unset($metrics['setpoint_cool']['values']);
|
unset($metrics['setpoint_cool']['values']);
|
||||||
|
|
||||||
|
// runtime_per_heating_degree_day
|
||||||
|
$metrics['runtime_per_heating_degree_day']['standard_deviation'] = round($this->standard_deviation(
|
||||||
|
$metrics['runtime_per_heating_degree_day']['values']
|
||||||
|
), 2);
|
||||||
|
$metrics['runtime_per_heating_degree_day']['median'] = array_median($metrics['runtime_per_heating_degree_day']['values']);
|
||||||
|
unset($metrics['runtime_per_heating_degree_day']['values']);
|
||||||
|
|
||||||
return $metrics;
|
return $metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
beestat.home_comparisons = {};
|
beestat.comparisons = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fire off an API call to get the comparison scores using the currently
|
* Fire off an API call to get the comparison scores using the currently
|
||||||
@ -14,7 +14,7 @@ beestat.home_comparisons = {};
|
|||||||
* @param {Function} callback Optional callback to fire when the API call
|
* @param {Function} callback Optional callback to fire when the API call
|
||||||
* completes.
|
* completes.
|
||||||
*/
|
*/
|
||||||
beestat.home_comparisons.get_comparison_scores = function(callback) {
|
beestat.comparisons.get_comparison_scores = function(callback) {
|
||||||
var types = [
|
var types = [
|
||||||
'heat',
|
'heat',
|
||||||
'cool',
|
'cool',
|
||||||
@ -29,15 +29,26 @@ beestat.home_comparisons.get_comparison_scores = function(callback) {
|
|||||||
'get_scores',
|
'get_scores',
|
||||||
{
|
{
|
||||||
'type': type,
|
'type': type,
|
||||||
'attributes': beestat.home_comparisons.get_comparison_attributes(type)
|
'attributes': beestat.comparisons.get_comparison_attributes(type)
|
||||||
},
|
},
|
||||||
type
|
'score_' + type
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.add_call(
|
||||||
|
'thermostat_group',
|
||||||
|
'get_metrics',
|
||||||
|
{
|
||||||
|
'attributes': beestat.comparisons.get_comparison_attributes('resist') // todo
|
||||||
|
},
|
||||||
|
'metrics'
|
||||||
|
);
|
||||||
|
|
||||||
api.set_callback(function(data) {
|
api.set_callback(function(data) {
|
||||||
|
beestat.cache.set('data.metrics', data.metrics);
|
||||||
|
|
||||||
types.forEach(function(type) {
|
types.forEach(function(type) {
|
||||||
beestat.cache.set('data.comparison_scores_' + type, data[type]);
|
beestat.cache.set('data.comparison_scores_' + type, data['score_' + type]);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (callback !== undefined) {
|
if (callback !== undefined) {
|
||||||
@ -56,7 +67,7 @@ beestat.home_comparisons.get_comparison_scores = function(callback) {
|
|||||||
*
|
*
|
||||||
* @return {Object} The comparison attributes.
|
* @return {Object} The comparison attributes.
|
||||||
*/
|
*/
|
||||||
beestat.home_comparisons.get_comparison_attributes = function(type) {
|
beestat.comparisons.get_comparison_attributes = function(type) {
|
||||||
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
||||||
var thermostat_group =
|
var thermostat_group =
|
||||||
beestat.cache.thermostat_group[thermostat.thermostat_group_id];
|
beestat.cache.thermostat_group[thermostat.thermostat_group_id];
|
@ -298,3 +298,34 @@ beestat.series.indoor_resist_delta = {
|
|||||||
'color': beestat.style.color.gray.dark
|
'color': beestat.style.color.gray.dark
|
||||||
};
|
};
|
||||||
beestat.series.indoor_resist_delta_raw = beestat.series.indoor_resist_delta;
|
beestat.series.indoor_resist_delta_raw = beestat.series.indoor_resist_delta;
|
||||||
|
|
||||||
|
// Temperature Profiles New
|
||||||
|
beestat.series.indoor_heat_1_delta = {
|
||||||
|
'name': 'Indoor Heat 1 Δ',
|
||||||
|
'color': beestat.series.compressor_heat_1.color
|
||||||
|
};
|
||||||
|
beestat.series.indoor_heat_1_delta_raw = beestat.series.indoor_heat_1_delta;
|
||||||
|
|
||||||
|
beestat.series.indoor_heat_2_delta = {
|
||||||
|
'name': 'Indoor Heat 2 Δ',
|
||||||
|
'color': beestat.series.compressor_heat_2.color
|
||||||
|
};
|
||||||
|
beestat.series.indoor_heat_2_delta_raw = beestat.series.indoor_heat_2_delta;
|
||||||
|
|
||||||
|
beestat.series.indoor_cool_1_delta = {
|
||||||
|
'name': 'Indoor Cool 1 Δ',
|
||||||
|
'color': beestat.series.compressor_cool_1.color
|
||||||
|
};
|
||||||
|
beestat.series.indoor_cool_1_delta_raw = beestat.series.indoor_cool_1_delta;
|
||||||
|
|
||||||
|
beestat.series.indoor_cool_2_delta = {
|
||||||
|
'name': 'Indoor Cool 2 Δ',
|
||||||
|
'color': beestat.series.compressor_cool_2.color
|
||||||
|
};
|
||||||
|
beestat.series.indoor_cool_2_delta_raw = beestat.series.indoor_cool_2_delta;
|
||||||
|
|
||||||
|
beestat.series.indoor_resist_delta = {
|
||||||
|
'name': 'Indoor Δ',
|
||||||
|
'color': beestat.style.color.gray.dark
|
||||||
|
};
|
||||||
|
beestat.series.indoor_resist_delta_raw = beestat.series.indoor_resist_delta;
|
||||||
|
@ -32,8 +32,7 @@ beestat.user.has_early_access = function() {
|
|||||||
return user.user_id === 1 ||
|
return user.user_id === 1 ||
|
||||||
(
|
(
|
||||||
user.patreon_status !== null &&
|
user.patreon_status !== null &&
|
||||||
user.patreon_status.patron_status === 'active_patron' &&
|
user.patreon_status.patron_status === 'active_patron'
|
||||||
user.patreon_status.currently_entitled_amount_cents >= 500
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* Possible issue with your comparison.
|
|
||||||
*/
|
|
||||||
beestat.component.card.comparison_issue = function() {
|
|
||||||
beestat.component.card.apply(this, arguments);
|
|
||||||
};
|
|
||||||
beestat.extend(beestat.component.card.comparison_issue, beestat.component.card);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorate
|
|
||||||
*
|
|
||||||
* @param {rocket.Elements} parent
|
|
||||||
*/
|
|
||||||
beestat.component.card.comparison_issue.prototype.decorate_contents_ = function(parent) {
|
|
||||||
parent.style('background', beestat.style.color.red.dark);
|
|
||||||
parent.appendChild($.createElement('p').innerText('Notice how one or more of the lines below slopes down or is very flat? The expectation is that these slope upwards. This may affect the accuracy of your scores.'));
|
|
||||||
parent.appendChild($.createElement('p').innerText('I\'ll be investigating these situations and improving the algorithm as much as possible to provide as accurate results as I can. Thank you!'));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the title of the card.
|
|
||||||
*
|
|
||||||
* @return {string} The title of the card.
|
|
||||||
*/
|
|
||||||
beestat.component.card.comparison_issue.prototype.get_title_ = function() {
|
|
||||||
return 'Possible issue with your temperature profiles!';
|
|
||||||
};
|
|
||||||
|
|
@ -51,24 +51,24 @@ beestat.component.card.comparison_settings.prototype.decorate_contents_ = functi
|
|||||||
* If the data is available, then get the data if we don't already have it
|
* If the data is available, then get the data if we don't already have it
|
||||||
* loaded. If the data is not available, poll until it becomes available.
|
* loaded. If the data is not available, poll until it becomes available.
|
||||||
*/
|
*/
|
||||||
if (thermostat_group.temperature_profile === null) {
|
if (thermostat_group.profile === null) {
|
||||||
// This will show the loading screen.
|
// This will show the loading screen.
|
||||||
self.data_available_();
|
self.data_available_();
|
||||||
|
|
||||||
var poll_interval = 10000;
|
var poll_interval = 10000;
|
||||||
|
|
||||||
beestat.add_poll_interval(poll_interval);
|
beestat.add_poll_interval(poll_interval);
|
||||||
beestat.dispatcher.addEventListener('poll.home_comparisons_load', function() {
|
beestat.dispatcher.addEventListener('poll.comparisons_load', function() {
|
||||||
if (self.data_available_() === true) {
|
if (self.data_available_() === true) {
|
||||||
beestat.remove_poll_interval(poll_interval);
|
beestat.remove_poll_interval(poll_interval);
|
||||||
beestat.dispatcher.removeEventListener('poll.home_comparisons_load');
|
beestat.dispatcher.removeEventListener('poll.comparisons_load');
|
||||||
|
|
||||||
new beestat.api()
|
new beestat.api()
|
||||||
.add_call(
|
.add_call(
|
||||||
'thermostat_group',
|
'thermostat_group',
|
||||||
'generate_temperature_profiles',
|
'generate_profiles',
|
||||||
{},
|
{},
|
||||||
'generate_temperature_profiles'
|
'generate_profiles'
|
||||||
)
|
)
|
||||||
.add_call(
|
.add_call(
|
||||||
'thermostat_group',
|
'thermostat_group',
|
||||||
@ -78,7 +78,7 @@ beestat.component.card.comparison_settings.prototype.decorate_contents_ = functi
|
|||||||
)
|
)
|
||||||
.set_callback(function(response) {
|
.set_callback(function(response) {
|
||||||
beestat.cache.set('thermostat_group', response.thermostat_group);
|
beestat.cache.set('thermostat_group', response.thermostat_group);
|
||||||
(new beestat.layer.home_comparisons()).render();
|
(new beestat.layer.comparisons()).render();
|
||||||
})
|
})
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ beestat.component.card.comparison_settings.prototype.decorate_region_ = function
|
|||||||
// Open up the loading window.
|
// Open up the loading window.
|
||||||
self.show_loading_('Calculating Score for ' + region + ' region');
|
self.show_loading_('Calculating Score for ' + region + ' region');
|
||||||
|
|
||||||
beestat.home_comparisons.get_comparison_scores(function() {
|
beestat.comparisons.get_comparison_scores(function() {
|
||||||
// Rerender to get rid of the loader.
|
// Rerender to get rid of the loader.
|
||||||
self.rerender();
|
self.rerender();
|
||||||
});
|
});
|
||||||
@ -200,7 +200,7 @@ beestat.component.card.comparison_settings.prototype.decorate_property_ = functi
|
|||||||
// Open up the loading window.
|
// Open up the loading window.
|
||||||
self.show_loading_('Calculating Score for ' + property_type.text);
|
self.show_loading_('Calculating Score for ' + property_type.text);
|
||||||
|
|
||||||
beestat.home_comparisons.get_comparison_scores(function() {
|
beestat.comparisons.get_comparison_scores(function() {
|
||||||
// Rerender to get rid of the loader.
|
// Rerender to get rid of the loader.
|
||||||
self.rerender();
|
self.rerender();
|
||||||
});
|
});
|
||||||
|
27
js/component/card/early_access.js
Normal file
27
js/component/card/early_access.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Early access
|
||||||
|
*/
|
||||||
|
beestat.component.card.early_access = function() {
|
||||||
|
beestat.component.card.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.card.early_access, beestat.component.card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
beestat.component.card.early_access.prototype.decorate_contents_ = function(parent) {
|
||||||
|
parent.style('background', beestat.style.color.green.base);
|
||||||
|
parent.appendChild($.createElement('p').innerText('Experimental early access features below! ⤵'));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of the card.
|
||||||
|
*
|
||||||
|
* @return {string} The title of the card.
|
||||||
|
*/
|
||||||
|
// beestat.component.card.early_access.prototype.get_title_ = function() {
|
||||||
|
// return 'Possible issue with your temperature profiles!';
|
||||||
|
// };
|
||||||
|
|
84
js/component/card/metrics.js
Normal file
84
js/component/card/metrics.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* Metrics card.
|
||||||
|
*/
|
||||||
|
beestat.component.card.metrics = function(thermostat_group_id) {
|
||||||
|
this.thermostat_group_id_ = thermostat_group_id;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debounce so that multiple setting changes don't re-trigger the same
|
||||||
|
* event. This fires on the trailing edge so that all changes are accounted
|
||||||
|
* for when rerendering.
|
||||||
|
*/
|
||||||
|
var data_change_function = beestat.debounce(function() {
|
||||||
|
self.rerender();
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
beestat.dispatcher.addEventListener(
|
||||||
|
'cache.data.metrics',
|
||||||
|
data_change_function
|
||||||
|
);
|
||||||
|
|
||||||
|
beestat.component.card.apply(this, arguments);
|
||||||
|
|
||||||
|
// this.layer_.register_loader(beestat.comparisons.get_comparison_metricss);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.card.metrics, beestat.component.card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
beestat.component.card.metrics.prototype.decorate_contents_ = function(parent) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var metrics = [
|
||||||
|
'setpoint_heat',
|
||||||
|
'setpoint_cool',
|
||||||
|
// 'runtime_per_heating_degree_day'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Decorate the metrics
|
||||||
|
var metric_container = $.createElement('div')
|
||||||
|
.style({
|
||||||
|
'display': 'grid',
|
||||||
|
// 'grid-template-columns': 'repeat(auto-fit, minmax(160px, 1fr))',
|
||||||
|
'grid-template-columns': '1fr 1fr 1fr',
|
||||||
|
'margin': '0 0 ' + beestat.style.size.gutter + 'px -' + beestat.style.size.gutter + 'px'
|
||||||
|
});
|
||||||
|
parent.appendChild(metric_container);
|
||||||
|
|
||||||
|
metrics.forEach(function(metric) {
|
||||||
|
var div = $.createElement('div')
|
||||||
|
.style({
|
||||||
|
'padding': beestat.style.size.gutter + 'px 0 0 ' + beestat.style.size.gutter + 'px'
|
||||||
|
});
|
||||||
|
metric_container.appendChild(div);
|
||||||
|
|
||||||
|
(new beestat.component.metric[metric](self.thermostat_group_id_)).render(div);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of the card.
|
||||||
|
*
|
||||||
|
* @return {string} The title of the card.
|
||||||
|
*/
|
||||||
|
beestat.component.card.metrics.prototype.get_title_ = function() {
|
||||||
|
return 'Metrics';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate the menu.
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
/*beestat.component.card.my_home.prototype.decorate_top_right_ = function(parent) {
|
||||||
|
|
||||||
|
};*/
|
@ -20,7 +20,7 @@ beestat.component.card.score = function() {
|
|||||||
|
|
||||||
beestat.component.card.apply(this, arguments);
|
beestat.component.card.apply(this, arguments);
|
||||||
|
|
||||||
this.layer_.register_loader(beestat.home_comparisons.get_comparison_scores);
|
this.layer_.register_loader(beestat.comparisons.get_comparison_scores);
|
||||||
};
|
};
|
||||||
beestat.extend(beestat.component.card.score, beestat.component.card);
|
beestat.extend(beestat.component.card.score, beestat.component.card);
|
||||||
|
|
||||||
|
237
js/component/card/temperature_profiles_new.js
Normal file
237
js/component/card/temperature_profiles_new.js
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/**
|
||||||
|
* Temperature profiles.
|
||||||
|
*
|
||||||
|
* @param {number} thermostat_group_id The thermostat_group_id this card is
|
||||||
|
* displaying data for.
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new = function(thermostat_group_id) {
|
||||||
|
this.thermostat_group_id_ = thermostat_group_id;
|
||||||
|
|
||||||
|
beestat.component.card.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.card.temperature_profiles_new, beestat.component.card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate card.
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.decorate_contents_ = function(parent) {
|
||||||
|
var data = this.get_data_();
|
||||||
|
this.chart_ = new beestat.component.chart.temperature_profiles_new(data);
|
||||||
|
this.chart_.render(parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the series data.
|
||||||
|
*
|
||||||
|
* @return {object} The series data.
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.get_data_ = function() {
|
||||||
|
var thermostat_group = beestat.cache.thermostat_group[
|
||||||
|
this.thermostat_group_id_
|
||||||
|
];
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
'x': [],
|
||||||
|
'series': {},
|
||||||
|
'metadata': {
|
||||||
|
'series': {},
|
||||||
|
'chart': {
|
||||||
|
'title': this.get_title_(),
|
||||||
|
'subtitle': this.get_subtitle_(),
|
||||||
|
'outdoor_temperature': beestat.temperature({
|
||||||
|
'temperature': (thermostat_group.weather.temperature / 10),
|
||||||
|
'round': 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
thermostat_group.profile === null
|
||||||
|
) {
|
||||||
|
this.chart_.render(parent);
|
||||||
|
this.show_loading_('Calculating');
|
||||||
|
} else {
|
||||||
|
// Global x range.
|
||||||
|
var x_min = Infinity;
|
||||||
|
var x_max = -Infinity;
|
||||||
|
|
||||||
|
var y_min = Infinity;
|
||||||
|
var y_max = -Infinity;
|
||||||
|
for (var type in thermostat_group.profile.temperature) {
|
||||||
|
// Cloned because I mutate this data for temperature conversions.
|
||||||
|
var profile = beestat.clone(
|
||||||
|
thermostat_group.profile.temperature[type]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (profile !== null) {
|
||||||
|
// Convert the data to Celsius if necessary
|
||||||
|
var deltas_converted = {};
|
||||||
|
for (var key in profile.deltas) {
|
||||||
|
deltas_converted[beestat.temperature({'temperature': key})] =
|
||||||
|
beestat.temperature({
|
||||||
|
'temperature': (profile.deltas[key]),
|
||||||
|
'delta': true,
|
||||||
|
'round': 3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
profile.deltas = deltas_converted;
|
||||||
|
var linear_trendline = this.get_linear_trendline_(profile.deltas);
|
||||||
|
|
||||||
|
var min_max_keys = Object.keys(profile.deltas);
|
||||||
|
|
||||||
|
// 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] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data is stored internally as °F with 1 value per degree. That data
|
||||||
|
* gets converted to °C which then requires additional precision
|
||||||
|
* (increment).
|
||||||
|
*
|
||||||
|
* The additional precision introduces floating point error, so
|
||||||
|
* convert the x value to a fixed string.
|
||||||
|
*
|
||||||
|
* The string then needs converted to a number for highcharts, so
|
||||||
|
* later on use parseFloat to get back to that.
|
||||||
|
*
|
||||||
|
* Stupid Celsius.
|
||||||
|
*/
|
||||||
|
var increment;
|
||||||
|
var fixed;
|
||||||
|
if (beestat.setting('temperature_unit') === '°F') {
|
||||||
|
increment = 1;
|
||||||
|
fixed = 0;
|
||||||
|
} else {
|
||||||
|
increment = 0.1;
|
||||||
|
fixed = 1;
|
||||||
|
}
|
||||||
|
for (var x = this_x_min; x <= this_x_max; x += increment) {
|
||||||
|
var x_fixed = x.toFixed(fixed);
|
||||||
|
var y = (linear_trendline.slope * x_fixed) +
|
||||||
|
linear_trendline.intercept;
|
||||||
|
|
||||||
|
data.series['trendline_' + type].push([
|
||||||
|
parseFloat(x_fixed),
|
||||||
|
y
|
||||||
|
]);
|
||||||
|
if (profile.deltas[x_fixed] !== undefined) {
|
||||||
|
data.series['raw_' + type].push([
|
||||||
|
parseFloat(x_fixed),
|
||||||
|
profile.deltas[x_fixed]
|
||||||
|
]);
|
||||||
|
y_min = Math.min(y_min, profile.deltas[x_fixed]);
|
||||||
|
y_max = Math.max(y_max, profile.deltas[x_fixed]);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.metadata.chart.y_min = y_min;
|
||||||
|
data.metadata.chart.y_max = y_max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a linear trendline from a set of data.
|
||||||
|
*
|
||||||
|
* @param {Object} data The data; at least two points required.
|
||||||
|
*
|
||||||
|
* @return {Object} The slope and intercept of the trendline.
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.get_linear_trendline_ = function(data) {
|
||||||
|
// Requires at least two points.
|
||||||
|
if (Object.keys(data).length < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum_x = 0;
|
||||||
|
var sum_y = 0;
|
||||||
|
var sum_xy = 0;
|
||||||
|
var sum_x_squared = 0;
|
||||||
|
var n = 0;
|
||||||
|
|
||||||
|
for (var x in data) {
|
||||||
|
x = parseFloat(x);
|
||||||
|
var y = parseFloat(data[x]);
|
||||||
|
|
||||||
|
sum_x += x;
|
||||||
|
sum_y += y;
|
||||||
|
sum_xy += (x * y);
|
||||||
|
sum_x_squared += Math.pow(x, 2);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var slope = ((n * sum_xy) - (sum_x * sum_y)) /
|
||||||
|
((n * sum_x_squared) - (Math.pow(sum_x, 2)));
|
||||||
|
var intercept = ((sum_y) - (slope * sum_x)) / (n);
|
||||||
|
|
||||||
|
return {
|
||||||
|
'slope': slope,
|
||||||
|
'intercept': intercept
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of the card.
|
||||||
|
*
|
||||||
|
* @return {string} The title.
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.get_title_ = function() {
|
||||||
|
return 'Temperature Profiles';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the subtitle of the card.
|
||||||
|
*
|
||||||
|
* @return {string} The subtitle.
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.get_subtitle_ = function() {
|
||||||
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
||||||
|
var thermostat_group = beestat.cache.thermostat_group[
|
||||||
|
thermostat.thermostat_group_id
|
||||||
|
];
|
||||||
|
|
||||||
|
var generated_at_m = moment(
|
||||||
|
thermostat_group.profile.metadata.generated_at
|
||||||
|
);
|
||||||
|
|
||||||
|
return 'Generated ' + generated_at_m.format('MMM Do @ h a') + ' (updated weekly)';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate the menu.
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
beestat.component.card.temperature_profiles_new.prototype.decorate_top_right_ = function(parent) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
var menu = (new beestat.component.menu()).render(parent);
|
||||||
|
|
||||||
|
menu.add_menu_item(new beestat.component.menu_item()
|
||||||
|
.set_text('Download Chart')
|
||||||
|
.set_icon('download')
|
||||||
|
.set_callback(function() {
|
||||||
|
self.chart_.export();
|
||||||
|
}));
|
||||||
|
|
||||||
|
menu.add_menu_item(new beestat.component.menu_item()
|
||||||
|
.set_text('Help')
|
||||||
|
.set_icon('help_circle')
|
||||||
|
.set_callback(function() {
|
||||||
|
window.open('https://doc.beestat.io/9c0fba6793dd4bc68f798c1516f0ea25');
|
||||||
|
}));
|
||||||
|
};
|
346
js/component/chart/temperature_profiles_new.js
Normal file
346
js/component/chart/temperature_profiles_new.js
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
/**
|
||||||
|
* Temperature profiles chart.
|
||||||
|
*
|
||||||
|
* @param {object} data The chart data.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new = function(data) {
|
||||||
|
this.data_ = data;
|
||||||
|
|
||||||
|
beestat.component.chart.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.chart.temperature_profiles_new, beestat.component.chart);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_xAxis_labels_formatter_.
|
||||||
|
*
|
||||||
|
* @return {Function} xAxis labels formatter.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_xAxis_labels_formatter_ = function() {
|
||||||
|
return function() {
|
||||||
|
return this.value + beestat.setting('temperature_unit');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_series_.
|
||||||
|
*
|
||||||
|
* @return {Array} All of the series to display on the chart.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_series_ = function() {
|
||||||
|
var series = [];
|
||||||
|
|
||||||
|
// Trendline data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.trendline_heat_1,
|
||||||
|
'name': 'indoor_heat_1_delta',
|
||||||
|
'color': beestat.series.indoor_heat_1_delta.color,
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'line',
|
||||||
|
'lineWidth': 2,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trendline data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.trendline_heat_2,
|
||||||
|
'name': 'indoor_heat_2_delta',
|
||||||
|
'color': beestat.series.indoor_heat_2_delta.color,
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'line',
|
||||||
|
'lineWidth': 2,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trendline data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.trendline_cool_1,
|
||||||
|
'name': 'indoor_cool_1_delta',
|
||||||
|
'color': beestat.series.indoor_cool_1_delta.color,
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'line',
|
||||||
|
'lineWidth': 2,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trendline data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.trendline_cool_2,
|
||||||
|
'name': 'indoor_cool_2_delta',
|
||||||
|
'color': beestat.series.indoor_cool_2_delta.color,
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'line',
|
||||||
|
'lineWidth': 2,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trendline data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.trendline_resist,
|
||||||
|
'name': 'indoor_resist_delta',
|
||||||
|
'color': beestat.series.indoor_resist_delta.color,
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'line',
|
||||||
|
'lineWidth': 2,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Raw data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.raw_heat_1,
|
||||||
|
'name': 'indoor_heat_1_delta_raw',
|
||||||
|
'color': beestat.series.indoor_heat_1_delta_raw.color,
|
||||||
|
'dashStyle': 'ShortDot',
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'spline',
|
||||||
|
'lineWidth': 1,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Raw data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.raw_heat_2,
|
||||||
|
'name': 'indoor_heat_2_delta_raw',
|
||||||
|
'color': beestat.series.indoor_heat_2_delta_raw.color,
|
||||||
|
'dashStyle': 'ShortDot',
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'spline',
|
||||||
|
'lineWidth': 1,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Raw data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.raw_cool_1,
|
||||||
|
'name': 'indoor_cool_1_delta_raw',
|
||||||
|
'color': beestat.series.indoor_cool_1_delta_raw.color,
|
||||||
|
'dashStyle': 'ShortDot',
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'spline',
|
||||||
|
'lineWidth': 1,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Raw data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.raw_cool_2,
|
||||||
|
'name': 'indoor_cool_2_delta_raw',
|
||||||
|
'color': beestat.series.indoor_cool_2_delta_raw.color,
|
||||||
|
'dashStyle': 'ShortDot',
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'spline',
|
||||||
|
'lineWidth': 1,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Raw data
|
||||||
|
series.push({
|
||||||
|
'data': this.data_.series.raw_resist,
|
||||||
|
'name': 'indoor_resist_delta_raw',
|
||||||
|
'color': beestat.series.indoor_resist_delta_raw.color,
|
||||||
|
'dashStyle': 'ShortDot',
|
||||||
|
'marker': {
|
||||||
|
'enabled': false,
|
||||||
|
'states': {'hover': {'enabled': false}}
|
||||||
|
},
|
||||||
|
'type': 'spline',
|
||||||
|
'lineWidth': 1,
|
||||||
|
'states': {'hover': {'lineWidthPlus': 0}}
|
||||||
|
});
|
||||||
|
|
||||||
|
return series;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_yAxis_.
|
||||||
|
*
|
||||||
|
* @return {Array} The y-axis options.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_yAxis_ = function() {
|
||||||
|
var absolute_y_max = Math.max(
|
||||||
|
Math.abs(this.data_.metadata.chart.y_min),
|
||||||
|
Math.abs(this.data_.metadata.chart.y_max)
|
||||||
|
);
|
||||||
|
|
||||||
|
var y_min = absolute_y_max * -1;
|
||||||
|
var y_max = absolute_y_max;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'alignTicks': false,
|
||||||
|
'gridLineColor': beestat.style.color.bluegray.light,
|
||||||
|
'gridLineDashStyle': 'longdash',
|
||||||
|
'title': {'text': null},
|
||||||
|
'labels': {
|
||||||
|
'style': {'color': beestat.style.color.gray.base},
|
||||||
|
'formatter': function() {
|
||||||
|
return this.value + beestat.setting('temperature_unit');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'min': y_min,
|
||||||
|
'max': y_max,
|
||||||
|
'plotLines': [
|
||||||
|
{
|
||||||
|
'color': beestat.style.color.bluegray.light,
|
||||||
|
'dashStyle': 'solid',
|
||||||
|
'width': 3,
|
||||||
|
'value': 0,
|
||||||
|
'zIndex': 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_tooltip_formatter_.
|
||||||
|
*
|
||||||
|
* @return {Function} The tooltip formatter.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_tooltip_formatter_ = function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
var sections = [];
|
||||||
|
var section = [];
|
||||||
|
this.points.forEach(function(point) {
|
||||||
|
var series = point.series;
|
||||||
|
|
||||||
|
var value = beestat.temperature({
|
||||||
|
'temperature': point.y,
|
||||||
|
'units': true,
|
||||||
|
'convert': false,
|
||||||
|
'delta': true,
|
||||||
|
'type': 'string'
|
||||||
|
}) + ' / h';
|
||||||
|
|
||||||
|
if (series.name.indexOf('raw') === -1) {
|
||||||
|
section.push({
|
||||||
|
'label': beestat.series[series.name].name,
|
||||||
|
'value': value,
|
||||||
|
'color': series.color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sections.push(section);
|
||||||
|
|
||||||
|
return self.tooltip_formatter_helper_(
|
||||||
|
'Outdoor Temp: ' +
|
||||||
|
beestat.temperature({
|
||||||
|
'temperature': this.x,
|
||||||
|
'round': 0,
|
||||||
|
'units': true,
|
||||||
|
'convert': false
|
||||||
|
}),
|
||||||
|
sections
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_chart_zoomType_.
|
||||||
|
*
|
||||||
|
* @return {string} The zoom type.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_chart_zoomType_ = function() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_legend_.
|
||||||
|
*
|
||||||
|
* @return {object} The legend options.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_legend_ = function() {
|
||||||
|
return {
|
||||||
|
'enabled': false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_xAxis_.
|
||||||
|
*
|
||||||
|
* @return {object} The xAxis options.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_xAxis_ = function() {
|
||||||
|
return {
|
||||||
|
'lineWidth': 0,
|
||||||
|
'tickLength': 0,
|
||||||
|
'tickInterval': 5,
|
||||||
|
'gridLineWidth': 1,
|
||||||
|
'gridLineColor': beestat.style.color.bluegray.light,
|
||||||
|
'gridLineDashStyle': 'longdash',
|
||||||
|
'labels': {
|
||||||
|
'style': {
|
||||||
|
'color': beestat.style.color.gray.base
|
||||||
|
},
|
||||||
|
'formatter': this.get_options_xAxis_labels_formatter_()
|
||||||
|
},
|
||||||
|
'crosshair': this.get_options_xAxis_crosshair_(),
|
||||||
|
'plotLines': [
|
||||||
|
{
|
||||||
|
'color': beestat.series.outdoor_temperature.color,
|
||||||
|
'dashStyle': 'ShortDash',
|
||||||
|
'width': 1,
|
||||||
|
'label': {
|
||||||
|
'style': {
|
||||||
|
'color': beestat.series.outdoor_temperature.color
|
||||||
|
},
|
||||||
|
'useHTML': true,
|
||||||
|
'text': 'Now: ' + beestat.temperature({
|
||||||
|
'temperature': this.data_.metadata.chart.outdoor_temperature,
|
||||||
|
'convert': false,
|
||||||
|
'units': true,
|
||||||
|
'round': 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
'value': this.data_.metadata.chart.outdoor_temperature,
|
||||||
|
'zIndex': 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_chart_height_.
|
||||||
|
*
|
||||||
|
* @return {number} The height of the chart.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_chart_height_ = function() {
|
||||||
|
return 300;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for get_options_plotOptions_series_connectNulls_.
|
||||||
|
*
|
||||||
|
* @return {boolean} Whether or not to connect nulls.
|
||||||
|
*/
|
||||||
|
beestat.component.chart.temperature_profiles_new.prototype.get_options_plotOptions_series_connectNulls_ = function() {
|
||||||
|
return true;
|
||||||
|
};
|
@ -38,7 +38,7 @@ beestat.component.header.prototype.decorate_ = function(parent) {
|
|||||||
'icon': 'signal_variant'
|
'icon': 'signal_variant'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'layer': 'home_comparisons',
|
'layer': 'comparisons',
|
||||||
'text': 'Comparisons',
|
'text': 'Comparisons',
|
||||||
'icon': 'home_group'
|
'icon': 'home_group'
|
||||||
}
|
}
|
||||||
|
137
js/component/metric.js
Normal file
137
js/component/metric.js
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/**
|
||||||
|
* Generic customizable metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric = function() {
|
||||||
|
beestat.component.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.metric, beestat.component);
|
||||||
|
|
||||||
|
beestat.component.metric.prototype.rerender_on_breakpoint_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate
|
||||||
|
*
|
||||||
|
* @param {rocket.Elements} parent
|
||||||
|
*/
|
||||||
|
beestat.component.metric.prototype.decorate_ = function(parent) {
|
||||||
|
if (beestat.cache.data.metrics === undefined) { // todo
|
||||||
|
parent.appendChild($.createElement('div').innerText('Loading...'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var outer_container = $.createElement('div').style({
|
||||||
|
'background': beestat.style.color.bluegray.dark,
|
||||||
|
'padding': (beestat.style.size.gutter / 2)
|
||||||
|
});
|
||||||
|
|
||||||
|
outer_container.appendChild(
|
||||||
|
$.createElement('div').innerText(this.get_title_())
|
||||||
|
);
|
||||||
|
|
||||||
|
var inner_container = $.createElement('div').style({
|
||||||
|
'position': 'relative',
|
||||||
|
'margin-top': '50px',
|
||||||
|
'margin-bottom': '20px',
|
||||||
|
'margin-left': '25px'
|
||||||
|
});
|
||||||
|
|
||||||
|
var icon = $.createElement('div').style({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '-12px',
|
||||||
|
'left': '-28px'
|
||||||
|
});
|
||||||
|
|
||||||
|
(new beestat.component.icon(this.get_icon_()))
|
||||||
|
.set_color(this.get_color_())
|
||||||
|
.render(icon);
|
||||||
|
|
||||||
|
var line = $.createElement('div').style({
|
||||||
|
'background': this.get_color_(),
|
||||||
|
'height': '5px',
|
||||||
|
'border-radius': '5px'
|
||||||
|
});
|
||||||
|
|
||||||
|
var min = $.createElement('div')
|
||||||
|
.innerText(this.get_min_(true))
|
||||||
|
.style({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '10px',
|
||||||
|
'left': '0px'
|
||||||
|
});
|
||||||
|
|
||||||
|
var max = $.createElement('div')
|
||||||
|
.innerText(this.get_max_(true))
|
||||||
|
.style({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '10px',
|
||||||
|
'right': '0px'
|
||||||
|
});
|
||||||
|
|
||||||
|
var label = $.createElement('div')
|
||||||
|
.innerText(this.get_value_())
|
||||||
|
.style({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '-25px',
|
||||||
|
'left': this.get_marker_position_() + '%',
|
||||||
|
'width': '100px',
|
||||||
|
'text-align': 'center',
|
||||||
|
'margin-left': '-50px',
|
||||||
|
'font-weight': beestat.style.font_weight.bold
|
||||||
|
});
|
||||||
|
|
||||||
|
var circle = $.createElement('div').style({
|
||||||
|
'background': this.get_color_(),
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '-4px',
|
||||||
|
'left': this.get_marker_position_() + '%',
|
||||||
|
'margin-left': '-7px',
|
||||||
|
'width': '14px',
|
||||||
|
'height': '14px',
|
||||||
|
'border-radius': '50%'
|
||||||
|
});
|
||||||
|
|
||||||
|
var chart = $.createElement('div').style({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '-40px',
|
||||||
|
'left': '0px',
|
||||||
|
'width': '100%',
|
||||||
|
'height': '40px'
|
||||||
|
});
|
||||||
|
|
||||||
|
var histogram = this.get_histogram_();
|
||||||
|
var histogram_max = this.get_histogram_max_();
|
||||||
|
var column_width = (100 / histogram.length) + '%';
|
||||||
|
histogram.forEach(function(data) {
|
||||||
|
var column = $.createElement('div').style({
|
||||||
|
'display': 'inline-block',
|
||||||
|
'background': 'rgba(255, 255, 255, 0.1)',
|
||||||
|
'width': column_width,
|
||||||
|
'height': (data.count / histogram_max * 100) + '%'
|
||||||
|
});
|
||||||
|
chart.appendChild(column);
|
||||||
|
});
|
||||||
|
|
||||||
|
inner_container.appendChild(icon);
|
||||||
|
inner_container.appendChild(line);
|
||||||
|
inner_container.appendChild(min);
|
||||||
|
inner_container.appendChild(max);
|
||||||
|
inner_container.appendChild(label);
|
||||||
|
inner_container.appendChild(circle);
|
||||||
|
inner_container.appendChild(chart);
|
||||||
|
|
||||||
|
outer_container.appendChild(inner_container);
|
||||||
|
|
||||||
|
parent.appendChild(outer_container);
|
||||||
|
};
|
||||||
|
|
||||||
|
beestat.component.metric.prototype.get_marker_position_ = function() {
|
||||||
|
return 100 * (this.get_value_() - this.get_min_()) / (this.get_max_() - this.get_min_());
|
||||||
|
};
|
||||||
|
|
||||||
|
beestat.component.metric.prototype.get_histogram_max_ = function() {
|
||||||
|
var max = -Infinity;
|
||||||
|
this.get_histogram_().forEach(function(data) {
|
||||||
|
max = Math.max(max, data.count);
|
||||||
|
});
|
||||||
|
return max;
|
||||||
|
};
|
98
js/component/metric/runtime_per_heating_degree_day.js
Normal file
98
js/component/metric/runtime_per_heating_degree_day.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* Runtime per heating degree day metric.
|
||||||
|
*
|
||||||
|
* @param {number} thermostat_group_id The thermostat group.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day = function(thermostat_group_id) {
|
||||||
|
this.thermostat_group_id_ = thermostat_group_id;
|
||||||
|
|
||||||
|
beestat.component.metric.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.metric.runtime_per_heating_degree_day, beestat.component.metric);
|
||||||
|
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.rerender_on_breakpoint_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The title of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_title_ = function() {
|
||||||
|
return 'Runtime / HDD';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the icon of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The icon of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_icon_ = function() {
|
||||||
|
return 'fire';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the color of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The color of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_color_ = function() {
|
||||||
|
return beestat.series.compressor_heat_1.color;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @return {mixed} The minimum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_min_ = function() {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.runtime_per_heating_degree_day.standard_deviation;
|
||||||
|
return (beestat.cache.data.metrics.runtime_per_heating_degree_day.median - (standard_deviation * 2)).toFixed(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @return {mixed} The maximum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_max_ = function() {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.runtime_per_heating_degree_day.standard_deviation;
|
||||||
|
return (beestat.cache.data.metrics.runtime_per_heating_degree_day.median + (standard_deviation * 2)).toFixed(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of this metric.
|
||||||
|
*
|
||||||
|
* @return {mixed} The value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_value_ = function() {
|
||||||
|
var thermostat_group = beestat.cache.thermostat_group[
|
||||||
|
this.thermostat_group_id_
|
||||||
|
];
|
||||||
|
// todo: store this explicitly on the profile so it doesn't have to be calculated in JS?
|
||||||
|
return (thermostat_group.profile.runtime.heat_1 /
|
||||||
|
thermostat_group.profile.degree_days.heat).toFixed(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a histogram between the min and max values of this metric.
|
||||||
|
*
|
||||||
|
* @return {array} The histogram.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.runtime_per_heating_degree_day.prototype.get_histogram_ = function() {
|
||||||
|
var histogram = [];
|
||||||
|
for (var value in beestat.cache.data.metrics.runtime_per_heating_degree_day.histogram) {
|
||||||
|
if (
|
||||||
|
value >= this.get_min_() &&
|
||||||
|
value <= this.get_max_()
|
||||||
|
) {
|
||||||
|
var count = beestat.cache.data.metrics.runtime_per_heating_degree_day.histogram[value];
|
||||||
|
histogram.push({
|
||||||
|
'value': value,
|
||||||
|
'count': count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return histogram;
|
||||||
|
};
|
119
js/component/metric/setpoint_cool.js
Normal file
119
js/component/metric/setpoint_cool.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Cool setpoint metric.
|
||||||
|
*
|
||||||
|
* @param {number} thermostat_group_id The thermostat group.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool = function(thermostat_group_id) {
|
||||||
|
this.thermostat_group_id_ = thermostat_group_id;
|
||||||
|
|
||||||
|
beestat.component.metric.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.metric.setpoint_cool, beestat.component.metric);
|
||||||
|
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.rerender_on_breakpoint_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The title of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_title_ = function() {
|
||||||
|
return 'Cool Setpoint';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the icon of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The icon of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_icon_ = function() {
|
||||||
|
return 'snowflake';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the color of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The color of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_color_ = function() {
|
||||||
|
return beestat.series.compressor_cool_1.color;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The minimum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_min_ = function(units) {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.setpoint_cool.standard_deviation;
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': beestat.cache.data.metrics.setpoint_cool.median - (standard_deviation * 2),
|
||||||
|
'round': 0,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The maximum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_max_ = function(units) {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.setpoint_cool.standard_deviation;
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': beestat.cache.data.metrics.setpoint_cool.median + (standard_deviation * 2),
|
||||||
|
'round': 0,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of this metric.
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_value_ = function(units) {
|
||||||
|
var thermostat_group = beestat.cache.thermostat_group[
|
||||||
|
this.thermostat_group_id_
|
||||||
|
];
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': thermostat_group.profile.setpoint.cool,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a histogram between the min and max values of this metric.
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {array} The histogram.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_cool.prototype.get_histogram_ = function(units) {
|
||||||
|
var histogram = [];
|
||||||
|
for (var temperature in beestat.cache.data.metrics.setpoint_cool.histogram) {
|
||||||
|
if (
|
||||||
|
temperature >= this.get_min_(units) &&
|
||||||
|
temperature <= this.get_max_(units)
|
||||||
|
) {
|
||||||
|
var count = beestat.cache.data.metrics.setpoint_cool.histogram[temperature];
|
||||||
|
histogram.push({
|
||||||
|
'value': beestat.temperature(temperature),
|
||||||
|
'count': count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return histogram;
|
||||||
|
};
|
119
js/component/metric/setpoint_heat.js
Normal file
119
js/component/metric/setpoint_heat.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Heat setpoint metric.
|
||||||
|
*
|
||||||
|
* @param {number} thermostat_group_id The thermostat group.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat = function(thermostat_group_id) {
|
||||||
|
this.thermostat_group_id_ = thermostat_group_id;
|
||||||
|
|
||||||
|
beestat.component.metric.apply(this, arguments);
|
||||||
|
};
|
||||||
|
beestat.extend(beestat.component.metric.setpoint_heat, beestat.component.metric);
|
||||||
|
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.rerender_on_breakpoint_ = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the title of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The title of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_title_ = function() {
|
||||||
|
return 'Heat Setpoint';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the icon of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The icon of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_icon_ = function() {
|
||||||
|
return 'fire';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the color of this metric.
|
||||||
|
*
|
||||||
|
* @return {string} The color of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_color_ = function() {
|
||||||
|
return beestat.series.compressor_heat_1.color;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The minimum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_min_ = function(units) {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.setpoint_heat.standard_deviation;
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': beestat.cache.data.metrics.setpoint_heat.median - (standard_deviation * 2),
|
||||||
|
'round': 0,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum value of this metric (within two standard deviations).
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The maximum value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_max_ = function(units) {
|
||||||
|
var standard_deviation =
|
||||||
|
beestat.cache.data.metrics.setpoint_heat.standard_deviation;
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': beestat.cache.data.metrics.setpoint_heat.median + (standard_deviation * 2),
|
||||||
|
'round': 0,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of this metric.
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {mixed} The value of this metric.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_value_ = function(units) {
|
||||||
|
var thermostat_group = beestat.cache.thermostat_group[
|
||||||
|
this.thermostat_group_id_
|
||||||
|
];
|
||||||
|
return beestat.temperature({
|
||||||
|
'temperature': thermostat_group.profile.setpoint.heat,
|
||||||
|
'units': units
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a histogram between the min and max values of this metric.
|
||||||
|
*
|
||||||
|
* @param {boolean} units Whether or not to return a numerical value or a
|
||||||
|
* string with units.
|
||||||
|
*
|
||||||
|
* @return {array} The histogram.
|
||||||
|
*/
|
||||||
|
beestat.component.metric.setpoint_heat.prototype.get_histogram_ = function(units) {
|
||||||
|
var histogram = [];
|
||||||
|
for (var temperature in beestat.cache.data.metrics.setpoint_heat.histogram) {
|
||||||
|
if (
|
||||||
|
temperature >= this.get_min_(units) &&
|
||||||
|
temperature <= this.get_max_(units)
|
||||||
|
) {
|
||||||
|
var count = beestat.cache.data.metrics.setpoint_heat.histogram[temperature];
|
||||||
|
histogram.push({
|
||||||
|
'value': beestat.temperature(temperature),
|
||||||
|
'count': count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return histogram;
|
||||||
|
};
|
@ -148,7 +148,7 @@ beestat.component.modal.change_system_type.prototype.get_buttons_ = function() {
|
|||||||
|
|
||||||
// Re-run comparison scores as they are invalid for the new system
|
// Re-run comparison scores as they are invalid for the new system
|
||||||
// type.
|
// type.
|
||||||
beestat.home_comparisons.get_comparison_scores();
|
beestat.comparisons.get_comparison_scores();
|
||||||
|
|
||||||
// Close the modal.
|
// Close the modal.
|
||||||
self.dispose();
|
self.dispose();
|
||||||
|
13
js/js.php
13
js/js.php
@ -27,7 +27,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
|||||||
echo '<script src="/js/beestat/time.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/time.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/setting.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/setting.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/poll.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/poll.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/home_comparisons.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/comparisons.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/highcharts.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/highcharts.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/get_sync_progress.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/get_sync_progress.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/beestat/user.js"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat/user.js"></script>' . PHP_EOL;
|
||||||
@ -40,7 +40,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
|||||||
echo '<script src="/js/layer.js"></script>' . PHP_EOL;
|
echo '<script src="/js/layer.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/layer/load.js"></script>' . PHP_EOL;
|
echo '<script src="/js/layer/load.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/layer/dashboard.js"></script>' . PHP_EOL;
|
echo '<script src="/js/layer/dashboard.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/layer/home_comparisons.js"></script>' . PHP_EOL;
|
echo '<script src="/js/layer/comparisons.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/layer/sensors.js"></script>' . PHP_EOL;
|
echo '<script src="/js/layer/sensors.js"></script>' . PHP_EOL;
|
||||||
|
|
||||||
// Component
|
// Component
|
||||||
@ -51,7 +51,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
|||||||
echo '<script src="/js/component/card/runtime_thermostat_summary.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/runtime_thermostat_summary.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/alerts.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/alerts.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/comparison_settings.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/comparison_settings.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/comparison_issue.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/early_access.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/demo.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/demo.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/footer.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/footer.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/my_home.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/my_home.js"></script>' . PHP_EOL;
|
||||||
@ -65,9 +65,12 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
|||||||
echo '<script src="/js/component/card/sensors.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/sensors.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/system.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/system.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/card/temperature_profiles.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/card/temperature_profiles.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/card/temperature_profiles_new.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/card/metrics.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart/runtime_thermostat_summary.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart/runtime_thermostat_summary.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart/temperature_profiles.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart/temperature_profiles.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/chart/temperature_profiles_new.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart/runtime_thermostat_detail_temperature.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart/runtime_thermostat_detail_temperature.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart/runtime_thermostat_detail_equipment.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart/runtime_thermostat_detail_equipment.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/chart/runtime_sensor_detail_temperature.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/chart/runtime_sensor_detail_temperature.js"></script>' . PHP_EOL;
|
||||||
@ -98,6 +101,10 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
|||||||
echo '<script src="/js/component/button.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/button.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/button_group.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/button_group.js"></script>' . PHP_EOL;
|
||||||
echo '<script src="/js/component/title.js"></script>' . PHP_EOL;
|
echo '<script src="/js/component/title.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/metric.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/metric/setpoint_heat.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/metric/setpoint_cool.js"></script>' . PHP_EOL;
|
||||||
|
echo '<script src="/js/component/metric/runtime_per_heating_degree_day.js"></script>' . PHP_EOL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
echo '<script src="/js/beestat.js?' . $setting->get('commit') . '"></script>' . PHP_EOL;
|
echo '<script src="/js/beestat.js?' . $setting->get('commit') . '"></script>' . PHP_EOL;
|
||||||
|
@ -1,100 +1,103 @@
|
|||||||
/**
|
/**
|
||||||
* Home comparisons layer.
|
* Home comparisons layer.
|
||||||
*/
|
*/
|
||||||
beestat.layer.home_comparisons = function() {
|
beestat.layer.comparisons = function() {
|
||||||
beestat.layer.apply(this, arguments);
|
beestat.layer.apply(this, arguments);
|
||||||
};
|
};
|
||||||
beestat.extend(beestat.layer.home_comparisons, beestat.layer);
|
beestat.extend(beestat.layer.comparisons, beestat.layer);
|
||||||
|
|
||||||
beestat.layer.home_comparisons.prototype.decorate_ = function(parent) {
|
beestat.layer.comparisons.prototype.decorate_ = function(parent) {
|
||||||
/*
|
/*
|
||||||
* Set the overflow on the body so the scrollbar is always present so
|
* Set the overflow on the body so the scrollbar is always present so
|
||||||
* highcharts graphs render properly.
|
* highcharts graphs render properly.
|
||||||
*/
|
*/
|
||||||
$('body').style({
|
$('body').style({
|
||||||
'overflow-y': 'scroll',
|
'overflow-y': 'scroll',
|
||||||
'background': beestat.style.color.bluegray.light,
|
'background': beestat.style.color.bluegray.light,
|
||||||
'padding': '0 ' + beestat.style.size.gutter + 'px'
|
'padding': '0 ' + beestat.style.size.gutter + 'px'
|
||||||
});
|
});
|
||||||
|
|
||||||
(new beestat.component.header('home_comparisons')).render(parent);
|
(new beestat.component.header('comparisons')).render(parent);
|
||||||
|
|
||||||
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
||||||
var thermostat_group = beestat.cache.thermostat_group[thermostat.thermostat_group_id];
|
var thermostat_group = beestat.cache.thermostat_group[thermostat.thermostat_group_id];
|
||||||
|
|
||||||
// All the cards
|
// All the cards
|
||||||
var cards = [];
|
var cards = [];
|
||||||
|
|
||||||
if (window.is_demo === true) {
|
if (window.is_demo === true) {
|
||||||
cards.push([
|
cards.push([
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.demo(),
|
'card': new beestat.component.card.demo(),
|
||||||
'size': 12
|
'size': 12
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
cards.push([
|
cards.push([
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.comparison_settings(),
|
'card': new beestat.component.card.comparison_settings(),
|
||||||
'size': 6
|
'size': 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.my_home(),
|
'card': new beestat.component.card.my_home(),
|
||||||
'size': 6
|
'size': 6
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Scores and graph
|
// Scores and graph
|
||||||
if (thermostat_group.temperature_profile !== null) {
|
if (thermostat_group.profile !== null) {
|
||||||
cards.push([
|
cards.push([
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.score.heat(),
|
'card': new beestat.component.card.score.heat(),
|
||||||
'size': 4
|
'size': 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.score.cool(),
|
'card': new beestat.component.card.score.cool(),
|
||||||
'size': 4
|
'size': 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'card': new beestat.component.card.score.resist(),
|
'card': new beestat.component.card.score.resist(),
|
||||||
'size': 4
|
'size': 4
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (
|
cards.push([
|
||||||
(
|
{
|
||||||
thermostat_group.temperature_profile.heat !== undefined &&
|
'card': new beestat.component.card.temperature_profiles(thermostat_group.thermostat_group_id),
|
||||||
thermostat_group.temperature_profile.heat.linear_trendline.slope < 0
|
'size': 12
|
||||||
) ||
|
}
|
||||||
(
|
]);
|
||||||
thermostat_group.temperature_profile.cool !== undefined &&
|
|
||||||
thermostat_group.temperature_profile.cool.linear_trendline.slope < 0
|
if (beestat.user.has_early_access() === true) {
|
||||||
)
|
cards.push([
|
||||||
) {
|
{
|
||||||
cards.push([
|
'card': new beestat.component.card.early_access(),
|
||||||
{
|
'size': 12
|
||||||
'card': new beestat.component.card.comparison_issue(),
|
}
|
||||||
'size': 12
|
]);
|
||||||
}
|
cards.push([
|
||||||
]);
|
{
|
||||||
}
|
'card': new beestat.component.card.metrics(thermostat_group.thermostat_group_id),
|
||||||
|
'size': 12
|
||||||
cards.push([
|
}
|
||||||
{
|
]);
|
||||||
'card': new beestat.component.card.temperature_profiles(thermostat_group.thermostat_group_id),
|
cards.push([
|
||||||
'size': 12
|
{
|
||||||
}
|
'card': new beestat.component.card.temperature_profiles_new(thermostat_group.thermostat_group_id),
|
||||||
]);
|
'size': 12
|
||||||
}
|
}
|
||||||
|
]);
|
||||||
// Footer
|
}
|
||||||
cards.push([
|
}
|
||||||
{
|
|
||||||
'card': new beestat.component.card.footer(),
|
// Footer
|
||||||
'size': 12
|
cards.push([
|
||||||
}
|
{
|
||||||
]);
|
'card': new beestat.component.card.footer(),
|
||||||
|
'size': 12
|
||||||
(new beestat.component.layout(cards)).render(parent);
|
}
|
||||||
};
|
]);
|
||||||
|
|
||||||
|
(new beestat.component.layout(cards)).render(parent);
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user