mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
Loading now doesn't break if the sync fails, and as a bonus that made it trivial to display whether or not ecobee is down.
This commit is contained in:
parent
deaf81e214
commit
a6564305b0
@ -857,7 +857,7 @@ final class database extends \mysqli {
|
||||
');
|
||||
$row = $result->fetch_assoc();
|
||||
if($row['lock'] !== 1) {
|
||||
throw new \Exception('Could not get lock.', 1209);
|
||||
throw new exception('Could not get lock.', 1209);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,8 @@ class runtime extends cora\api {
|
||||
*
|
||||
* @param int $thermostat_id Optional thermostat_id to sync. If not set will
|
||||
* sync all thermostats attached to this user.
|
||||
*
|
||||
* @return boolean true if the sync ran, false if not.
|
||||
*/
|
||||
public function sync($thermostat_id = null) {
|
||||
// Skip this for the demo
|
||||
@ -42,6 +44,7 @@ class runtime extends cora\api {
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
try {
|
||||
if($thermostat_id === null) {
|
||||
$thermostat_ids = array_keys(
|
||||
$this->api(
|
||||
@ -91,6 +94,9 @@ class runtime extends cora\api {
|
||||
|
||||
$this->database->release_lock($lock_name);
|
||||
}
|
||||
} catch(cora\exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,9 +46,10 @@ class sensor extends cora\crud {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync all sensors connected to this account. Once Nest support is
|
||||
* added this will need to check for all connected accounts and run the
|
||||
* appropriate ones.
|
||||
* Sync all sensors for the current user. If we fail to get a lock, fail
|
||||
* silently (catch the exception) and just return false.
|
||||
*
|
||||
* @return boolean true if the sync ran, false if not.
|
||||
*/
|
||||
public function sync() {
|
||||
// Skip this for the demo
|
||||
@ -56,6 +57,7 @@ class sensor extends cora\crud {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$lock_name = 'sensor->sync(' . $this->session->get_user_id() . ')';
|
||||
$this->database->get_lock($lock_name);
|
||||
|
||||
@ -70,6 +72,9 @@ class sensor extends cora\crud {
|
||||
);
|
||||
|
||||
$this->database->release_lock($lock_name);
|
||||
} catch(cora\exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,14 +22,18 @@ class thermostat extends cora\crud {
|
||||
];
|
||||
|
||||
/**
|
||||
* Sync all thermostats for the current user with their associated service.
|
||||
* Sync all thermostats for the current user. If we fail to get a lock, fail
|
||||
* silently (catch the exception) and just return false.
|
||||
*
|
||||
* @return boolean true if the sync ran, false if not.
|
||||
*/
|
||||
public function sync() {
|
||||
// Skip this for the demo
|
||||
if($this->setting->is_demo() === true) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$lock_name = 'thermostat->sync(' . $this->session->get_user_id() . ')';
|
||||
$this->database->get_lock($lock_name);
|
||||
|
||||
@ -42,6 +46,11 @@ class thermostat extends cora\crud {
|
||||
);
|
||||
|
||||
$this->database->release_lock($lock_name);
|
||||
|
||||
return true;
|
||||
} catch(cora\exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,6 @@ beestat.ecobee_thermostat_models = {
|
||||
'vulcanSmart': 'SmartThermostat'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a default value for an argument if it is not currently set.
|
||||
*
|
||||
@ -106,16 +105,6 @@ beestat.get_thermostat_color = function(thermostat_id) {
|
||||
return beestat.style.color.bluegray.dark;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current user.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
beestat.get_user = function() {
|
||||
var user_id = Object.keys(beestat.cache.user)[0];
|
||||
return beestat.cache.user[user_id];
|
||||
};
|
||||
|
||||
// Register service worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
|
@ -178,8 +178,6 @@ beestat.api.prototype.load_ = function(response_text) {
|
||||
) {
|
||||
window.location.href = '/';
|
||||
return;
|
||||
} 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,
|
||||
|
25
js/beestat/ecobee.js
Normal file
25
js/beestat/ecobee.js
Normal file
@ -0,0 +1,25 @@
|
||||
beestat.ecobee = {};
|
||||
|
||||
/**
|
||||
* Check to see if ecobee is down. If so, render the footer component.
|
||||
*/
|
||||
beestat.ecobee.notify_if_down = function() {
|
||||
if (
|
||||
beestat.cache !== undefined &&
|
||||
beestat.cache.thermostat !== undefined &&
|
||||
beestat.user.get() !== undefined
|
||||
) {
|
||||
var last_update = moment.utc(beestat.user.get().sync_status.thermostat);
|
||||
var down = last_update.isBefore(moment().subtract(15, 'minutes'));
|
||||
|
||||
if (beestat.ecobee.down_notification_ === undefined) {
|
||||
beestat.ecobee.down_notification_ = new beestat.component.down_notification();
|
||||
}
|
||||
|
||||
if (down === true) {
|
||||
beestat.ecobee.down_notification_.render($('body'));
|
||||
} else {
|
||||
beestat.ecobee.down_notification_.dispose();
|
||||
}
|
||||
}
|
||||
};
|
@ -95,6 +95,8 @@ beestat.poll = function() {
|
||||
beestat.cache.set('ecobee_sensor', response.ecobee_sensor);
|
||||
beestat.enable_poll();
|
||||
beestat.dispatcher.dispatchEvent('poll');
|
||||
|
||||
beestat.ecobee.notify_if_down();
|
||||
});
|
||||
|
||||
api.send();
|
||||
|
@ -6,8 +6,6 @@ beestat.component = function() {
|
||||
// Give every component a state object to use for storing data.
|
||||
this.state_ = {};
|
||||
|
||||
// this.render_count_ = 0;
|
||||
|
||||
this.layer_ = beestat.current_layer;
|
||||
|
||||
if (this.rerender_on_breakpoint_ === true) {
|
||||
@ -28,6 +26,7 @@ beestat.extend(beestat.component, rocket.EventTarget);
|
||||
* @return {beestat.component} This
|
||||
*/
|
||||
beestat.component.prototype.render = function(parent) {
|
||||
if (this.rendered_ === false) {
|
||||
var self = this;
|
||||
|
||||
if (parent !== undefined) {
|
||||
@ -46,7 +45,7 @@ beestat.component.prototype.render = function(parent) {
|
||||
|
||||
// The render function was called.
|
||||
this.rendered_ = true;
|
||||
// this.render_count_++;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -71,21 +70,20 @@ beestat.component.prototype.rerender = function() {
|
||||
setTimeout(function() {
|
||||
self.dispatchEvent('render');
|
||||
}, 0);
|
||||
|
||||
// this.render_count_++;
|
||||
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove this component from the page.
|
||||
*/
|
||||
beestat.component.prototype.dispose = function() {
|
||||
var child = this.component_container_.parentNode();
|
||||
if (this.rendered_ === true) {
|
||||
var child = this.component_container_;
|
||||
var parent = child.parentNode();
|
||||
parent.removeChild(child);
|
||||
this.rendered_ = false;
|
||||
}
|
||||
};
|
||||
|
||||
beestat.component.prototype.decorate_ = function() {
|
||||
|
34
js/component/down_notification.js
Normal file
34
js/component/down_notification.js
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Ecobee is down!
|
||||
*/
|
||||
beestat.component.down_notification = function() {
|
||||
beestat.component.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.down_notification, beestat.component);
|
||||
|
||||
beestat.component.down_notification.prototype.rerender_on_breakpoint_ = false;
|
||||
|
||||
/**
|
||||
* Decorate a floating banner at the bottom of the page.
|
||||
*
|
||||
* @param {rocket.Elements} parent
|
||||
*/
|
||||
beestat.component.down_notification.prototype.decorate_ = function(parent) {
|
||||
var div = $.createElement('div');
|
||||
div.style({
|
||||
'position': 'fixed',
|
||||
'bottom': '0px',
|
||||
'left': '0px',
|
||||
'width': '100%',
|
||||
'text-align': 'center',
|
||||
'padding-left': beestat.style.size.gutter,
|
||||
'padding-right': beestat.style.size.gutter,
|
||||
'background': beestat.style.color.red.dark
|
||||
});
|
||||
|
||||
var last_update = moment.utc(beestat.user.get().sync_status.thermostat).local()
|
||||
.format('h:m a');
|
||||
div.appendChild($.createElement('p').innerText('Ecobee seems to be down. Your data will update as soon as possible. Last update was at ' + last_update + '.'));
|
||||
|
||||
parent.appendChild(div);
|
||||
};
|
@ -19,7 +19,6 @@ beestat.component.menu.prototype.decorate_ = function(parent) {
|
||||
.set_bubble_text(this.bubble_text_)
|
||||
.set_bubble_color(this.bubble_color_)
|
||||
.set_text_color('#fff')
|
||||
// .set_background_hover_color(beestat.style.color.bluegray.light)
|
||||
.set_background_hover_color('rgba(255, 255, 255, 0.1')
|
||||
.addEventListener('click', function() {
|
||||
// Did I just try to open the same menu as last time?
|
||||
@ -41,12 +40,20 @@ beestat.component.menu.prototype.decorate_ = function(parent) {
|
||||
* Close this menu by hiding the container and removing the event listeners.
|
||||
*/
|
||||
beestat.component.menu.prototype.dispose = function() {
|
||||
var self = this;
|
||||
beestat.component.menu.open_menu.rendered_ = false;
|
||||
this.rendered_ = false;
|
||||
|
||||
if (beestat.component.menu.open_menu !== undefined) {
|
||||
var container = beestat.component.menu.open_menu.container_;
|
||||
container.style('transform', 'scale(0)');
|
||||
|
||||
delete beestat.component.menu.open_menu;
|
||||
setTimeout(function() {
|
||||
self.menu_items_.forEach(function(menu_item) {
|
||||
menu_item.dispose();
|
||||
});
|
||||
|
||||
container.parentNode().removeChild(container);
|
||||
}, 200);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
||||
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/user.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/beestat/ecobee.js"></script>' . PHP_EOL;
|
||||
|
||||
// Layer
|
||||
echo '<script src="/js/layer.js"></script>' . PHP_EOL;
|
||||
@ -42,6 +43,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
||||
// Component
|
||||
echo '<script src="/js/component.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/alert.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/down_notification.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/card.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;
|
||||
|
@ -22,6 +22,8 @@ beestat.layer.prototype.render = function() {
|
||||
|
||||
body.innerHTML('');
|
||||
body.appendChild(container);
|
||||
|
||||
beestat.ecobee.notify_if_down();
|
||||
};
|
||||
|
||||
beestat.layer.prototype.decorate_ = function(parent) {
|
||||
|
@ -128,7 +128,6 @@ beestat.layer.load.prototype.decorate_ = function(parent) {
|
||||
);
|
||||
|
||||
api.set_callback(function(response) {
|
||||
|
||||
beestat.cache.set('user', response.user);
|
||||
|
||||
// Rollbar isn't defined on dev.
|
||||
@ -217,6 +216,8 @@ beestat.layer.load.prototype.decorate_ = function(parent) {
|
||||
|
||||
(new beestat.layer.dashboard()).render();
|
||||
|
||||
beestat.ecobee.notify_if_down();
|
||||
|
||||
/*
|
||||
* If never seen an announcement, or if there is an unread important
|
||||
* announcement, show the modal.
|
||||
|
Loading…
x
Reference in New Issue
Block a user