diff --git a/js/beestat/get_sync_progress.js b/js/beestat/get_sync_progress.js
deleted file mode 100755
index 86ff9fc..0000000
--- a/js/beestat/get_sync_progress.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Get the sync progress for a thermostat.
- *
- * @param {number} thermostat_id
- *
- * @return {number} A number between 0 and 100 inclusive.
- */
-beestat.get_sync_progress = function(thermostat_id) {
- var thermostat = beestat.cache.thermostat[thermostat_id];
-
- var current_sync_begin = moment.utc(thermostat.sync_begin);
- var current_sync_end = moment.utc(thermostat.sync_end);
-
- var required_sync_begin = moment.max(
- moment(thermostat.first_connected),
- moment().subtract(1, 'year')
- );
- var required_sync_end = moment().subtract(1, 'hour');
-
- var denominator = required_sync_end.diff(required_sync_begin, 'day');
- var numerator = current_sync_end.diff(current_sync_begin, 'day');
-
- return Math.min(100, Math.round(numerator / denominator * 100)) || 0;
-};
diff --git a/js/beestat/runtime_sensor.js b/js/beestat/runtime_sensor.js
index 971afb6..ccde640 100644
--- a/js/beestat/runtime_sensor.js
+++ b/js/beestat/runtime_sensor.js
@@ -78,13 +78,6 @@ beestat.runtime_sensor.get_data = function(thermostat_id, range) {
);
}
- // TODO: This needs to be max of begin and when I actually have sensor data
- var thermostat = beestat.cache.thermostat[thermostat_id];
- begin_m = moment.max(
- begin_m,
- moment(thermostat.first_connected)
- );
-
begin_m
.minute(Math.ceil(begin_m.minute() / 5) * 5)
.second(0)
diff --git a/js/beestat/thermostat.js b/js/beestat/thermostat.js
new file mode 100644
index 0000000..ccd2e6b
--- /dev/null
+++ b/js/beestat/thermostat.js
@@ -0,0 +1,59 @@
+beestat.thermostat = {};
+
+/**
+ * Get the sync progress for a thermostat.
+ *
+ * @param {number} thermostat_id
+ *
+ * @return {number|null} A number between 0 and 100 inclusive. Can return null
+ * for unknown.
+ */
+beestat.thermostat.get_sync_progress = function(thermostat_id) {
+ var thermostat = beestat.cache.thermostat[thermostat_id];
+
+ var current_sync_begin = moment(thermostat.sync_begin);
+ var current_sync_end = moment(thermostat.sync_end);
+
+ var required_sync_begin = moment.max(
+ moment(thermostat.first_connected),
+ moment().subtract(1, 'year')
+ );
+ var required_sync_end = moment().subtract(1, 'hour');
+
+ // If the thermostat was connected within the last hour.
+ if (required_sync_end.isSameOrBefore(required_sync_begin) === true) {
+ return null;
+ }
+
+ var denominator = required_sync_end.diff(required_sync_begin, 'day');
+ var numerator = current_sync_end.diff(current_sync_begin, 'day');
+
+ return Math.min(100, Math.round(numerator / denominator * 100)) || 0;
+};
+
+/**
+ * Determine whether or not the data to render the desired date range has been
+ * synced.
+ *
+ * @param {number} thermostat_id
+ * @param {moment} required_sync_begin
+ * @param {moment} required_sync_end
+ *
+ * @return {boolean} Whether or not the data is synced.
+ */
+beestat.thermostat.data_synced = function(thermostat_id, required_sync_begin, required_sync_end) {
+ // Demo can just grab whatever data is there.
+ if (window.is_demo === true) {
+ return true;
+ }
+
+ var thermostat = beestat.cache.thermostat[thermostat_id];
+
+ var current_sync_begin = moment(thermostat.sync_begin);
+ var current_sync_end = moment(thermostat.sync_end);
+
+ return (
+ current_sync_begin.isSameOrBefore(required_sync_begin) === true &&
+ current_sync_end.isSameOrAfter(required_sync_end) === true
+ );
+};
diff --git a/js/component/card/comparison_settings.js b/js/component/card/comparison_settings.js
index 5ac122e..3a48190 100644
--- a/js/component/card/comparison_settings.js
+++ b/js/component/card/comparison_settings.js
@@ -278,7 +278,7 @@ beestat.component.card.comparison_settings.prototype.decorate_top_right_ = funct
* @return {boolean} Whether or not all of the data has been loaded.
*/
beestat.component.card.comparison_settings.prototype.data_available_ = function() {
- var sync_progress = beestat.get_sync_progress(beestat.setting('thermostat_id'));
+ var sync_progress = beestat.thermostat.get_sync_progress(beestat.setting('thermostat_id'));
if (sync_progress >= 95) {
this.show_loading_('Calculating Scores');
diff --git a/js/component/card/runtime_sensor_detail.js b/js/component/card/runtime_sensor_detail.js
index faf8719..1a0a0dd 100644
--- a/js/component/card/runtime_sensor_detail.js
+++ b/js/component/card/runtime_sensor_detail.js
@@ -19,6 +19,7 @@ beestat.component.card.runtime_sensor_detail = function(thermostat_id) {
* for when rerendering.
*/
var change_function = beestat.debounce(function() {
+ self.get_data_(true);
self.rerender();
}, 10);
@@ -44,30 +45,29 @@ beestat.extend(beestat.component.card.runtime_sensor_detail, beestat.component.c
beestat.component.card.runtime_sensor_detail.prototype.decorate_contents_ = function(parent) {
var self = this;
- var range = {
- 'type': beestat.setting('runtime_sensor_detail_range_type'),
- 'dynamic': beestat.setting('runtime_sensor_detail_range_dynamic'),
- 'static_begin': beestat.setting('runtime_sensor_detail_range_static_begin'),
- 'static_end': beestat.setting('runtime_sensor_detail_range_static_end')
- };
-
- var sensor_data = beestat.runtime_sensor.get_data(this.thermostat_id_, range);
- var thermostat_data = beestat.runtime_thermostat.get_data(this.thermostat_id_, range);
-
- var data = sensor_data;
-
- Object.assign(data.series, thermostat_data.series);
- Object.assign(data.metadata.series, thermostat_data.metadata.series);
-
this.charts_ = {
- 'equipment': new beestat.component.chart.runtime_thermostat_detail_equipment(data),
- 'occupancy': new beestat.component.chart.runtime_sensor_detail_occupancy(data),
- 'temperature': new beestat.component.chart.runtime_sensor_detail_temperature(data)
+ 'equipment': new beestat.component.chart.runtime_thermostat_detail_equipment(
+ this.get_data_()
+ ),
+ 'occupancy': new beestat.component.chart.runtime_sensor_detail_occupancy(
+ this.get_data_()
+ ),
+ 'temperature': new beestat.component.chart.runtime_sensor_detail_temperature(
+ this.get_data_()
+ )
};
- this.charts_.equipment.render(parent);
- this.charts_.occupancy.render(parent);
- this.charts_.temperature.render(parent);
+ var container = $.createElement('div').style({
+ 'position': 'relative'
+ });
+ parent.appendChild(container);
+
+ var chart_container = $.createElement('div');
+ container.appendChild(chart_container);
+
+ this.charts_.equipment.render(chart_container);
+ this.charts_.occupancy.render(chart_container);
+ this.charts_.temperature.render(chart_container);
// Sync extremes and crosshair.
Object.values(this.charts_).forEach(function(source_chart) {
@@ -130,12 +130,12 @@ beestat.component.card.runtime_sensor_detail.prototype.decorate_contents_ = func
* cache is empty, then query the data. If the needed data does not exist in
* the database, check every 2 seconds until it does.
*/
- if (this.data_synced_(required_begin, required_end) === true) {
+ if (beestat.thermostat.data_synced(this.thermostat_id_, required_begin, required_end) === true) {
if (
beestat.cache.runtime_sensor === undefined ||
beestat.cache.data.runtime_thermostat_last !== 'runtime_sensor_detail'
) {
- this.show_loading_('Loading Sensor Detail');
+ this.show_loading_('Loading');
var value;
var operator;
@@ -201,9 +201,25 @@ beestat.component.card.runtime_sensor_detail.prototype.decorate_contents_ = func
});
api_call.send();
+ } else if (this.has_data_() === false) {
+ chart_container.style('filter', 'blur(3px)');
+ var no_data = $.createElement('div');
+ no_data.style({
+ 'position': 'absolute',
+ 'top': 0,
+ 'left': 0,
+ 'width': '100%',
+ 'height': '100%',
+ 'display': 'flex',
+ 'flex-direction': 'column',
+ 'justify-content': 'center',
+ 'text-align': 'center'
+ });
+ no_data.innerText('No data to display');
+ container.appendChild(no_data);
}
} else {
- this.show_loading_('Syncing Sensor Detail');
+ this.show_loading_('Syncing');
setTimeout(function() {
new beestat.api()
.add_call(
@@ -312,6 +328,58 @@ beestat.component.card.runtime_sensor_detail.prototype.decorate_top_right_ = fun
}));
};
+/**
+ * Whether or not there is data to display on the chart.
+ *
+ * @return {boolean} Whether or not there is data to display on the chart.
+ */
+beestat.component.card.runtime_sensor_detail.prototype.has_data_ = function() {
+ var data = this.get_data_();
+ for (var series_code in data.metadata.series) {
+ if (
+ series_code !== 'dummy' &&
+ data.metadata.series[series_code].active === true
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * Get data. This doesn't directly or indirectly make any API calls, but it
+ * caches the data so it doesn't have to loop over everything more than once.
+ *
+ * @param {boolean} force Force get the data?
+ *
+ * @return {object} The data.
+ */
+beestat.component.card.runtime_sensor_detail.prototype.get_data_ = function(force) {
+ if (this.data_ === undefined || force === true) {
+
+ var range = {
+ 'type': beestat.setting('runtime_sensor_detail_range_type'),
+ 'dynamic': beestat.setting('runtime_sensor_detail_range_dynamic'),
+ 'static_begin': beestat.setting('runtime_sensor_detail_range_static_begin'),
+ 'static_end': beestat.setting('runtime_sensor_detail_range_static_end')
+ };
+
+ var sensor_data = beestat.runtime_sensor.get_data(this.thermostat_id_, range);
+ var thermostat_data = beestat.runtime_thermostat.get_data(this.thermostat_id_, range);
+
+ this.data_ = sensor_data;
+
+ Object.assign(this.data_.series, thermostat_data.series);
+ Object.assign(this.data_.metadata.series, thermostat_data.metadata.series);
+
+ this.data_.metadata.chart.title = this.get_title_();
+ this.data_.metadata.chart.subtitle = this.get_subtitle_();
+ }
+
+ return this.data_;
+};
+
/**
* Get the title of the card.
*
@@ -343,29 +411,3 @@ beestat.component.card.runtime_sensor_detail.prototype.get_subtitle_ = function(
return begin + ' to ' + end;
};
-
-/**
- * Determine whether or not the data to render the desired date range has been
- * synced.
- *
- * @param {moment} required_sync_begin
- * @param {moment} required_sync_end
- *
- * @return {boolean} Whether or not the data is synced.
- */
-beestat.component.card.runtime_sensor_detail.prototype.data_synced_ = function(required_sync_begin, required_sync_end) {
- // Demo can just grab whatever data is there.
- if (window.is_demo === true) {
- 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);
-
- return (
- current_sync_begin.isSameOrBefore(required_sync_begin) &&
- current_sync_end.isSameOrAfter(required_sync_end)
- );
-};
diff --git a/js/component/card/runtime_thermostat_detail.js b/js/component/card/runtime_thermostat_detail.js
index 31d5502..2ea5399 100644
--- a/js/component/card/runtime_thermostat_detail.js
+++ b/js/component/card/runtime_thermostat_detail.js
@@ -27,7 +27,8 @@ beestat.component.card.runtime_thermostat_detail = function(thermostat_id) {
[
'setting.runtime_thermostat_detail_range_type',
'setting.runtime_thermostat_detail_range_dynamic',
- 'cache.runtime_thermostat'
+ 'cache.runtime_thermostat',
+ 'cache.thermostat'
],
change_function
);
@@ -36,32 +37,6 @@ beestat.component.card.runtime_thermostat_detail = function(thermostat_id) {
};
beestat.extend(beestat.component.card.runtime_thermostat_detail, beestat.component.card);
-/**
- * Get data. This doesn't directly or indirectly make any API calls, but it
- * caches the data so it doesn't have to loop over everything more than once.
- *
- * @param {boolean} force Force get the data?
- *
- * @return {object} The data.
- */
-beestat.component.card.runtime_thermostat_detail.prototype.get_data_ = function(force) {
- if (this.data_ === undefined || force === true) {
- var range = {
- 'type': beestat.setting('runtime_thermostat_detail_range_type'),
- 'dynamic': beestat.setting('runtime_thermostat_detail_range_dynamic'),
- 'static_begin': beestat.setting('runtime_thermostat_detail_range_static_begin'),
- 'static_end': beestat.setting('runtime_thermostat_detail_range_static_end')
- };
-
- this.data_ = beestat.runtime_thermostat.get_data(this.thermostat_id_, range);
-
- this.data_.metadata.chart.title = this.get_title_();
- this.data_.metadata.chart.subtitle = this.get_subtitle_();
- }
-
- return this.data_;
-};
-
/**
* Decorate
*
@@ -174,12 +149,12 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_contents_ =
* cache is empty, then query the data. If the needed data does not exist in
* the database, check every 2 seconds until it does.
*/
- if (this.data_synced_(required_begin, required_end) === true) {
+ if (beestat.thermostat.data_synced(this.thermostat_id_, required_begin, required_end) === true) {
if (
beestat.cache.runtime_thermostat === undefined ||
beestat.cache.data.runtime_thermostat_last !== 'runtime_thermostat_detail'
) {
- this.show_loading_('Loading Thermostat Detail');
+ this.show_loading_('Loading');
var value;
var operator;
@@ -232,7 +207,7 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_contents_ =
container.appendChild(no_data);
}
} else {
- this.show_loading_('Syncing Thermostat Detail');
+ this.show_loading_('Syncing');
setTimeout(function() {
new beestat.api()
.add_call(
@@ -247,7 +222,6 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_contents_ =
)
.set_callback(function(response) {
beestat.cache.set('thermostat', response);
- self.rerender();
})
.send();
}, 2000);
@@ -343,6 +317,51 @@ beestat.component.card.runtime_thermostat_detail.prototype.decorate_top_right_ =
}));
};
+/**
+ * Whether or not there is data to display on the chart.
+ *
+ * @return {boolean} Whether or not there is data to display on the chart.
+ */
+beestat.component.card.runtime_thermostat_detail.prototype.has_data_ = function() {
+ var data = this.get_data_();
+ for (var series_code in data.metadata.series) {
+ if (
+ series_code !== 'dummy' &&
+ data.metadata.series[series_code].active === true
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * Get data. This doesn't directly or indirectly make any API calls, but it
+ * caches the data so it doesn't have to loop over everything more than once.
+ *
+ * @param {boolean} force Force get the data?
+ *
+ * @return {object} The data.
+ */
+beestat.component.card.runtime_thermostat_detail.prototype.get_data_ = function(force) {
+ if (this.data_ === undefined || force === true) {
+ var range = {
+ 'type': beestat.setting('runtime_thermostat_detail_range_type'),
+ 'dynamic': beestat.setting('runtime_thermostat_detail_range_dynamic'),
+ 'static_begin': beestat.setting('runtime_thermostat_detail_range_static_begin'),
+ 'static_end': beestat.setting('runtime_thermostat_detail_range_static_end')
+ };
+
+ this.data_ = beestat.runtime_thermostat.get_data(this.thermostat_id_, range);
+
+ this.data_.metadata.chart.title = this.get_title_();
+ this.data_.metadata.chart.subtitle = this.get_subtitle_();
+ }
+
+ return this.data_;
+};
+
/**
* Get the title of the card.
*
@@ -374,48 +393,3 @@ beestat.component.card.runtime_thermostat_detail.prototype.get_subtitle_ = funct
return begin + ' to ' + end;
};
-
-/**
- * Determine whether or not the data to render the desired date range has been
- * synced.
- *
- * @param {moment} required_sync_begin
- * @param {moment} required_sync_end
- *
- * @return {boolean} Whether or not the data is synced.
- */
-beestat.component.card.runtime_thermostat_detail.prototype.data_synced_ = function(required_sync_begin, required_sync_end) {
- // Demo can just grab whatever data is there.
- if (window.is_demo === true) {
- return true;
- }
-
- var thermostat = beestat.cache.thermostat[this.thermostat_id_];
-
- var current_sync_begin = moment.utc(thermostat.sync_begin);
- var current_sync_end = moment.utc(thermostat.sync_end);
-
- return (
- current_sync_begin.isSameOrBefore(required_sync_begin) &&
- current_sync_end.isSameOrAfter(required_sync_end)
- );
-};
-
-/**
- * Whether or not there is data to display on the chart.
- *
- * @return {boolean} Whether or not there is data to display on the chart.
- */
-beestat.component.card.runtime_thermostat_detail.prototype.has_data_ = function() {
- var data = this.get_data_();
- for (var series_code in data.metadata.series) {
- if (
- series_code !== 'dummy' &&
- data.metadata.series[series_code].active === true
- ) {
- return true;
- }
- }
-
- return false;
-};
diff --git a/js/component/card/runtime_thermostat_summary.js b/js/component/card/runtime_thermostat_summary.js
index fe8b388..3bfb011 100755
--- a/js/component/card/runtime_thermostat_summary.js
+++ b/js/component/card/runtime_thermostat_summary.js
@@ -14,7 +14,7 @@ beestat.component.card.runtime_thermostat_summary = function(thermostat_id) {
* long the sync will take to complete.
*/
this.sync_begin_m_ = moment();
- this.sync_begin_progress_ = beestat.get_sync_progress(thermostat_id);
+ this.sync_begin_progress_ = beestat.thermostat.get_sync_progress(thermostat_id);
/*
* When a setting is changed clear all of the data. Then rerender which will
@@ -49,13 +49,37 @@ beestat.extend(beestat.component.card.runtime_thermostat_summary, beestat.compon
* @param {rocket.Elements} parent
*/
beestat.component.card.runtime_thermostat_summary.prototype.decorate_contents_ = function(parent) {
+ var container = $.createElement('div').style({
+ 'position': 'relative'
+ });
+ parent.appendChild(container);
+
+ var chart_container = $.createElement('div');
+ container.appendChild(chart_container);
+
var data = this.get_data_();
this.chart_ = new beestat.component.chart.runtime_thermostat_summary(data);
- this.chart_.render(parent);
+ this.chart_.render(chart_container);
- var sync_progress = beestat.get_sync_progress(this.thermostat_id_);
+ var sync_progress = beestat.thermostat.get_sync_progress(this.thermostat_id_);
- if (sync_progress < 100) {
+ if (sync_progress === null) {
+ chart_container.style('filter', 'blur(3px)');
+ var no_data = $.createElement('div');
+ no_data.style({
+ 'position': 'absolute',
+ 'top': 0,
+ 'left': 0,
+ 'width': '100%',
+ 'height': '100%',
+ 'display': 'flex',
+ 'flex-direction': 'column',
+ 'justify-content': 'center',
+ 'text-align': 'center'
+ });
+ no_data.innerText('No data to display');
+ container.appendChild(no_data);
+ } else if (sync_progress < 100) {
var time_taken = moment.duration(moment().diff(this.sync_begin_m_));
var percent_taken = sync_progress - this.sync_begin_progress_;
var percent_per_second = percent_taken / time_taken.asSeconds();
@@ -73,7 +97,7 @@ beestat.component.card.runtime_thermostat_summary.prototype.decorate_contents_ =
}
}
- this.show_loading_('Syncing Thermostat Summary (' + sync_progress + '%)
' + string_remain + ' remaining');
+ this.show_loading_('Syncing (' + sync_progress + '%)
' + string_remain + ' remaining');
setTimeout(function() {
var api = new beestat.api();
api.add_call(
diff --git a/js/js.php b/js/js.php
index fcf3781..f5f50d4 100755
--- a/js/js.php
+++ b/js/js.php
@@ -29,7 +29,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;
- echo '' . PHP_EOL;
+ echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;
echo '' . PHP_EOL;