2018-01-01 18:56:07 +00:00
|
|
|
|
function startApp()
|
2017-04-16 11:40:34 +00:00
|
|
|
|
{
|
2018-03-19 06:45:54 +00:00
|
|
|
|
// Source: https://github.com/axios/axios/issues/164
|
|
|
|
|
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
|
|
|
|
|
var config = err.config;
|
|
|
|
|
// If config does not exist or the retry option is not set, reject
|
|
|
|
|
if(!config || !config.retry) return Promise.reject(err);
|
|
|
|
|
|
|
|
|
|
// Set the variable for keeping track of the retry count
|
|
|
|
|
config.__retryCount = config.__retryCount || 0;
|
|
|
|
|
|
|
|
|
|
// Check if we've maxed out the total number of retries
|
|
|
|
|
if(config.__retryCount >= config.retry) {
|
|
|
|
|
// Reject with the error
|
|
|
|
|
return Promise.reject(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Increase the retry count
|
|
|
|
|
config.__retryCount += 1;
|
|
|
|
|
|
|
|
|
|
// Create new promise to handle exponential backoff
|
|
|
|
|
var backoff = new Promise(function(resolve) {
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
resolve();
|
|
|
|
|
}, config.retryDelay || 1);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Return the promise in which recalls axios to retry the request
|
|
|
|
|
return backoff.then(function() {
|
|
|
|
|
return axios(config);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2018-01-22 22:01:49 +00:00
|
|
|
|
Vue.component('check', {
|
2018-01-23 14:06:51 +00:00
|
|
|
|
template: '<div class="check" :class="{ checked: value, disabled: disabled }" @keydown="handleKeyDown" @click="handleClick" tabindex="0"><div class="control"><div class="inner"></div></div><div class="label">{{ title }}</div></div>',
|
2018-01-22 22:01:49 +00:00
|
|
|
|
props: {
|
|
|
|
|
title: String,
|
|
|
|
|
value: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
2018-01-23 14:06:51 +00:00
|
|
|
|
},
|
|
|
|
|
disabled: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
2018-01-22 22:01:49 +00:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
|
handleClick: function()
|
|
|
|
|
{
|
2018-01-23 14:06:51 +00:00
|
|
|
|
if (this.disabled) return;
|
2018-01-22 22:01:49 +00:00
|
|
|
|
this.value = !this.value;
|
|
|
|
|
this.$emit('input', this.value);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleKeyDown: function(event)
|
|
|
|
|
{
|
|
|
|
|
if (event.keyCode == 32)
|
|
|
|
|
{
|
|
|
|
|
this.handleClick();
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Vue.component('radio', {
|
2018-01-23 14:06:51 +00:00
|
|
|
|
template: '<div class="radio" :class="{ checked: value == id, disabled: disabled }" @keydown="handleKeyDown" @click="handleClick" tabindex="0"><div class="control"><div class="inner"></div></div><div class="label">{{ title }}</div></div>',
|
2018-01-22 22:01:49 +00:00
|
|
|
|
props: {
|
|
|
|
|
title: String,
|
|
|
|
|
value: null,
|
2018-01-23 14:06:51 +00:00
|
|
|
|
id: null,
|
|
|
|
|
disabled: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: false
|
|
|
|
|
}
|
2018-01-22 22:01:49 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
|
handleClick: function()
|
|
|
|
|
{
|
2018-01-23 14:06:51 +00:00
|
|
|
|
if (this.disabled) return;
|
2018-01-22 22:01:49 +00:00
|
|
|
|
this.value = this.id;
|
|
|
|
|
this.$emit('input', this.value);
|
2018-01-23 14:06:51 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleKeyDown: function(event)
|
|
|
|
|
{
|
|
|
|
|
if (event.keyCode == 32)
|
|
|
|
|
{
|
|
|
|
|
this.handleClick();
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
}
|
2018-01-22 22:01:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2018-02-03 14:44:44 +00:00
|
|
|
|
|
|
|
|
|
Vue.component('range', {
|
|
|
|
|
template: '<div>' +
|
|
|
|
|
'<div class="start">' +
|
|
|
|
|
'<span class="value">{{ value.start }}</span>' +
|
|
|
|
|
'<div class="slidercontainer">' +
|
|
|
|
|
'<input type="range" min="0" max="4094" class="slider" v-model.number="value.start">' +
|
|
|
|
|
'</div>' +
|
|
|
|
|
'</div>' +
|
|
|
|
|
|
|
|
|
|
'<div class="end">' +
|
|
|
|
|
'<span class="value">{{ value.end }}</span>' +
|
|
|
|
|
'<div class="slidercontainer">' +
|
|
|
|
|
'<input type="range" min="1" max="4095" class="slider" v-model.number="value.end">' +
|
|
|
|
|
'</div>' +
|
|
|
|
|
'</div>' +
|
|
|
|
|
'</div>',
|
|
|
|
|
props: ['value'],
|
|
|
|
|
|
|
|
|
|
mounted: function()
|
|
|
|
|
{
|
|
|
|
|
this.oldValue = { start: this.value.start, end: this.value.end };
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
watch: {
|
|
|
|
|
value: {
|
|
|
|
|
handler: function(newValue)
|
|
|
|
|
{
|
|
|
|
|
if (newValue.start != this.oldValue.start)
|
|
|
|
|
{
|
|
|
|
|
if (newValue.start > newValue.end)
|
|
|
|
|
{
|
|
|
|
|
newValue.end = newValue.start + 1;
|
|
|
|
|
this.$emit('input', newValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (newValue.end != this.oldValue.end)
|
|
|
|
|
{
|
|
|
|
|
if (newValue.end < newValue.start)
|
|
|
|
|
{
|
|
|
|
|
newValue.start = newValue.end - 1;
|
|
|
|
|
this.$emit('input', newValue);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.oldValue.start = newValue.start;
|
|
|
|
|
this.oldValue.end = newValue.end;
|
|
|
|
|
},
|
|
|
|
|
deep: true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
var i18n = new VueI18n({
|
2018-03-19 06:45:54 +00:00
|
|
|
|
locale: navigator.language.split('-')[0],
|
2018-01-01 18:56:07 +00:00
|
|
|
|
fallbackLocale: 'en',
|
|
|
|
|
messages: messages
|
2017-03-25 15:36:04 +00:00
|
|
|
|
});
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
var app = new Vue({
|
|
|
|
|
el: '#app',
|
|
|
|
|
|
|
|
|
|
i18n: i18n,
|
|
|
|
|
|
|
|
|
|
data: {
|
2018-01-18 16:10:18 +00:00
|
|
|
|
notification: null,
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
loading: true,
|
|
|
|
|
saving: false,
|
2018-01-07 22:12:42 +00:00
|
|
|
|
savingSteps: false,
|
2018-01-01 18:56:07 +00:00
|
|
|
|
loadingIndicator: '|',
|
2018-01-03 20:44:34 +00:00
|
|
|
|
uploadProgress: false,
|
2018-02-03 14:44:44 +00:00
|
|
|
|
savingCalibration: false,
|
2018-01-01 18:56:07 +00:00
|
|
|
|
|
|
|
|
|
activeTab: 'status',
|
|
|
|
|
|
2018-02-12 21:13:03 +00:00
|
|
|
|
status: {
|
2018-01-01 18:56:07 +00:00
|
|
|
|
systemID: 'loading...',
|
|
|
|
|
version: 'loading...',
|
2018-02-12 21:13:03 +00:00
|
|
|
|
time: null,
|
|
|
|
|
timeOffset: 0,
|
|
|
|
|
resetReason: null,
|
|
|
|
|
stackTrace: false
|
2018-01-01 18:56:07 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
wifiStatus: {
|
|
|
|
|
ap: {
|
|
|
|
|
enabled: false,
|
|
|
|
|
ip: '0.0.0.0'
|
|
|
|
|
},
|
|
|
|
|
station: {
|
|
|
|
|
enabled: false,
|
|
|
|
|
status: 0,
|
|
|
|
|
ip: '0.0.0.0'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-07 22:12:42 +00:00
|
|
|
|
searchingLocation: false,
|
|
|
|
|
|
|
|
|
|
triggers: {
|
2018-01-12 15:20:28 +00:00
|
|
|
|
time: {
|
|
|
|
|
enabled: false,
|
2018-01-17 22:28:39 +00:00
|
|
|
|
transitionTime: null,
|
|
|
|
|
triggers: []
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
motion: {
|
|
|
|
|
enabled: false,
|
2018-04-22 08:30:34 +00:00
|
|
|
|
enabledDuringTimeTrigger: 0,
|
2018-02-16 21:02:55 +00:00
|
|
|
|
enabledDuringDay: false,
|
2018-01-17 22:28:39 +00:00
|
|
|
|
transitionTime: null,
|
|
|
|
|
delay: null,
|
2018-01-12 15:20:28 +00:00
|
|
|
|
triggers: []
|
|
|
|
|
}
|
2018-01-07 22:12:42 +00:00
|
|
|
|
},
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
connection: {
|
|
|
|
|
hostname: null,
|
|
|
|
|
accesspoint: true,
|
|
|
|
|
station: false,
|
|
|
|
|
ssid: null,
|
|
|
|
|
password: null,
|
|
|
|
|
dhcp: true,
|
|
|
|
|
ip: null,
|
|
|
|
|
subnetmask: null,
|
|
|
|
|
gateway: null
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-11 20:03:46 +00:00
|
|
|
|
system: {
|
2018-01-18 16:10:18 +00:00
|
|
|
|
ntpServer: null,
|
|
|
|
|
ntpInterval: 5,
|
2018-01-11 20:03:46 +00:00
|
|
|
|
lat: null,
|
|
|
|
|
lng: null,
|
|
|
|
|
pins: {
|
|
|
|
|
ledAP: null,
|
|
|
|
|
ledSTA: null,
|
|
|
|
|
apButton: null,
|
|
|
|
|
pwmSDA: null,
|
|
|
|
|
pwmSCL: null
|
|
|
|
|
},
|
|
|
|
|
pwmAddress: null,
|
|
|
|
|
pwmFrequency: null,
|
|
|
|
|
mapsAPIKey: ''
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-07 22:12:42 +00:00
|
|
|
|
allSteps: true,
|
|
|
|
|
allStepsValue: 0,
|
2018-01-11 20:03:46 +00:00
|
|
|
|
steps: [],
|
|
|
|
|
|
2018-01-17 15:57:14 +00:00
|
|
|
|
location: '',
|
|
|
|
|
|
|
|
|
|
fixedTimes: [],
|
2018-01-28 19:03:47 +00:00
|
|
|
|
relativeTimes: [],
|
|
|
|
|
|
|
|
|
|
calibration: null
|
2018-01-01 18:56:07 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
created: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
2018-01-18 16:10:18 +00:00
|
|
|
|
self.notificationTimer = null;
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
document.title = i18n.t('title');
|
2018-01-07 22:12:42 +00:00
|
|
|
|
var hash = window.location.hash.substr(1);
|
|
|
|
|
if (hash)
|
|
|
|
|
self.activeTab = hash;
|
2018-01-01 18:56:07 +00:00
|
|
|
|
|
2018-01-07 22:12:42 +00:00
|
|
|
|
self.startLoadingIndicator();
|
2018-01-01 18:56:07 +00:00
|
|
|
|
self.updateWiFiStatus();
|
|
|
|
|
|
2018-01-07 22:12:42 +00:00
|
|
|
|
self.disableStepsChanged = false;
|
|
|
|
|
self.savingStepsTimer = false;
|
2018-02-03 14:44:44 +00:00
|
|
|
|
self.savingCalibrationTimer = false;
|
2018-01-07 22:12:42 +00:00
|
|
|
|
|
2018-01-17 15:57:14 +00:00
|
|
|
|
var fixedTimes = [];
|
|
|
|
|
var relativeTimes = [];
|
|
|
|
|
|
|
|
|
|
for (var minutes = 0; minutes < 60 * 24; minutes += 15)
|
|
|
|
|
fixedTimes.push(minutes);
|
|
|
|
|
|
|
|
|
|
for (var minutes = -(4 * 60); minutes <= 4 * 60; minutes += 15)
|
|
|
|
|
relativeTimes.push(minutes);
|
|
|
|
|
|
|
|
|
|
self.fixedTimes = fixedTimes;
|
|
|
|
|
self.relativeTimes = relativeTimes;
|
|
|
|
|
|
2018-01-16 21:07:20 +00:00
|
|
|
|
|
|
|
|
|
// Sequential loading of all the settings makes sure
|
|
|
|
|
// we don't overload the ESP8266 with requests, as that
|
|
|
|
|
// can cause it to run out of memory easily.
|
2018-01-18 16:10:18 +00:00
|
|
|
|
// This is a horrible way to implement it, but I don't feel like
|
|
|
|
|
// including a big library or working out a clean short solution
|
|
|
|
|
// at the moment, and it works :)
|
2018-02-12 21:13:03 +00:00
|
|
|
|
self.loadStatus().then(function()
|
2018-01-16 21:07:20 +00:00
|
|
|
|
{
|
|
|
|
|
self.loadConnection().then(function()
|
2018-01-01 18:56:07 +00:00
|
|
|
|
{
|
2018-01-16 21:07:20 +00:00
|
|
|
|
self.loadSystem().then(function()
|
|
|
|
|
{
|
|
|
|
|
self.loadTimeTriggers().then(function()
|
|
|
|
|
{
|
2018-01-17 22:28:39 +00:00
|
|
|
|
self.loadMotionTriggers().then(function()
|
2018-01-16 21:07:20 +00:00
|
|
|
|
{
|
2018-01-17 22:28:39 +00:00
|
|
|
|
self.loadSteps().then(function()
|
|
|
|
|
{
|
|
|
|
|
self.stopLoadingIndicator();
|
|
|
|
|
self.loading = false;
|
|
|
|
|
});
|
2018-01-16 21:07:20 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2018-01-01 18:56:07 +00:00
|
|
|
|
});
|
2018-01-16 21:07:20 +00:00
|
|
|
|
});
|
|
|
|
|
},
|
2018-01-01 18:56:07 +00:00
|
|
|
|
|
2018-01-16 21:07:20 +00:00
|
|
|
|
methods: {
|
2018-01-18 16:10:18 +00:00
|
|
|
|
showNotification: function(message, error)
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.notification = {
|
|
|
|
|
message: message,
|
|
|
|
|
error: error
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (self.notificationTimer != null)
|
|
|
|
|
clearTimeout(self.notificationTimer);
|
|
|
|
|
|
|
|
|
|
self.notificationTimer = setTimeout(function()
|
|
|
|
|
{
|
|
|
|
|
self.notification = null;
|
|
|
|
|
self.notificationTimer = null;
|
|
|
|
|
}, 5000);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
hideNotification: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.notification = null;
|
|
|
|
|
|
|
|
|
|
if (self.notificationTimer != null)
|
|
|
|
|
{
|
|
|
|
|
clearTimeout(self.notificationTimer);
|
|
|
|
|
self.notificationTimer = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleAPIError: function(messageId, error)
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
console.log(error);
|
|
|
|
|
var errorMessage = '';
|
|
|
|
|
|
|
|
|
|
if (error.response)
|
|
|
|
|
{
|
|
|
|
|
errorMessage = 'HTTP response code ' + error.response.status;
|
|
|
|
|
}
|
|
|
|
|
else if (error.request)
|
|
|
|
|
{
|
|
|
|
|
errorMessage = 'No response';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
errorMessage = error.message;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.showNotification(i18n.t(messageId) + '\n\n' + errorMessage, true);
|
|
|
|
|
},
|
|
|
|
|
|
2018-02-12 21:13:03 +00:00
|
|
|
|
loadStatus: function()
|
2018-01-16 21:07:20 +00:00
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/status', { retry: 10, retryDelay: 1000 })
|
2018-01-16 21:07:20 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
2018-02-12 21:13:03 +00:00
|
|
|
|
self.status = response.data;
|
2018-01-16 21:07:20 +00:00
|
|
|
|
})
|
2018-02-12 21:13:03 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadStatus'));
|
2018-01-16 21:07:20 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
loadConnection: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/connection', { retry: 10, retryDelay: 1000 })
|
2018-01-01 18:56:07 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
|
|
|
|
self.connection = response.data;
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadConnection'));
|
2018-01-16 21:07:20 +00:00
|
|
|
|
},
|
2018-01-01 18:56:07 +00:00
|
|
|
|
|
2018-01-16 21:07:20 +00:00
|
|
|
|
loadSystem: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/system', { retry: 10, retryDelay: 1000 })
|
2018-01-11 20:03:46 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
|
|
|
|
self.system = response.data;
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadSystem'));
|
2018-01-16 21:07:20 +00:00
|
|
|
|
},
|
2018-01-11 20:03:46 +00:00
|
|
|
|
|
2018-01-16 21:07:20 +00:00
|
|
|
|
loadTimeTriggers: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/triggers/time', { retry: 10, retryDelay: 1000 })
|
2018-01-12 15:20:28 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
2018-01-17 15:57:14 +00:00
|
|
|
|
{
|
|
|
|
|
var timeSettings = {
|
|
|
|
|
enabled: response.data.enabled || false,
|
|
|
|
|
transitionTime: response.data.transitionTime || 0,
|
|
|
|
|
triggers: []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(response.data.triggers))
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < response.data.triggers.length; i++)
|
|
|
|
|
{
|
|
|
|
|
var trigger = response.data.triggers[i];
|
|
|
|
|
|
|
|
|
|
timeSettings.triggers.push({
|
|
|
|
|
brightness: trigger.brightness || 0,
|
|
|
|
|
triggerType: trigger.triggerType || 0,
|
|
|
|
|
enabled: trigger.enabled || false,
|
|
|
|
|
|
|
|
|
|
fixedTime: trigger.triggerType > 0 ? 0 : trigger.time || 0,
|
|
|
|
|
relativeTime: trigger.triggerType > 0 ? trigger.time || 0 : 0,
|
|
|
|
|
|
|
|
|
|
monday: (trigger.daysOfWeek & 1) > 0,
|
|
|
|
|
tuesday: (trigger.daysOfWeek & 2) > 0,
|
|
|
|
|
wednesday: (trigger.daysOfWeek & 4) > 0,
|
|
|
|
|
thursday: (trigger.daysOfWeek & 8) > 0,
|
|
|
|
|
friday: (trigger.daysOfWeek & 16) > 0,
|
|
|
|
|
saturday: (trigger.daysOfWeek & 32) > 0,
|
|
|
|
|
sunday: (trigger.daysOfWeek & 64) > 0
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.triggers.time = timeSettings;
|
|
|
|
|
}
|
2018-01-12 15:20:28 +00:00
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadTimeTriggers'));
|
2018-01-16 21:07:20 +00:00
|
|
|
|
},
|
|
|
|
|
|
2018-01-17 22:28:39 +00:00
|
|
|
|
loadMotionTriggers: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/triggers/motion', { retry: 10, retryDelay: 1000 })
|
2018-01-17 22:28:39 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
|
|
|
|
self.triggers.motion = response.data;
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadMotionTriggers'));
|
2018-01-17 22:28:39 +00:00
|
|
|
|
},
|
2018-01-12 15:20:28 +00:00
|
|
|
|
|
2018-01-16 21:07:20 +00:00
|
|
|
|
loadSteps: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/steps/values', { retry: 10, retryDelay: 1000 })
|
2018-01-01 18:56:07 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
2018-01-07 22:12:42 +00:00
|
|
|
|
if (Array.isArray(response.data))
|
|
|
|
|
{
|
|
|
|
|
var allSteps = true;
|
|
|
|
|
var allStepsValue = false;
|
|
|
|
|
|
|
|
|
|
var total = 0;
|
|
|
|
|
var steps = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < response.data.length; i++)
|
|
|
|
|
{
|
|
|
|
|
var value = response.data[i];
|
|
|
|
|
|
|
|
|
|
if (allStepsValue === false)
|
|
|
|
|
allStepsValue = value;
|
|
|
|
|
else if (value !== allStepsValue)
|
|
|
|
|
allSteps = false;
|
|
|
|
|
|
|
|
|
|
steps.push({ value: value });
|
|
|
|
|
total += value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.steps = steps;
|
|
|
|
|
self.allStepsValue = Math.floor(total / steps.length);
|
|
|
|
|
self.allSteps = allSteps;
|
|
|
|
|
}
|
2018-01-16 21:07:20 +00:00
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
|
|
|
|
|
applyConnection: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.saving) return;
|
|
|
|
|
|
|
|
|
|
self.saving = true;
|
|
|
|
|
|
|
|
|
|
axios.post('/api/connection', {
|
|
|
|
|
hostname: self.connection.hostname,
|
|
|
|
|
accesspoint: self.connection.accesspoint,
|
|
|
|
|
station: self.connection.station,
|
|
|
|
|
ssid: self.connection.ssid,
|
|
|
|
|
password: self.connection.password,
|
|
|
|
|
dhcp: self.connection.dhcp,
|
|
|
|
|
ip: self.connection.ip,
|
|
|
|
|
subnetmask: self.connection.subnetmask,
|
|
|
|
|
gateway: self.connection.gateway,
|
2018-03-19 06:45:54 +00:00
|
|
|
|
}, { retry: 10, retryDelay: 1000 })
|
2018-01-01 18:56:07 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.applyConnection'))
|
2018-01-01 18:56:07 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.saving = false;
|
2018-01-17 15:57:14 +00:00
|
|
|
|
});
|
2018-01-01 18:56:07 +00:00
|
|
|
|
},
|
|
|
|
|
|
2018-01-11 20:03:46 +00:00
|
|
|
|
applySystem: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.saving) return;
|
|
|
|
|
|
|
|
|
|
self.saving = true;
|
|
|
|
|
|
2018-03-19 06:45:54 +00:00
|
|
|
|
axios.post('/api/system', self.system, { retry: 10, retryDelay: 1000 })
|
2018-01-11 20:03:46 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
2018-01-18 16:10:18 +00:00
|
|
|
|
self.showNotification(i18n.t('rebootPending'));
|
2018-01-11 20:03:46 +00:00
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.applySystem'))
|
2018-01-11 20:03:46 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.saving = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
startLoadingIndicator: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
self.loadingStage = 0;
|
|
|
|
|
self.loadingTimer = setInterval(function()
|
|
|
|
|
{
|
|
|
|
|
self.loadingStage++;
|
|
|
|
|
switch (self.loadingStage)
|
|
|
|
|
{
|
|
|
|
|
case 1: self.loadingIndicator = '/'; break;
|
|
|
|
|
case 2: self.loadingIndicator = '-'; break;
|
|
|
|
|
case 3: self.loadingIndicator = '\\'; break;
|
|
|
|
|
case 4: self.loadingIndicator = '|'; self.loadingStage = 0; break;
|
|
|
|
|
}
|
|
|
|
|
}, 250);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stopLoadingIndicator: function()
|
|
|
|
|
{
|
|
|
|
|
clearInterval(this.loadingTimer);
|
|
|
|
|
},
|
2017-03-24 22:04:58 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
getWiFiStationStatus: function()
|
|
|
|
|
{
|
|
|
|
|
if (!this.wifiStatus.station.enabled)
|
|
|
|
|
return 'disconnected';
|
|
|
|
|
|
|
|
|
|
switch (this.wifiStatus.station.status)
|
|
|
|
|
{
|
|
|
|
|
case 0: // WL_IDLE_STATUS
|
|
|
|
|
case 2: // WL_SCAN_COMPLETED
|
|
|
|
|
return 'connecting';
|
|
|
|
|
|
|
|
|
|
case 1: // WL_NO_SSID_AVAIL
|
|
|
|
|
case 4: // WL_CONNECT_FAILED
|
|
|
|
|
case 5: // WL_CONNECTION_LOST
|
|
|
|
|
return 'error';
|
|
|
|
|
|
|
|
|
|
case 3: // WL_CONNECTED
|
|
|
|
|
return 'connected';
|
|
|
|
|
|
|
|
|
|
case 6: // WL_DISCONNECTED
|
|
|
|
|
default:
|
|
|
|
|
return 'disconnected';
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getWiFiStationStatusText: function()
|
|
|
|
|
{
|
|
|
|
|
if (!this.wifiStatus.station.enabled)
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.disabled');
|
2017-03-25 15:36:04 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
switch (this.wifiStatus.station.status)
|
|
|
|
|
{
|
|
|
|
|
case 0: // WL_IDLE_STATUS
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.idle');
|
2017-03-24 22:04:58 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 1: // WL_NO_SSID_AVAIL
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.noSSID');
|
2017-05-06 13:27:20 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 2: // WL_SCAN_COMPLETED
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.scanCompleted');
|
2017-05-06 13:27:20 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 3: // WL_CONNECTED
|
|
|
|
|
return this.wifiStatus.station.ip;
|
2017-05-06 13:27:20 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 4: // WL_CONNECT_FAILED
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.connectFailed');
|
2017-05-06 13:27:20 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 5: // WL_CONNECTION_LOST
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.connectionLost');
|
2017-04-16 11:40:34 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
case 6: // WL_DISCONNECTED
|
|
|
|
|
default:
|
|
|
|
|
return i18n.t('wifiStatus.stationmode.disconnected');
|
|
|
|
|
}
|
|
|
|
|
},
|
2017-04-16 11:40:34 +00:00
|
|
|
|
|
2018-01-01 18:56:07 +00:00
|
|
|
|
updateWiFiStatus: function()
|
2018-01-03 20:44:34 +00:00
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (!self.saving)
|
|
|
|
|
{
|
2018-03-19 06:45:54 +00:00
|
|
|
|
axios.get('/api/connection/status', { retry: 10, retryDelay: 1000 })
|
2018-01-03 20:44:34 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
|
|
|
|
self.wifiStatus = response.data;
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.updateWiFiStatus'))
|
2018-01-03 20:44:34 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
setTimeout(self.updateWiFiStatus, 5000);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
setTimeout(self.updateWiFiStatus, 5000);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
uploadFirmware: function()
|
2017-04-16 12:25:36 +00:00
|
|
|
|
{
|
2018-01-01 18:56:07 +00:00
|
|
|
|
var self = this;
|
|
|
|
|
if (self.saving) return;
|
|
|
|
|
|
2018-01-03 20:44:34 +00:00
|
|
|
|
self.saving = true;
|
|
|
|
|
self.uploadProgress = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var data = new FormData();
|
|
|
|
|
data.append('file', document.getElementById('firmwareFile').files[0]);
|
|
|
|
|
|
|
|
|
|
var config = {
|
|
|
|
|
timeout: 360000,
|
|
|
|
|
onUploadProgress: function(progressEvent)
|
|
|
|
|
{
|
|
|
|
|
self.uploadProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-05 19:02:30 +00:00
|
|
|
|
axios.post('/api/firmware', data, config)
|
2018-01-01 18:56:07 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
2018-01-18 16:10:18 +00:00
|
|
|
|
self.showNotification(i18n.t('rebootPending'));
|
2018-01-03 20:44:34 +00:00
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.uploadFirmware'))
|
2018-01-03 20:44:34 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.uploadProgress = false;
|
|
|
|
|
self.saving = false;
|
2018-01-01 20:00:56 +00:00
|
|
|
|
|
2018-01-03 20:44:34 +00:00
|
|
|
|
document.getElementById('firmware').reset();
|
|
|
|
|
});
|
2018-01-07 22:12:42 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stepsChanged: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.loading || self.disableStepsChanged) return;
|
|
|
|
|
|
|
|
|
|
if (self.savingStepsTimer === false)
|
|
|
|
|
self.savingStepsTimer = setTimeout(function() { self.updateSteps(); }, 200);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
updateSteps: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
2018-02-03 14:44:44 +00:00
|
|
|
|
if (self.savingSteps)
|
|
|
|
|
self.savingStepsTimer = setTimeout(function() { self.updateSteps(); }, 200);
|
|
|
|
|
|
2018-01-07 22:12:42 +00:00
|
|
|
|
self.savingSteps = true;
|
|
|
|
|
self.savingStepsTimer = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.disableStepsChanged = true;
|
|
|
|
|
|
|
|
|
|
if (self.allSteps)
|
|
|
|
|
{
|
|
|
|
|
var newSteps = [];
|
|
|
|
|
for (var i = 0; i < self.steps.length; i++)
|
|
|
|
|
newSteps.push({ value: self.allStepsValue });
|
|
|
|
|
|
|
|
|
|
self.steps = newSteps;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var total = 0;
|
|
|
|
|
for (var i = 0; i < self.steps.length; i++)
|
|
|
|
|
total += self.steps[i].value;
|
|
|
|
|
|
|
|
|
|
self.allStepsValue = Math.floor(total / self.steps.length);
|
|
|
|
|
}
|
|
|
|
|
var steps = [];
|
|
|
|
|
for (var i = 0; i < self.steps.length; i++)
|
|
|
|
|
steps.push(self.steps[i].value);
|
|
|
|
|
|
|
|
|
|
self.disableStepsChanged = false;
|
|
|
|
|
|
|
|
|
|
|
2018-01-26 10:50:42 +00:00
|
|
|
|
axios.post('/api/steps/values', {
|
2018-01-07 22:12:42 +00:00
|
|
|
|
transitionTime: 1000,
|
2018-03-19 06:45:54 +00:00
|
|
|
|
values: steps,
|
|
|
|
|
retry: 10,
|
|
|
|
|
retryDelay: 1000
|
2018-01-07 22:12:42 +00:00
|
|
|
|
})
|
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.updateSteps'))
|
2018-01-07 22:12:42 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.savingSteps = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
searchLocation: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
2018-01-11 20:03:46 +00:00
|
|
|
|
if (!self.location) return;
|
2018-01-07 22:12:42 +00:00
|
|
|
|
|
|
|
|
|
self.searchingLocation = true;
|
|
|
|
|
|
2018-01-11 20:03:46 +00:00
|
|
|
|
axios.get('https://maps.googleapis.com/maps/api/geocode/json', { params: { address: self.location, key: self.system.mapsAPIKey }})
|
2018-01-07 22:12:42 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
2018-01-08 15:27:04 +00:00
|
|
|
|
if (Array.isArray(response.data.results) && response.data.results.length > 0)
|
|
|
|
|
{
|
|
|
|
|
var location = response.data.results[0].geometry.location;
|
2018-01-11 20:03:46 +00:00
|
|
|
|
self.system.lat = location.lat;
|
|
|
|
|
self.system.lng = location.lng;
|
2018-01-08 15:27:04 +00:00
|
|
|
|
}
|
2018-01-07 22:12:42 +00:00
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.searchLocation'))
|
2018-01-07 22:12:42 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.searchingLocation = false;
|
|
|
|
|
});
|
2018-01-17 15:57:14 +00:00
|
|
|
|
},
|
|
|
|
|
|
2018-01-18 16:10:18 +00:00
|
|
|
|
applyTimeTriggers: function()
|
2018-01-17 15:57:14 +00:00
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.saving) return;
|
|
|
|
|
|
|
|
|
|
self.saving = true;
|
|
|
|
|
|
|
|
|
|
var timeSettings = {
|
|
|
|
|
enabled: self.triggers.time.enabled,
|
|
|
|
|
transitionTime: self.triggers.time.transitionTime,
|
|
|
|
|
triggers: []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < self.triggers.time.triggers.length; i++)
|
|
|
|
|
{
|
|
|
|
|
var trigger = self.triggers.time.triggers[i];
|
|
|
|
|
|
|
|
|
|
timeSettings.triggers.push({
|
|
|
|
|
brightness: trigger.brightness,
|
|
|
|
|
triggerType: trigger.triggerType,
|
|
|
|
|
enabled: trigger.enabled,
|
|
|
|
|
time: trigger.triggerType > 0 ? trigger.relativeTime : trigger.fixedTime,
|
|
|
|
|
daysOfWeek: (trigger.monday ? 1 : 0) |
|
|
|
|
|
(trigger.tuesday ? 2 : 0) |
|
|
|
|
|
(trigger.wednesday ? 4 : 0) |
|
|
|
|
|
(trigger.thursday ? 8 : 0) |
|
|
|
|
|
(trigger.friday ? 16 : 0) |
|
|
|
|
|
(trigger.saturday ? 32 : 0) |
|
|
|
|
|
(trigger.sunday ? 64 : 0)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-19 06:45:54 +00:00
|
|
|
|
axios.post('/api/triggers/time', timeSettings, { retry: 10, retryDelay: 1000 })
|
2018-01-17 15:57:14 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
})
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.applyTimeTriggers'))
|
2018-01-17 15:57:14 +00:00
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.saving = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
addTimeTrigger: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.triggers.time.triggers.push({
|
|
|
|
|
brightness: 0,
|
|
|
|
|
triggerType: 0,
|
|
|
|
|
enabled: true,
|
|
|
|
|
|
|
|
|
|
fixedTime: 9 * 60,
|
|
|
|
|
relativeTime: 0,
|
|
|
|
|
|
|
|
|
|
monday: true,
|
|
|
|
|
tuesday: true,
|
|
|
|
|
wednesday: true,
|
|
|
|
|
thursday: true,
|
|
|
|
|
friday: true,
|
|
|
|
|
saturday: true,
|
|
|
|
|
sunday: true
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
deleteTimeTrigger: function(index)
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.triggers.time.triggers.splice(index, 1);
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-18 16:10:18 +00:00
|
|
|
|
applyMotionTriggers: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.saving) return;
|
|
|
|
|
|
|
|
|
|
self.saving = true;
|
|
|
|
|
|
2018-03-19 06:45:54 +00:00
|
|
|
|
axios.post('/api/triggers/motion', self.triggers.motion, { retry: 10, retryDelay: 1000 })
|
2018-01-18 16:10:18 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
})
|
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.applyMotionTriggers'))
|
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.saving = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-17 22:28:39 +00:00
|
|
|
|
addMotionTrigger: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.triggers.motion.triggers.push({
|
|
|
|
|
brightness: 0,
|
|
|
|
|
enabled: true,
|
|
|
|
|
pin: 2,
|
2018-02-13 20:52:24 +00:00
|
|
|
|
direction: 1
|
2018-01-17 22:28:39 +00:00
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
deleteMotionTrigger: function(index)
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
self.triggers.motion.triggers.splice(index, 1);
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-17 15:57:14 +00:00
|
|
|
|
getDisplayTime: function(time, isRelative)
|
|
|
|
|
{
|
|
|
|
|
var result = '';
|
|
|
|
|
|
2018-02-12 20:16:30 +00:00
|
|
|
|
if (isRelative)
|
|
|
|
|
result += time >= 0 ? '+' : '-';
|
2018-01-17 15:57:14 +00:00
|
|
|
|
|
2018-02-12 20:16:30 +00:00
|
|
|
|
time = Math.abs(time);
|
2018-01-17 15:57:14 +00:00
|
|
|
|
var hours = Math.floor(time / 60);
|
2018-02-12 20:16:30 +00:00
|
|
|
|
var minutes = time % 60;
|
2018-01-17 15:57:14 +00:00
|
|
|
|
|
|
|
|
|
result += hours + ':';
|
|
|
|
|
if (minutes < 10)
|
|
|
|
|
result += '0';
|
|
|
|
|
|
|
|
|
|
result += minutes;
|
|
|
|
|
return result;
|
2018-01-28 19:03:47 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
startCalibration: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
2018-03-19 06:45:54 +00:00
|
|
|
|
axios.get('/api/steps', { retry: 10, retryDelay: 1000 })
|
2018-02-03 14:44:44 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
if (typeof response.data == 'object')
|
|
|
|
|
{
|
|
|
|
|
self.calibration = {
|
|
|
|
|
wizardStep: 0,
|
|
|
|
|
count: response.data.count,
|
|
|
|
|
useCurve: response.data.useCurve,
|
|
|
|
|
ranges: response.data.ranges
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.loadSteps'));
|
2018-01-28 19:03:47 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
stopCalibration: function()
|
|
|
|
|
{
|
|
|
|
|
this.calibration = null;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
applyCalibration: function()
|
|
|
|
|
{
|
2018-02-03 14:44:44 +00:00
|
|
|
|
// All the changes are already applied
|
|
|
|
|
this.stopCalibration();
|
2018-01-28 19:03:47 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
hasNextCalibrationStep: function()
|
|
|
|
|
{
|
|
|
|
|
return this.calibration.wizardStep < 1;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
nextCalibrationStep: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
2018-02-03 14:44:44 +00:00
|
|
|
|
if (self.calibration.wizardStep == 0)
|
|
|
|
|
{
|
|
|
|
|
if (self.calibration.count < 1)
|
|
|
|
|
self.calibration.count = 1;
|
|
|
|
|
else if (self.calibration.count > 16)
|
|
|
|
|
self.calibration.count = 16;
|
|
|
|
|
|
|
|
|
|
// Update ranges with possible new count
|
|
|
|
|
if (self.calibration.ranges.length > self.calibration.count)
|
|
|
|
|
{
|
|
|
|
|
self.calibration.ranges.splice(self.calibration.count);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (self.calibration.ranges.length < self.calibration.count)
|
|
|
|
|
self.calibration.ranges.push({ start: 0, end: 4095 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.calibration.wizardStep++;
|
2018-01-28 19:03:47 +00:00
|
|
|
|
if (self.calibration.wizardStep == 2)
|
|
|
|
|
self.applyCalibration();
|
2018-02-03 14:44:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
calibrationChanged: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.loadingCalibration || self.calibration === null) return;
|
|
|
|
|
|
|
|
|
|
if (self.savingCalibrationTimer === false)
|
|
|
|
|
self.savingCalibrationTimer = setTimeout(function() { self.updateCalibration(); }, 200);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
updateCalibration: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
if (self.calibration === null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (self.savingCalibration)
|
|
|
|
|
self.savingStepsTimer = setTimeout(function() { self.updateCalibration(); }, 200);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.savingCalibration = true;
|
|
|
|
|
self.savingCalibrationTimer = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
axios.post('/api/steps', {
|
|
|
|
|
count: self.calibration.count,
|
|
|
|
|
useCurve: self.calibration.useCurve,
|
|
|
|
|
ranges: self.calibration.ranges
|
2018-03-19 06:45:54 +00:00
|
|
|
|
}, { retry: 10, retryDelay: 1000 })
|
2018-02-03 14:44:44 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
})
|
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.updateCalibration'))
|
|
|
|
|
.then(function()
|
|
|
|
|
{
|
|
|
|
|
self.savingCalibration = false;
|
|
|
|
|
});
|
|
|
|
|
},
|
2018-02-12 21:13:03 +00:00
|
|
|
|
|
|
|
|
|
deleteStackTrace: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
2018-03-19 06:45:54 +00:00
|
|
|
|
return axios.get('/api/stacktrace/delete', { retry: 10, retryDelay: 1000 })
|
2018-02-13 20:52:24 +00:00
|
|
|
|
.then(function(response)
|
|
|
|
|
{
|
|
|
|
|
self.status.resetReason = 0;
|
|
|
|
|
self.status.stackTrace = false;
|
|
|
|
|
})
|
|
|
|
|
.catch(self.handleAPIError.bind(self, 'error.stackTraceDeleteError'));
|
2018-02-12 21:13:03 +00:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
|
hasResetError: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
REASON_DEFAULT_RST = 0 normal startup by power on
|
|
|
|
|
REASON_WDT_RST = 1 hardware watch dog reset
|
|
|
|
|
REASON_EXCEPTION_RST = 2 exception reset, GPIO status won’t change
|
|
|
|
|
REASON_SOFT_WDT_RST = 3 software watch dog reset, GPIO status won’t change
|
|
|
|
|
REASON_SOFT_RESTART = 4 software restart ,system_restart , GPIO status won’t change
|
|
|
|
|
REASON_DEEP_SLEEP_AWAKE = 5 wake up from deep-sleep
|
|
|
|
|
REASON_EXT_SYS_RST = 6 system reset
|
|
|
|
|
*/
|
|
|
|
|
return (self.status.resetReason === 1 ||
|
|
|
|
|
self.status.resetReason === 2 ||
|
|
|
|
|
self.status.resetReason === 3 ||
|
|
|
|
|
self.status.stackTrace);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getDeviceTime: function()
|
|
|
|
|
{
|
|
|
|
|
var self = this;
|
|
|
|
|
if (self.status.time === false)
|
|
|
|
|
return '';
|
|
|
|
|
|
|
|
|
|
var date = new Date(self.status.time * 1000);
|
|
|
|
|
var hours = date.getHours();
|
|
|
|
|
var minutes = '0' + date.getMinutes();
|
|
|
|
|
|
|
|
|
|
var offsetHours = '0' + Math.floor(Math.abs(self.status.timeOffset / 60) / 60);
|
|
|
|
|
var offsetMinutes = '0' + Math.abs(self.status.timeOffset / 60) % 60;
|
|
|
|
|
var offset = (self.status.timeOffset >= 0 ? '+' : '-') + offsetHours.substr(-2) + ':' + offsetMinutes.substr(-2);
|
|
|
|
|
|
|
|
|
|
return hours + ':' + minutes.substr(-2) + ' (' + offset + ')';
|
|
|
|
|
}
|
2018-01-07 22:12:42 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
watch: {
|
|
|
|
|
// The sync: true ensures we can wrap the internal updates with disableStepsChanged
|
|
|
|
|
allSteps: {
|
|
|
|
|
handler: function() { this.stepsChanged(); },
|
|
|
|
|
sync: true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
allStepsValue: {
|
|
|
|
|
handler: function() { this.stepsChanged(); },
|
|
|
|
|
sync: true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
steps: {
|
|
|
|
|
handler: function() { this.stepsChanged(); },
|
|
|
|
|
deep: true,
|
|
|
|
|
sync: true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
activeTab: function(newValue)
|
|
|
|
|
{
|
|
|
|
|
window.location.hash = '#' + newValue;
|
2018-02-03 14:44:44 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
calibration: {
|
|
|
|
|
handler: function() { this.calibrationChanged(); },
|
|
|
|
|
deep: true
|
2017-04-16 12:25:36 +00:00
|
|
|
|
}
|
2018-01-01 18:56:07 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|