diff --git a/js/.eslintrc.json b/js/.eslintrc.json index ca55bc9..f0fd195 100644 --- a/js/.eslintrc.json +++ b/js/.eslintrc.json @@ -27,6 +27,7 @@ "indent": ["error", 2], "init-declarations": "off", "linebreak-style": "off", + "lines-around-comment": "off", "max-len": ["error", {"ignoreUrls": true, "ignoreStrings": true}], "max-lines": "off", "max-depth": "off", diff --git a/js/beestat/api.js b/js/beestat/api.js index 4702fa2..36b761a 100644 --- a/js/beestat/api.js +++ b/js/beestat/api.js @@ -1,4 +1,4 @@ -beestat.api2 = function() { +beestat.api = function() { this.api_calls_ = []; }; @@ -7,18 +7,14 @@ beestat.api2 = function() { * * @type {Object} */ -beestat.api2.cache = {}; - -// if (window.localStorage.getItem('api_cache') !== null) { -// beestat.api2.cache = JSON.parse(window.localStorage.getItem('api_cache')); -// } +beestat.api.cache = {}; /** * Beestat's local API key. * * @type {string} */ -beestat.api2.api_key = 'ER9Dz8t05qUdui0cvfWi5GiVVyHP6OB8KPuSisP2'; +beestat.api.api_key = 'ER9Dz8t05qUdui0cvfWi5GiVVyHP6OB8KPuSisP2'; /** * Send an API call. If the api_call parameter is specified it will send that. @@ -27,9 +23,9 @@ beestat.api2.api_key = 'ER9Dz8t05qUdui0cvfWi5GiVVyHP6OB8KPuSisP2'; * * @param {Object=} opt_api_call The API call object. * - * @return {beestat.api2} This. + * @return {beestat.api} This. */ -beestat.api2.prototype.send = function(opt_api_call) { +beestat.api.prototype.send = function(opt_api_call) { var self = this; this.xhr_ = new XMLHttpRequest(); @@ -37,7 +33,7 @@ beestat.api2.prototype.send = function(opt_api_call) { // If passing an actual API call, fire it off! if (opt_api_call !== undefined) { // Add in the API key - opt_api_call.api_key = beestat.api2.api_key; + opt_api_call.api_key = beestat.api.api_key; // Build the query string var query_string = Object.keys(opt_api_call) @@ -66,9 +62,17 @@ beestat.api2.prototype.send = function(opt_api_call) { }); if (uncached_batch_api_calls.length === 0) { - // If no API calls left, just fire off the callback with the data. + /** + * If no API calls left, just fire off the callback with the data. + * Timeout makes this behave like an actual API call in terms of + * program flow. Without this, if there is a rerender() inside a + * callback, the rerender can happen during a render which causes + * problems. + */ if (this.callback_ !== undefined) { - this.callback_(this.cached_batch_api_calls_); + setTimeout(function() { + self.callback_(self.cached_batch_api_calls_); + }, 0); } } else { // If more than one API call left, fire off a batch API call. @@ -80,7 +84,16 @@ beestat.api2.prototype.send = function(opt_api_call) { var cached = this.get_cached_(single_api_call); if (cached !== undefined) { if (this.callback_ !== undefined) { - this.callback_(cached.data); + + /** + * Timeout makes this behave like an actual API call in terms of + * program flow. Without this, if there is a rerender() inside a + * callback, the rerender can happen during a render which causes + * problems. + */ + setTimeout(function() { + self.callback_(cached.data); + }, 0); } } else { this.send(single_api_call); @@ -99,9 +112,9 @@ beestat.api2.prototype.send = function(opt_api_call) { * @param {Object=} opt_args Optional arguments. * @param {string=} opt_alias Optional alias (required for batch API calls). * - * @return {beestat.api2} This. + * @return {beestat.api} This. */ -beestat.api2.prototype.add_call = function(resource, method, opt_args, opt_alias) { +beestat.api.prototype.add_call = function(resource, method, opt_args, opt_alias) { var api_call = { 'resource': resource, 'method': method, @@ -121,9 +134,9 @@ beestat.api2.prototype.add_call = function(resource, method, opt_args, opt_alias * * @param {Function} callback The callback function. * - * @return {beestat.api2} This. + * @return {beestat.api} This. */ -beestat.api2.prototype.set_callback = function(callback) { +beestat.api.prototype.set_callback = function(callback) { this.callback_ = callback; return this; @@ -134,7 +147,7 @@ beestat.api2.prototype.set_callback = function(callback) { * * @param {string} response_text Whatever the XHR request returned. */ -beestat.api2.prototype.load_ = function(response_text) { +beestat.api.prototype.load_ = function(response_text) { var response; try { response = window.JSON.parse(response_text); @@ -209,7 +222,7 @@ beestat.api2.prototype.load_ = function(response_text) { * * @return {boolean} Whether or not this is a batch API call. */ -beestat.api2.prototype.is_batch_ = function() { +beestat.api.prototype.is_batch_ = function() { return this.api_calls_.length > 1; }; @@ -220,24 +233,14 @@ beestat.api2.prototype.is_batch_ = function() { * @param {*} data The data to cache. * @param {string} until Timestamp to cache until. */ -beestat.api2.prototype.cache_ = function(api_call, data, until) { +beestat.api.prototype.cache_ = function(api_call, data, until) { var server_date = moment(this.xhr_.getResponseHeader('date')); var duration = moment.duration(moment(until).diff(server_date)); - beestat.api2.cache[this.get_key_(api_call)] = { + beestat.api.cache[this.get_key_(api_call)] = { 'data': data, 'until': moment().add(duration.asSeconds(), 'seconds') }; - - /** - * Save the cache to localStorage to persist across reloads. It just happens - * to be annoying that localStorage only supports strings so I prefer to - * deal with myself. - */ - // window.localStorage.setItem( - // 'api_cache', - // window.JSON.stringify(beestat.api2.cache) - // ); }; /** @@ -247,8 +250,8 @@ beestat.api2.prototype.cache_ = function(api_call, data, until) { * * @return {*} The cached data, or undefined if none. */ -beestat.api2.prototype.get_cached_ = function(api_call) { - var cached = beestat.api2.cache[this.get_key_(api_call)]; +beestat.api.prototype.get_cached_ = function(api_call) { + var cached = beestat.api.cache[this.get_key_(api_call)]; if ( cached !== undefined && moment().isAfter(cached.until) === false @@ -266,67 +269,6 @@ beestat.api2.prototype.get_cached_ = function(api_call) { * * @return {string} The cache key. */ -beestat.api2.prototype.get_key_ = function(api_call) { +beestat.api.prototype.get_key_ = function(api_call) { return api_call.resource + '.' + api_call.method + '.' + api_call.arguments; }; - -// TODO OLD DELETE THIS -beestat.api = function(resource, method, args, callback) { - var xhr = new XMLHttpRequest(); - - var load = function() { - var response; - try { - response = window.JSON.parse(this.responseText); - } catch (e) { - beestat.error('API returned invalid response.', this.responseText); - return; - } - - if ( - response.data && - ( - response.data.error_code === 1004 || // Session is expired. - response.data.error_code === 10001 || // Could not get first token. - response.data.error_code === 10002 || // Could not refresh ecobee token; no token found. - response.data.error_code === 10003 // Could not refresh ecobee token; ecobee returned no token. - ) - ) { - window.location.href = '/'; - } else if (response.data && response.data.error_code === 1209) { - // Could not get lock; safe to ignore as that means sync is running. - } else if (response.success !== true) { - beestat.error( - 'API call failed: ' + response.data.error_message, - JSON.stringify(response, null, 2) - ); - } else if (callback !== undefined) { - callback(response.data); - } - }; - xhr.addEventListener('load', load); - - var api_key = 'ER9Dz8t05qUdui0cvfWi5GiVVyHP6OB8KPuSisP2'; - if (resource === 'api' && method === 'batch') { - args.forEach(function(api_call, i) { - if (args[i].arguments !== undefined) { - args[i].arguments = JSON.stringify(args[i].arguments); - } - }); - xhr.open( - 'POST', - '../api/?batch=' + JSON.stringify(args) + - '&api_key=' + api_key - ); - } else { - xhr.open( - 'POST', - '../api/?resource=' + resource + - '&method=' + method + - (args === undefined ? '' : '&arguments=' + JSON.stringify(args)) + - '&api_key=' + api_key - ); - } - - xhr.send(); -}; diff --git a/js/beestat/poll.js b/js/beestat/poll.js index a8081d7..fc93ab9 100644 --- a/js/beestat/poll.js +++ b/js/beestat/poll.js @@ -34,66 +34,71 @@ beestat.disable_poll = function() { * Poll the database for changes and update the cache. */ beestat.poll = function() { - beestat.api( - 'api', - 'batch', - [ - { - 'resource': 'user', - 'method': 'read_id', - 'alias': 'user' - }, - { - 'resource': 'thermostat', - 'method': 'read_id', - 'alias': 'thermostat', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'sensor', - 'method': 'read_id', - 'alias': 'sensor', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'ecobee_thermostat', - 'method': 'read_id', - 'alias': 'ecobee_thermostat', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'ecobee_sensor', - 'method': 'read_id', - 'alias': 'ecobee_sensor', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - } - ], - function(response) { - beestat.cache.set('user', response.user); - beestat.cache.set('thermostat', response.thermostat); - beestat.cache.set('sensor', response.sensor); - beestat.cache.set('ecobee_thermostat', response.ecobee_thermostat); - beestat.cache.set('ecobee_sensor', response.ecobee_sensor); - beestat.enable_poll(); - beestat.dispatcher.dispatchEvent('poll'); - } + + var api = new beestat.api(); + + api.add_call( + 'user', + 'read_id', + {}, + 'user' ); + + api.add_call( + 'thermostat', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'thermostat' + ); + + api.add_call( + 'sensor', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'sensor' + ); + + api.add_call( + 'ecobee_thermostat', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'ecobee_thermostat' + ); + + api.add_call( + 'ecobee_sensor', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'ecobee_sensor' + ); + + api.set_callback(function(response) { + beestat.cache.set('user', response.user); + beestat.cache.set('thermostat', response.thermostat); + beestat.cache.set('sensor', response.sensor); + beestat.cache.set('ecobee_thermostat', response.ecobee_thermostat); + beestat.cache.set('ecobee_sensor', response.ecobee_sensor); + beestat.enable_poll(); + beestat.dispatcher.dispatchEvent('poll'); + }); + + api.send(); }; beestat.default_poll_interval = 300000; // 5 minutes diff --git a/js/beestat/setting.js b/js/beestat/setting.js index ad82e70..165b160 100644 --- a/js/beestat/setting.js +++ b/js/beestat/setting.js @@ -56,27 +56,25 @@ beestat.setting = function(key, opt_value, opt_callback) { settings[key] = opt_value; } - var api_calls = []; + var api = new beestat.api(); + api.set_callback(opt_callback); + for (var k in settings) { if (user.json_settings[k] !== settings[k]) { user.json_settings[k] = settings[k]; beestat.dispatcher.dispatchEvent('setting.' + k); - api_calls.push({ - 'resource': 'user', - 'method': 'update_setting', - 'arguments': { + api.add_call( + 'user', + 'update_setting', + { 'key': k, 'value': settings[k] } - }); + ); } } - if (api_calls.length > 0) { - beestat.api('api', 'batch', api_calls, opt_callback); - } else if (opt_callback !== undefined) { - opt_callback(); - } + api.send(); }; diff --git a/js/beestat/thermostat_group.js b/js/beestat/thermostat_group.js index c22065d..0a75cb0 100644 --- a/js/beestat/thermostat_group.js +++ b/js/beestat/thermostat_group.js @@ -64,7 +64,7 @@ beestat.generate_temperature_profile = function(callback) { } } else { beestat.cache.delete('data.comparison_temperature_profile'); - new beestat.api2() + new beestat.api() .add_call( 'thermostat_group', 'generate_temperature_profile', @@ -106,7 +106,7 @@ beestat.get_comparison_scores = function(callback) { 'resist' ]; - var api = new beestat.api2(); + var api = new beestat.api(); types.forEach(function(type) { beestat.cache.delete('data.comparison_scores_' + type); api.add_call( diff --git a/js/component/alert.js b/js/component/alert.js index e1cf6a5..14bc0fb 100644 --- a/js/component/alert.js +++ b/js/component/alert.js @@ -251,14 +251,16 @@ beestat.component.alert.prototype.decorate_detail_ = function(parent) { .set_background_hover_color(beestat.style.color.red.light) .render(dismiss_container) .addEventListener('click', function() { - beestat.api( - 'thermostat', - 'dismiss_alert', - { - 'thermostat_id': beestat.setting('thermostat_id'), - 'guid': self.alert_.guid - } - ); + new beestat.api() + .add_call( + 'thermostat', + 'dismiss_alert', + { + 'thermostat_id': beestat.setting('thermostat_id'), + 'guid': self.alert_.guid + } + ) + .send(); beestat.cache.thermostat[beestat.setting('thermostat_id')].json_alerts.forEach(function(alert) { if (alert.guid === self.alert_.guid) { @@ -286,14 +288,16 @@ beestat.component.alert.prototype.decorate_detail_ = function(parent) { .set_background_hover_color(beestat.style.color.red.light) .render(restore_container) .addEventListener('click', function() { - beestat.api( - 'thermostat', - 'restore_alert', - { - 'thermostat_id': beestat.setting('thermostat_id'), - 'guid': self.alert_.guid - } - ); + new beestat.api() + .add_call( + 'thermostat', + 'restore_alert', + { + 'thermostat_id': beestat.setting('thermostat_id'), + 'guid': self.alert_.guid + } + ) + .send(); beestat.cache.thermostat[beestat.setting('thermostat_id')].json_alerts.forEach(function(alert) { if (alert.guid === self.alert_.guid) { diff --git a/js/component/card/aggregate_runtime.js b/js/component/card/aggregate_runtime.js index 7812fef..5f13ce9 100644 --- a/js/component/card/aggregate_runtime.js +++ b/js/component/card/aggregate_runtime.js @@ -6,6 +6,9 @@ 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. @@ -712,10 +715,10 @@ beestat.component.card.aggregate_runtime.prototype.get_subtitle_ = function() { }; /** - * Determine whether or not enough data is currently available to render this - * card. + * Is aggregate runtime data available? * - * @return {boolean} + * @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. @@ -738,7 +741,10 @@ beestat.component.card.aggregate_runtime.prototype.data_available_ = function() beestat.setting('aggregate_runtime_time_period') )); } - required_sync_begin = moment.max(required_sync_begin, moment(thermostat.first_connected)); + required_sync_begin = moment.max( + required_sync_begin, + moment(thermostat.first_connected) + ); var required_sync_end = moment().subtract(1, 'hour'); // Percentage @@ -772,18 +778,20 @@ beestat.component.card.aggregate_runtime.prototype.get_data_ = function() { var self = this; var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')]; - beestat.api( - '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') - }, - function(response) { + 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(); }; diff --git a/js/component/card/comparison_settings.js b/js/component/card/comparison_settings.js index 0b3bfed..232a24c 100644 --- a/js/component/card/comparison_settings.js +++ b/js/component/card/comparison_settings.js @@ -72,7 +72,7 @@ beestat.component.card.comparison_settings.prototype.decorate_contents_ = functi beestat.remove_poll_interval(poll_interval); beestat.dispatcher.removeEventListener('poll.home_comparisons_load'); - new beestat.api2() + new beestat.api() .add_call( 'thermostat_group', 'generate_temperature_profiles', diff --git a/js/component/card/recent_activity.js b/js/component/card/recent_activity.js index 72060bc..0619e39 100644 --- a/js/component/card/recent_activity.js +++ b/js/component/card/recent_activity.js @@ -1385,7 +1385,7 @@ beestat.component.card.recent_activity.prototype.get_data_ = function() { var self = this; var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')]; - new beestat.api2() + new beestat.api() .add_call( 'ecobee_runtime_thermostat', 'get_recent_activity', diff --git a/js/component/header.js b/js/component/header.js index 60d4502..fbf6ad3 100644 --- a/js/component/header.js +++ b/js/component/header.js @@ -150,13 +150,15 @@ beestat.component.header.prototype.decorate_ = function(parent) { .set_text('Log Out') .set_icon('exit_to_app') .set_callback(function() { - beestat.api( - 'user', - 'log_out', - {'all': false}, - function() { + new beestat.api() + .set_callback(function() { window.location.reload(); - } - ); + }) + .add_call( + 'user', + 'log_out', + {'all': false} + ) + .send(); })); }; diff --git a/js/component/modal/change_system_type.js b/js/component/modal/change_system_type.js index 22fa66f..1ff7826 100644 --- a/js/component/modal/change_system_type.js +++ b/js/component/modal/change_system_type.js @@ -129,7 +129,7 @@ beestat.component.modal.change_system_type.prototype.get_buttons_ = function() { .set_background_hover_color() .removeEventListener('click'); - new beestat.api2() + new beestat.api() .add_call( 'thermostat_group', 'update_system_types', diff --git a/js/js.php b/js/js.php index 3c69041..5f63ea0 100644 --- a/js/js.php +++ b/js/js.php @@ -19,7 +19,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; diff --git a/js/layer/load.js b/js/layer/load.js index 4c2fffe..c3f0286 100644 --- a/js/layer/load.js +++ b/js/layer/load.js @@ -32,195 +32,208 @@ beestat.layer.load.prototype.decorate_ = function(parent) { (new beestat.component.loading()).render(loading_text); - var batch = [ - { - 'resource': 'thermostat', - 'method': 'sync', - 'alias': 'thermostat_sync' - }, - { - 'resource': 'sensor', - 'method': 'sync', - 'alias': 'sensor_sync' - }, - { - 'resource': 'user', - 'method': 'read_id', - 'alias': 'user' - }, - { - 'resource': 'thermostat', - 'method': 'read_id', - 'alias': 'thermostat', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'thermostat_group', - 'method': 'read_id', - 'alias': 'thermostat_group' - }, - { - 'resource': 'sensor', - 'method': 'read_id', - 'alias': 'sensor', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'ecobee_thermostat', - 'method': 'read_id', - 'alias': 'ecobee_thermostat', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'ecobee_sensor', - 'method': 'read_id', - 'alias': 'ecobee_sensor', - 'arguments': { - 'attributes': { - 'inactive': 0 - } - } - }, - { - 'resource': 'address', - 'method': 'read_id', - 'alias': 'address' - }, - { - 'resource': 'announcement', - 'method': 'read_id', - 'alias': 'announcement' - } - ]; + var api = new beestat.api(); - // First up, sync all thermostats and sensors. - beestat.api( - 'api', - 'batch', - batch, - function(response) { - beestat.cache.set('user', response.user); + api.add_call( + 'thermostat', + 'sync', + {}, + 'thermostat_sync' + ); - // Rollbar isn't defined on dev. - if (window.Rollbar !== undefined) { - Rollbar.configure({ - 'payload': { - 'person': { - 'id': beestat.get_user().user_id - }, - 'beestat': { - 'user_id': beestat.get_user().user_id - } + api.add_call( + 'sensor', + 'sync', + {}, + 'sensor_sync' + ); + + api.add_call( + 'user', + 'read_id', + {}, + 'user' + ); + + api.add_call( + 'thermostat', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'thermostat' + ); + + api.add_call( + 'thermostat_group', + 'read_id', + {}, + 'thermostat_group' + ); + + api.add_call( + 'sensor', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'sensor' + ); + + api.add_call( + 'ecobee_thermostat', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'ecobee_thermostat' + ); + + api.add_call( + 'ecobee_sensor', + 'read_id', + { + 'attributes': { + 'inactive': 0 + } + }, + 'ecobee_sensor' + ); + + api.add_call( + 'address', + 'read_id', + {}, + 'address' + ); + + api.add_call( + 'announcement', + 'read_id', + {}, + 'announcement' + ); + + api.set_callback(function(response) { + beestat.cache.set('user', response.user); + + // Rollbar isn't defined on dev. + if (window.Rollbar !== undefined) { + Rollbar.configure({ + 'payload': { + 'person': { + 'id': beestat.get_user().user_id + }, + 'beestat': { + 'user_id': beestat.get_user().user_id } - }); - } + } + }); + } - beestat.cache.set('thermostat', response.thermostat); - beestat.cache.set('thermostat_group', response.thermostat_group); - beestat.cache.set('sensor', response.sensor); + beestat.cache.set('thermostat', response.thermostat); + beestat.cache.set('thermostat_group', response.thermostat_group); + beestat.cache.set('sensor', response.sensor); - beestat.cache.set('ecobee_thermostat', response.ecobee_thermostat); - beestat.cache.set('ecobee_sensor', response.ecobee_sensor); - beestat.cache.set('address', response.address); - beestat.cache.set('announcement', response.announcement); - beestat.cache.set('ecobee_runtime_thermostat', []); - beestat.cache.set('aggregate_runtime', []); + beestat.cache.set('ecobee_thermostat', response.ecobee_thermostat); + beestat.cache.set('ecobee_sensor', response.ecobee_sensor); + beestat.cache.set('address', response.address); + beestat.cache.set('announcement', response.announcement); + beestat.cache.set('ecobee_runtime_thermostat', []); + beestat.cache.set('aggregate_runtime', []); - // Set the active thermostat_id if this is your first time visiting. - if (beestat.setting('thermostat_id') === undefined) { - beestat.setting( - 'thermostat_id', - $.values(beestat.cache.thermostat)[0].thermostat_id - ); - } + // Set the active thermostat_id if this is your first time visiting. + if (beestat.setting('thermostat_id') === undefined) { + beestat.setting( + 'thermostat_id', + $.values(beestat.cache.thermostat)[0].thermostat_id + ); + } - // Change the active thermostat_id if the one you have is no longer valid. - if (response.thermostat[beestat.setting('thermostat_id')] === undefined) { - beestat.setting('thermostat_id', Object.keys(response.thermostat)[0]); - } + // Change the active thermostat_id if the one you have is no longer valid. + if (response.thermostat[beestat.setting('thermostat_id')] === undefined) { + beestat.setting('thermostat_id', Object.keys(response.thermostat)[0]); + } - var thermostat = beestat.cache.thermostat[ - beestat.setting('thermostat_id') - ]; - var ecobee_thermostat = beestat.cache.ecobee_thermostat[ - thermostat.ecobee_thermostat_id - ]; + var thermostat = beestat.cache.thermostat[ + beestat.setting('thermostat_id') + ]; + var ecobee_thermostat = beestat.cache.ecobee_thermostat[ + thermostat.ecobee_thermostat_id + ]; - // Rename series if only one stage is available. - if (ecobee_thermostat.json_settings.coolStages === 1) { - beestat.series.compressor_cool_1.name = 'Cool'; - } - if (ecobee_thermostat.json_settings.heatStages === 1) { - beestat.series.compressor_heat_1.name = 'Heat'; - } + // Rename series if only one stage is available. + if (ecobee_thermostat.json_settings.coolStages === 1) { + beestat.series.compressor_cool_1.name = 'Cool'; + } + if (ecobee_thermostat.json_settings.heatStages === 1) { + beestat.series.compressor_heat_1.name = 'Heat'; + } - // Fix some other stuff for non-heat-pump. - if (ecobee_thermostat.json_settings.hasHeatPump === false) { - beestat.series.auxiliary_heat_1.name = - beestat.series.compressor_heat_1.name; - beestat.series.auxiliary_heat_1.color = - beestat.series.compressor_heat_1.color; - beestat.series.auxiliary_heat_2.name = - beestat.series.compressor_heat_2.name; - beestat.series.auxiliary_heat_2.color = - beestat.series.compressor_heat_2.color; - beestat.series.auxiliary_heat_3.name = 'Heat 3'; - beestat.series.auxiliary_heat_3.color = '#d35400'; - } + // Fix some other stuff for non-heat-pump. + if (ecobee_thermostat.json_settings.hasHeatPump === false) { + beestat.series.auxiliary_heat_1.name = + beestat.series.compressor_heat_1.name; + beestat.series.auxiliary_heat_1.color = + beestat.series.compressor_heat_1.color; + beestat.series.auxiliary_heat_2.name = + beestat.series.compressor_heat_2.name; + beestat.series.auxiliary_heat_2.color = + beestat.series.compressor_heat_2.color; + beestat.series.auxiliary_heat_3.name = 'Heat 3'; + beestat.series.auxiliary_heat_3.color = '#d35400'; + } - /* - * Fire off an API call to sync. The cron job will eventually run but this - * ensures things get moving quicker. - */ - beestat.api( + /* + * Fire off an API call to sync. The cron job will eventually run but this + * ensures things get moving quicker. + */ + new beestat.api() + .add_call( 'ecobee_runtime_thermostat', 'sync', { 'thermostat_id': thermostat.thermostat_id } - ); + ) + .send(); - // Enable polling for live updates - beestat.enable_poll(); + // Enable polling for live updates + beestat.enable_poll(); - (new beestat.layer.dashboard()).render(); + (new beestat.layer.dashboard()).render(); - /* - * If never seen an announcement, or if there is an unread important - * announcement, show the modal. - */ - var last_read_announcement_id = beestat.setting('last_read_announcement_id'); + /* + * If never seen an announcement, or if there is an unread important + * announcement, show the modal. + */ + var last_read_announcement_id = beestat.setting('last_read_announcement_id'); - var most_recent_important_announcement_id; - var announcements = $.values(beestat.cache.announcement).reverse(); - for (var i = 0; i < announcements.length; i++) { - if (announcements[i].important === true) { - most_recent_important_announcement_id = announcements[i].announcement_id; - break; - } - } - - if ( - last_read_announcement_id === undefined || - ( - most_recent_important_announcement_id !== undefined && - last_read_announcement_id < most_recent_important_announcement_id - ) - ) { - (new beestat.component.modal.announcements()).render(); + var most_recent_important_announcement_id; + var announcements = $.values(beestat.cache.announcement).reverse(); + for (var i = 0; i < announcements.length; i++) { + if (announcements[i].important === true) { + most_recent_important_announcement_id = announcements[i].announcement_id; + break; } } - ); + + if ( + last_read_announcement_id === undefined || + ( + most_recent_important_announcement_id !== undefined && + last_read_announcement_id < most_recent_important_announcement_id + ) + ) { + (new beestat.component.modal.announcements()).render(); + } + }); + + api.send(); };