mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
798 lines
23 KiB
JavaScript
798 lines
23 KiB
JavaScript
/**
|
|
* Recent activity card. Shows a graph similar to what ecobee shows with the
|
|
* runtime info for a recent period of time.
|
|
*/
|
|
beestat.component.card.aggregate_runtime = function() {
|
|
var self = this;
|
|
|
|
/*
|
|
* When a setting is changed clear all of the data. Then rerender which will
|
|
* trigger the loading state.
|
|
*
|
|
* 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 setting_change_function = beestat.debounce(function() {
|
|
beestat.cache.set('aggregate_runtime', []);
|
|
self.rerender();
|
|
}, 10);
|
|
|
|
beestat.dispatcher.addEventListener(
|
|
[
|
|
'setting.aggregate_runtime_time_count',
|
|
'setting.aggregate_runtime_time_period',
|
|
'setting.aggregate_runtime_group_by',
|
|
'setting.aggregate_runtime_gap_fill'
|
|
],
|
|
setting_change_function
|
|
);
|
|
|
|
beestat.component.card.apply(this, arguments);
|
|
};
|
|
beestat.extend(beestat.component.card.aggregate_runtime, beestat.component.card);
|
|
|
|
beestat.component.card.aggregate_runtime.equipment_series = [
|
|
'compressor_cool_1',
|
|
'compressor_cool_2',
|
|
'compressor_heat_1',
|
|
'compressor_heat_2',
|
|
'auxiliary_heat_1',
|
|
'auxiliary_heat_2',
|
|
'auxiliary_heat_3'
|
|
];
|
|
|
|
beestat.component.card.aggregate_runtime.prototype.decorate_contents_ = function(parent) {
|
|
var self = this;
|
|
|
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
|
|
|
this.chart_ = new beestat.component.chart();
|
|
var series = this.get_series_();
|
|
|
|
this.chart_.options.chart.backgroundColor = beestat.style.color.bluegray.base;
|
|
this.chart_.options.exporting.filename = thermostat.name + ' - Aggregate Runtime';
|
|
this.chart_.options.exporting.chartOptions.title.text = this.get_title_();
|
|
this.chart_.options.exporting.chartOptions.subtitle.text = this.get_subtitle_();
|
|
|
|
var current_day;
|
|
var current_hour;
|
|
var current_week;
|
|
var current_month;
|
|
var current_year;
|
|
|
|
this.chart_.options.xAxis = {
|
|
'categories': series.x.chart_data,
|
|
'lineColor': beestat.style.color.bluegray.light,
|
|
'tickLength': 0,
|
|
'labels': {
|
|
'style': {
|
|
'color': beestat.style.color.gray.base
|
|
},
|
|
'formatter': function() {
|
|
var date_parts = this.value.match(/(?:h(\d+))?(?:d(\d+))?(?:w(\d+))?(?:m(\d+))?(?:y(\d+))?/);
|
|
var hour = moment(date_parts[1], 'H').format('ha');
|
|
var day = date_parts[2];
|
|
var month = moment(date_parts[4], 'M').format('MMM');
|
|
|
|
var year;
|
|
var week;
|
|
if (beestat.setting('aggregate_runtime_group_by') === 'week') {
|
|
// ISO 8601 week of the year.
|
|
var yearweek_m = moment().isoWeek(date_parts[3])
|
|
.year(date_parts[5])
|
|
.day('Monday');
|
|
week = yearweek_m.format('MMM D');
|
|
year = yearweek_m.format('YYYY');
|
|
} else {
|
|
year = date_parts[5];
|
|
}
|
|
|
|
var label_parts = [];
|
|
switch (beestat.setting('aggregate_runtime_group_by')) {
|
|
case 'year':
|
|
label_parts.push(year);
|
|
break;
|
|
case 'month':
|
|
label_parts.push(month);
|
|
if (year !== current_year) {
|
|
label_parts.push(year);
|
|
}
|
|
break;
|
|
case 'week':
|
|
if (week !== current_week) {
|
|
label_parts.push(week);
|
|
}
|
|
if (year !== current_year) {
|
|
label_parts.push(year);
|
|
}
|
|
break;
|
|
case 'day':
|
|
if (month !== current_month) {
|
|
label_parts.push(month);
|
|
}
|
|
label_parts.push(day);
|
|
if (year !== current_year) {
|
|
label_parts.push(year);
|
|
}
|
|
break;
|
|
case 'hour':
|
|
if (month !== current_month) {
|
|
label_parts.push(month);
|
|
}
|
|
if (day !== current_day) {
|
|
label_parts.push(day);
|
|
}
|
|
if (year !== current_year) {
|
|
label_parts.push(year);
|
|
}
|
|
label_parts.push(hour);
|
|
break;
|
|
}
|
|
|
|
current_hour = hour;
|
|
current_day = day;
|
|
current_week = week;
|
|
current_month = month;
|
|
current_year = year;
|
|
|
|
return label_parts.join(' ');
|
|
}
|
|
}
|
|
};
|
|
|
|
var y_max_hours;
|
|
var tick_interval;
|
|
switch (beestat.setting('aggregate_runtime_group_by')) {
|
|
case 'year':
|
|
y_max_hours = 8760;
|
|
tick_interval = 2190;
|
|
break;
|
|
case 'month':
|
|
y_max_hours = 672;
|
|
tick_interval = 168;
|
|
break;
|
|
case 'week':
|
|
y_max_hours = 168;
|
|
tick_interval = 24;
|
|
break;
|
|
case 'day':
|
|
y_max_hours = 24;
|
|
tick_interval = 6;
|
|
break;
|
|
}
|
|
|
|
this.chart_.options.yAxis = [
|
|
{
|
|
'alignTicks': false,
|
|
'min': 0,
|
|
'softMax': y_max_hours,
|
|
'tickInterval': tick_interval,
|
|
'reversedStacks': false,
|
|
'gridLineColor': beestat.style.color.bluegray.light,
|
|
'gridLineDashStyle': 'longdash',
|
|
'title': {
|
|
'text': ''
|
|
},
|
|
'labels': {
|
|
'style': {
|
|
'color': beestat.style.color.gray.base
|
|
},
|
|
'formatter': function() {
|
|
return this.value + 'h';
|
|
}
|
|
}
|
|
},
|
|
{
|
|
'alignTicks': false,
|
|
'gridLineColor': null,
|
|
'gridLineDashStyle': 'longdash',
|
|
'opposite': true,
|
|
'allowDecimals': false,
|
|
'title': {
|
|
'text': ''
|
|
},
|
|
'labels': {
|
|
'style': {
|
|
'color': beestat.style.color.gray.base
|
|
},
|
|
'formatter': function() {
|
|
return this.value + thermostat.temperature_unit;
|
|
}
|
|
}
|
|
}
|
|
];
|
|
|
|
this.chart_.options.tooltip = {
|
|
'shared': true,
|
|
'useHTML': true,
|
|
'borderWidth': 0,
|
|
'shadow': false,
|
|
'backgroundColor': null,
|
|
'followPointer': true,
|
|
'crosshairs': {
|
|
'width': 1,
|
|
'zIndex': 100,
|
|
'color': beestat.style.color.gray.light,
|
|
'dashStyle': 'shortDot',
|
|
'snap': false
|
|
},
|
|
'positioner': function(tooltip_width, tooltip_height, point) {
|
|
return beestat.component.chart.tooltip_positioner(
|
|
self.chart_.get_chart(),
|
|
tooltip_width,
|
|
tooltip_height,
|
|
point
|
|
);
|
|
},
|
|
'formatter': function() {
|
|
var date_parts = this.x.match(/(?:h(\d+))?(?:d(\d+))?(?:w(\d+))?(?:m(\d+))?(?:y(\d+))?/);
|
|
var hour = moment(date_parts[1], 'H').format('ha');
|
|
var day = date_parts[2];
|
|
var month = moment(date_parts[4], 'M').format('MMM');
|
|
|
|
var year;
|
|
var week;
|
|
if (beestat.setting('aggregate_runtime_group_by') === 'week') {
|
|
// ISO 8601 week of the year.
|
|
var yearweek_m = moment().isoWeek(date_parts[3])
|
|
.year(date_parts[5])
|
|
.day('Monday');
|
|
week = yearweek_m.format('MMM D');
|
|
year = yearweek_m.format('YYYY');
|
|
} else {
|
|
year = date_parts[5];
|
|
}
|
|
|
|
var label_parts = [];
|
|
switch (beestat.setting('aggregate_runtime_group_by')) {
|
|
case 'year':
|
|
label_parts.push(year);
|
|
break;
|
|
case 'month':
|
|
label_parts.push(month);
|
|
label_parts.push(year);
|
|
break;
|
|
case 'week':
|
|
label_parts.push('Week of');
|
|
label_parts.push(week + ',');
|
|
label_parts.push(year);
|
|
break;
|
|
case 'day':
|
|
label_parts.push(month);
|
|
label_parts.push(day);
|
|
break;
|
|
case 'hour':
|
|
label_parts.push(hour);
|
|
break;
|
|
}
|
|
|
|
var sections = [];
|
|
var section = [];
|
|
for (var series_code in series) {
|
|
var value = series[series_code].data[this.x];
|
|
|
|
// Don't show in tooltip if there was no runtime to report.
|
|
if (value === 0) {
|
|
continue;
|
|
}
|
|
|
|
switch (series_code) {
|
|
case 'x':
|
|
case 'min_max_outdoor_temperature':
|
|
continue;
|
|
break;
|
|
case 'average_outdoor_temperature':
|
|
value = beestat.temperature({
|
|
'temperature': value,
|
|
'convert': false,
|
|
'units': true,
|
|
'round': 0
|
|
});
|
|
|
|
value += ' (';
|
|
value += beestat.temperature({
|
|
'temperature': series.min_max_outdoor_temperature.data[this.x].min,
|
|
'convert': false,
|
|
'units': true,
|
|
'round': 0
|
|
});
|
|
value += ' to ';
|
|
value += beestat.temperature({
|
|
'temperature': series.min_max_outdoor_temperature.data[this.x].max,
|
|
'convert': false,
|
|
'units': true,
|
|
'round': 0
|
|
});
|
|
value += ')';
|
|
|
|
break;
|
|
default:
|
|
value = beestat.time(value, 'hours');
|
|
break;
|
|
}
|
|
|
|
if (value !== null) {
|
|
section.push({
|
|
'label': beestat.series[series_code].name,
|
|
'value': value,
|
|
'color': beestat.series[series_code].color
|
|
});
|
|
}
|
|
}
|
|
sections.push(section);
|
|
|
|
return beestat.component.chart.tooltip_formatter(
|
|
label_parts.join(' '),
|
|
sections,
|
|
150
|
|
);
|
|
}
|
|
};
|
|
|
|
this.chart_.options.series = [];
|
|
|
|
beestat.component.card.aggregate_runtime.equipment_series.forEach(function(series_code) {
|
|
if (series[series_code].enabled === true) {
|
|
self.chart_.options.series.push({
|
|
'data': series[series_code].chart_data,
|
|
'yAxis': 0,
|
|
'groupPadding': 0,
|
|
'name': beestat.series[series_code].name,
|
|
'type': 'column',
|
|
'color': beestat.series[series_code].color
|
|
});
|
|
}
|
|
});
|
|
|
|
this.chart_.options.series.push({
|
|
'name': beestat.series.average_outdoor_temperature.name,
|
|
'data': series.average_outdoor_temperature.chart_data,
|
|
'color': beestat.series.average_outdoor_temperature.color,
|
|
'type': 'spline',
|
|
'yAxis': 1,
|
|
'dashStyle': 'ShortDash',
|
|
'lineWidth': 1,
|
|
'zones': beestat.component.chart.get_outdoor_temperature_zones()
|
|
});
|
|
|
|
this.chart_.options.series.push({
|
|
'name': beestat.series.min_max_outdoor_temperature.name,
|
|
'data': series.min_max_outdoor_temperature.chart_data,
|
|
'color': beestat.series.min_max_outdoor_temperature.color,
|
|
'type': 'areasplinerange',
|
|
'yAxis': 1,
|
|
'fillOpacity': 0.2,
|
|
'lineWidth': 0,
|
|
'visible': false
|
|
});
|
|
|
|
this.chart_.render(parent);
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
if (this.data_available_() === true) {
|
|
if (beestat.cache.aggregate_runtime.length === 0) {
|
|
this.get_data_();
|
|
} else {
|
|
this.hide_loading_();
|
|
}
|
|
} else {
|
|
var poll_interval = 10000;
|
|
|
|
beestat.add_poll_interval(poll_interval);
|
|
beestat.dispatcher.addEventListener('poll.aggregate_runtime_load', function() {
|
|
if (self.data_available_() === true) {
|
|
beestat.remove_poll_interval(poll_interval);
|
|
beestat.dispatcher.removeEventListener('poll.aggregate_runtime_load');
|
|
self.get_data_();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Get all of the series data.
|
|
*
|
|
* @return {object} The series data.
|
|
*/
|
|
beestat.component.card.aggregate_runtime.prototype.get_series_ = function() {
|
|
// TODO: Auto-generate these where possible like I did in recent_activity
|
|
var series = {
|
|
'x': {
|
|
'enabled': true,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'average_outdoor_temperature': {
|
|
'enabled': true,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'min_max_outdoor_temperature': {
|
|
'enabled': true,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'compressor_heat_1': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'compressor_heat_2': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'compressor_cool_1': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'compressor_cool_2': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'auxiliary_heat_1': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'auxiliary_heat_2': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
},
|
|
'auxiliary_heat_3': {
|
|
'enabled': false,
|
|
'chart_data': [],
|
|
'data': {}
|
|
}
|
|
};
|
|
|
|
beestat.cache.aggregate_runtime.forEach(function(aggregate, i) {
|
|
|
|
/*
|
|
* Generate a custom x value that I can use to build the custom axis for
|
|
* later. I thought about sending a timestamp back from the API instead of
|
|
* these discrete values but it's not possible due to the grouping. I could
|
|
* try to convert this to a timestamp or moment value but I'll just have to
|
|
* break it back out anyways so there's not much point to that.
|
|
*/
|
|
var x_parts = [];
|
|
[
|
|
'hour',
|
|
'day',
|
|
'week',
|
|
'month',
|
|
'year'
|
|
].forEach(function(period) {
|
|
if (aggregate[period] !== undefined) {
|
|
x_parts.push(period[0] + aggregate[period]);
|
|
}
|
|
});
|
|
var x = x_parts.join('');
|
|
|
|
series.x.chart_data.push(x);
|
|
|
|
/*
|
|
* Used to estimate values when data is missing. These magic numbers are the
|
|
* number of expected data points in a group when that group represents a
|
|
* year, month, etc.
|
|
*/
|
|
var adjustment_factor;
|
|
switch (beestat.setting('aggregate_runtime_group_by')) {
|
|
case 'year':
|
|
var year = x_parts[0].match(/\d+/)[0];
|
|
var is_leap_year = moment(year, 'YYYY').isLeapYear();
|
|
var days_in_year = is_leap_year === true ? 366 : 365;
|
|
adjustment_factor = days_in_year * 288;
|
|
break;
|
|
case 'month':
|
|
var month = x_parts[0].match(/\d+/)[0];
|
|
var year = x_parts[1].match(/\d+/)[0];
|
|
var days_in_month = moment(year + '-' + month, 'YYYY-MM').daysInMonth();
|
|
adjustment_factor = days_in_month * 288;
|
|
break;
|
|
case 'week':
|
|
adjustment_factor = 2016;
|
|
break;
|
|
case 'day':
|
|
adjustment_factor = 288;
|
|
break;
|
|
case 'hour':
|
|
adjustment_factor = 12;
|
|
break;
|
|
default:
|
|
console.error('Adjustment factor not available.');
|
|
break;
|
|
}
|
|
|
|
beestat.component.card.aggregate_runtime.equipment_series.forEach(function(series_code) {
|
|
var value = aggregate[series_code];
|
|
|
|
// Account for missing data in all but the last x value.
|
|
if (
|
|
beestat.setting('aggregate_runtime_gap_fill') === true &&
|
|
i < (beestat.cache.aggregate_runtime.length - 1)
|
|
) {
|
|
value = value *
|
|
adjustment_factor /
|
|
aggregate.count;
|
|
}
|
|
|
|
// The value (in hours).
|
|
value /= 3600;
|
|
|
|
// Enable the series if it has data.
|
|
if (value > 0) {
|
|
series[series_code].enabled = true;
|
|
}
|
|
|
|
series[series_code].chart_data.push([
|
|
x,
|
|
value
|
|
]);
|
|
series[series_code].data[x] = value;
|
|
});
|
|
|
|
// Average outdoor temperature.
|
|
var average_outdoor_temperature_value = beestat.temperature({
|
|
'temperature': aggregate.average_outdoor_temperature
|
|
});
|
|
|
|
series.average_outdoor_temperature.data[x] = average_outdoor_temperature_value;
|
|
series.average_outdoor_temperature.chart_data.push([
|
|
x,
|
|
average_outdoor_temperature_value
|
|
]);
|
|
|
|
// Min/max outdoor temperature.
|
|
var min_outdoor_temperature_value = beestat.temperature({
|
|
'temperature': aggregate.min_outdoor_temperature
|
|
});
|
|
var max_outdoor_temperature_value = beestat.temperature({
|
|
'temperature': aggregate.max_outdoor_temperature
|
|
});
|
|
|
|
series.min_max_outdoor_temperature.data[x] = {
|
|
'min': min_outdoor_temperature_value,
|
|
'max': max_outdoor_temperature_value
|
|
};
|
|
series.min_max_outdoor_temperature.chart_data.push([
|
|
x,
|
|
min_outdoor_temperature_value,
|
|
max_outdoor_temperature_value
|
|
]);
|
|
});
|
|
|
|
return series;
|
|
};
|
|
|
|
/**
|
|
* Decorate the menu
|
|
*
|
|
* @param {rocket.Elements} parent
|
|
*/
|
|
beestat.component.card.aggregate_runtime.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('Past 2 Months')
|
|
.set_icon('calendar_range')
|
|
.set_callback(function() {
|
|
if (
|
|
beestat.setting('aggregate_runtime_time_count') !== 2 ||
|
|
beestat.setting('aggregate_runtime_time_period') !== 'month' ||
|
|
beestat.setting('aggregate_runtime_group_by') !== 'day'
|
|
) {
|
|
beestat.setting({
|
|
'aggregate_runtime_time_count': 2,
|
|
'aggregate_runtime_time_period': 'month',
|
|
'aggregate_runtime_group_by': 'day'
|
|
});
|
|
}
|
|
}));
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Past 12 Months')
|
|
.set_icon('calendar_range')
|
|
.set_callback(function() {
|
|
if (
|
|
beestat.setting('aggregate_runtime_time_count') !== 12 ||
|
|
beestat.setting('aggregate_runtime_time_period') !== 'month' ||
|
|
beestat.setting('aggregate_runtime_group_by') !== 'week'
|
|
) {
|
|
beestat.setting({
|
|
'aggregate_runtime_time_count': 12,
|
|
'aggregate_runtime_time_period': 'month',
|
|
'aggregate_runtime_group_by': 'week'
|
|
});
|
|
}
|
|
}));
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('All Time')
|
|
.set_icon('calendar_range')
|
|
.set_callback(function() {
|
|
if (
|
|
beestat.setting('aggregate_runtime_time_count') !== 0 ||
|
|
beestat.setting('aggregate_runtime_time_period') !== 'all' ||
|
|
beestat.setting('aggregate_runtime_group_by') !== 'month'
|
|
) {
|
|
beestat.setting({
|
|
'aggregate_runtime_time_count': 0,
|
|
'aggregate_runtime_time_period': 'all',
|
|
'aggregate_runtime_group_by': 'month'
|
|
});
|
|
}
|
|
}));
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Custom')
|
|
.set_icon('calendar_edit')
|
|
.set_callback(function() {
|
|
(new beestat.component.modal.aggregate_runtime_custom()).render();
|
|
}));
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Download Chart')
|
|
.set_icon('download')
|
|
.set_callback(function() {
|
|
self.chart_.get_chart().exportChartLocal();
|
|
}));
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Reset Zoom')
|
|
.set_icon('magnify_minus')
|
|
.set_callback(function() {
|
|
self.chart_.get_chart().zoomOut();
|
|
}));
|
|
|
|
if (beestat.setting('aggregate_runtime_gap_fill') === true) {
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Disable Gap-Fill')
|
|
.set_icon('basket_unfill')
|
|
.set_callback(function() {
|
|
beestat.setting('aggregate_runtime_gap_fill', false);
|
|
}));
|
|
} else {
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Enable Gap-Fill')
|
|
.set_icon('basket_fill')
|
|
.set_callback(function() {
|
|
beestat.setting('aggregate_runtime_gap_fill', true);
|
|
}));
|
|
}
|
|
|
|
menu.add_menu_item(new beestat.component.menu_item()
|
|
.set_text('Help')
|
|
.set_icon('help_circle')
|
|
.set_callback(function() {
|
|
(new beestat.component.modal.help_aggregate_runtime()).render();
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* Get the title of the card.
|
|
*
|
|
* @return {string}
|
|
*/
|
|
beestat.component.card.aggregate_runtime.prototype.get_title_ = function() {
|
|
return 'Aggregate Runtime';
|
|
};
|
|
|
|
/**
|
|
* Get the subtitle of the card.
|
|
*
|
|
* @return {string}
|
|
*/
|
|
beestat.component.card.aggregate_runtime.prototype.get_subtitle_ = function() {
|
|
var s = (beestat.setting('aggregate_runtime_time_count') > 1) ? 's' : '';
|
|
|
|
var string = '';
|
|
|
|
if (beestat.setting('aggregate_runtime_time_period') === 'all') {
|
|
string = 'All time';
|
|
} else {
|
|
string = 'Past ' +
|
|
beestat.setting('aggregate_runtime_time_count') +
|
|
' ' +
|
|
beestat.setting('aggregate_runtime_time_period') +
|
|
s;
|
|
}
|
|
|
|
string += ', ' +
|
|
' grouped by ' +
|
|
beestat.setting('aggregate_runtime_group_by');
|
|
|
|
return string;
|
|
};
|
|
|
|
/**
|
|
* Is aggregate runtime data available?
|
|
*
|
|
* @return {boolean} Whether or not enough data is currently available to
|
|
* render this card.
|
|
*/
|
|
beestat.component.card.aggregate_runtime.prototype.data_available_ = function() {
|
|
// Demo can juse grab whatever data is there.
|
|
if (window.is_demo === true) {
|
|
this.show_loading_('Loading Aggregate Runtime');
|
|
return true;
|
|
}
|
|
|
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
|
|
|
var current_sync_begin = moment.utc(thermostat.sync_begin);
|
|
var current_sync_end = moment.utc(thermostat.sync_end);
|
|
|
|
var required_sync_begin;
|
|
if (beestat.setting('aggregate_runtime_time_period') === 'all') {
|
|
required_sync_begin = moment(thermostat.first_connected);
|
|
} else {
|
|
required_sync_begin = moment().subtract(moment.duration(
|
|
beestat.setting('aggregate_runtime_time_count'),
|
|
beestat.setting('aggregate_runtime_time_period')
|
|
));
|
|
}
|
|
required_sync_begin = moment.max(
|
|
required_sync_begin,
|
|
moment(thermostat.first_connected)
|
|
);
|
|
var required_sync_end = moment().subtract(1, 'hour');
|
|
|
|
// Percentage
|
|
var denominator = required_sync_end.diff(required_sync_begin, 'day');
|
|
var numerator_begin = moment.max(current_sync_begin, required_sync_begin);
|
|
var numerator_end = moment.min(current_sync_end, required_sync_end);
|
|
var numerator = numerator_end.diff(numerator_begin, 'day');
|
|
var percentage = numerator / denominator * 100;
|
|
if (isNaN(percentage) === true || percentage < 0) {
|
|
percentage = 0;
|
|
}
|
|
|
|
if (percentage >= 95) {
|
|
this.show_loading_('Loading Aggregate Runtime');
|
|
} else {
|
|
this.show_loading_('Syncing Data (' +
|
|
Math.round(percentage) +
|
|
'%)');
|
|
}
|
|
|
|
return (
|
|
current_sync_begin.isSameOrBefore(required_sync_begin) &&
|
|
current_sync_end.isSameOrAfter(required_sync_end)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Get the data needed to render this card.
|
|
*/
|
|
beestat.component.card.aggregate_runtime.prototype.get_data_ = function() {
|
|
var self = this;
|
|
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
|
|
|
new beestat.api()
|
|
.add_call(
|
|
'ecobee_runtime_thermostat',
|
|
'get_aggregate_runtime',
|
|
{
|
|
'ecobee_thermostat_id': thermostat.ecobee_thermostat_id,
|
|
'time_period': beestat.setting('aggregate_runtime_time_period'),
|
|
'group_by': beestat.setting('aggregate_runtime_group_by'),
|
|
'time_count': beestat.setting('aggregate_runtime_time_count')
|
|
}
|
|
)
|
|
.set_callback(function(response) {
|
|
beestat.cache.set('aggregate_runtime', response);
|
|
self.rerender();
|
|
})
|
|
.send();
|
|
};
|