iobroker.vis
Version:
Graphical user interface for iobroker.
1,064 lines (1,008 loc) • 40.8 kB
JavaScript
////// ----------------------- Connection "class" ---------------------- ////////////
/* jshint browser:true */
/* global document*/
/* global console*/
/* global session*/
/* global window*/
/* global location*/
/* global setTimeout*/
/* global clearTimeout*/
/* global io*/
/* global $*/
// The idea of servConn is to use this class later in every addon (Yahui, Control and so on).
// The addon just must say, what must be loaded (values, objects, indexes) and
// the class loads it for addon. Authentication will be done automatically, so addon does not care about it.
// It will be .js file with localData and servConn
var servConn = {
_socket: null,
_hub: null,
_onConnChange: null,
_onUpdate: null,
_isConnected: false,
_disconnectedSince: null,
_connCallbacks: {
onConnChange: null,
onUpdate: null,
onRefresh: null,
onAuth: null
},
_authInfo: null,
_isAuthDone: false,
_isAuthRequired: false,
_authRunning: false,
_cmdQueue: [],
_connTimer: null,
_type: 1, // 0 - SignalR, 1 - socket.io, 2 - local demo
_timeout: 0, // 0 - use transport default timeout to detect disconnect
_reconnectInterval: 10000, // reconnect interval
getIsConnected: function () {
return this._isConnected;
},
getType: function () {
return this._type;
},
init: function (connCallbacks, type) {
if (typeof type == "string") {
type = type.toLowerCase();
}
if (typeof session !== 'undefined') {
var user = session.get('user');
if (user) {
this._authInfo = {
user: user,
hash: session.get('hash'),
salt: session.get('salt')
};
}
}
// If autodetect
if (type === undefined) {
type = visConfig.connType;
if (type === undefined || type === null) {
if (typeof io != "undefined") {
type = 1; // socket.io
} else if (typeof $ != "undefined" && typeof $.connection != "undefined") {
type = 0; // SignalR
} else {
type = 2; // local demo
}
}
}
this._connCallbacks = connCallbacks;
var connLink = visConfig.connLink || window.localStorage.getItem("connLink");
if (type === 0 || type == 'signalr') {
this._type = 0;
this.connection = $.hubConnection(connLink);
this._hub = this.connection.createHubProxy("serverHub");
//this._hub = $.connection.serverHub;
if (!this._hub) {
this._autoReconnect();
return;
}
var that = this;
this._hub.on("updatePointValue", function (model) {
if (that._connCallbacks.onUpdate) {
that._connCallbacks.onUpdate({name: model.name, val: model.val, ts: model.ts, ack: model.ack});
}
});
this._hub.on("authRequest", function (message, salt) {
that._isAuthRequired = true;
that._isAuthDone = false;
console.log('Auth request: ' + message);
if (that._authInfo) {
// If we have auth information, send it automatically
that.authenticate();
} else if (that._connCallbacks.onAuth) {
// Else request from GUI input of user, pass and data (salt)
that._connCallbacks.onAuth(message, salt);
} else {
// TODO Translate
alert('server requires authentication, but no onAuth callback is installed!');
}
});
this._hub.on("refresh", function () {
if (that._connCallbacks.onRefresh) {
that._connCallbacks.onRefresh();
}
});
this.connection.start().done(function () {
that._isConnected = true;
if (that._connCallbacks.onConnChange) {
that._connCallbacks.onConnChange(that._isConnected);
}
that._autoReconnect();
});
this.connection.reconnecting(function () {
that._isConnected = false;
if (that._connCallbacks.onConnChange) {
that._connCallbacks.onConnChange(that._isConnected);
}
that._autoReconnect();
});
this.connection.reconnected(function () {
that._isConnected = true;
if (that._connCallbacks.onConnChange) {
that._connCallbacks.onConnChange(that._isConnected);
}
that._autoReconnect();
});
this.connection.disconnected(function () {
that._isConnected = false;
if (that._connCallbacks.onConnChange) {
that._connCallbacks.onConnChange(that._isConnected);
}
that._autoReconnect();
});
} else if (type == 1 || type == "socket.io") {
this._type = 1;
if (typeof io != "undefined") {
if (typeof socketSession == 'undefined') {
socketSession = 'nokey';
}
var url;
if (connLink) {
url = connLink;
} else {
url = jQuery(location).attr('protocol') + '//' + jQuery(location).attr('host');
}
this._socket = io.connect(url, {
'query': 'key=' + socketSession,
'reconnection limit': 10000,
'max reconnection attempts': Infinity
});
this._socket._myParent = this;
this._socket.on('connect', function () {
//console.log("socket.io connect");
if (this._myParent._isConnected === true) {
// This seems to be a reconnect because we're already connected!
// -> prevent firing onConnChange twice
return;
}
this._myParent._isConnected = true;
if (this._myParent._connCallbacks.onConnChange) {
this._myParent._connCallbacks.onConnChange(this._myParent._isConnected);
}
//this._myParent._autoReconnect();
});
this._socket.on('disconnect', function () {
//console.log("socket.io disconnect");
this._myParent._disconnectedSince = (new Date()).getTime();
this._myParent._isConnected = false;
if (this._myParent._connCallbacks.onConnChange) {
this._myParent._connCallbacks.onConnChange(this._myParent._isConnected);
}
// Auto-Reconnect
//this._myParent._autoReconnect();
});
this._socket.on('reconnect', function () {
//console.log("socket.io reconnect");
var offlineTime = (new Date()).getTime() - this._myParent._disconnectedSince;
//console.log("was offline for " + (offlineTime / 1000) + "s");
// TODO does this make sense?
//if (offlineTime > 12000) {
//window.location.reload();
//}
this._myParent._isConnected = true;
if (this._myParent._connCallbacks.onConnChange) {
this._myParent._connCallbacks.onConnChange(this._myParent._isConnected);
}
//this._myParent._autoReconnect();
});
this._socket.on('refreshAddons', function () {
if (this._myParent._connCallbacks.onRefresh) {
this._myParent._connCallbacks.onRefresh();
}
});
this._socket.on('event', function (obj) {
if (obj === null) {
return;
}
var o = {};
o.name = obj[0] + "";
o.val = obj[1];
o.ts = obj[2];
o.ack = obj[3];
o.lc = obj[4];
if (this._myParent._connCallbacks.onUpdate) {
this._myParent._connCallbacks.onUpdate(o);
}
});
} //else {
//console.log("socket.io not initialized");
//}
} else if (type == 2 || type == "local") {
this._type = 2;
this._isAuthDone = true;
this._isConnected = true;
if (this._connCallbacks.onConnChange) {
this._connCallbacks.onConnChange(this._isConnected);
}
}
// start connection timer
//this._autoReconnect();
// Detect if running under cordova
var app = document.URL.indexOf('http://') === -1 && document.URL.indexOf('https://') === -1;
if (app) {
$('body').append('<div id="system_menu" style="z-index:3000;width: 30%; height:30px; background-color: white; position:absolute; bottom: 0; left: 35%; display: none; border:1px solid black; text-align:center">' + _('Settings') + '</a></div>');
$("#system_menu").click(function () {
console.log("Goto settings");
if (window.localStorage) {
window.localStorage.setItem("connSettings", true);
}
// Call settings window
window.location.href = '../index.html';
});
// Install menu on menu button
document.addEventListener("menubutton", function () {
var menuDiv = $("#system_menu");
if (servConn.menuOpen) {
console.log("close the menu");
menuDiv.hide();
servConn.menuOpen = false;
} else {
console.log("open the menu");
menuDiv.show();
servConn.menuOpen = true;
}
}, false);
}
},
// After 3 hours debugging...
// It is questionable if ths function really required.
// Socket.io automatically reconnects to the server and sets _isConnected to true, so
// it will never happened...
// And in the future we will have two servers - one for static pages and one for socket.io.
// @Bluefox: i introduced this function because socket.io didn't reconnect sometimes after a long
// offline period (several minutes/hours). Since 0.9beta97 it's buggy and causes a reload-loop with android
// stock browser:
// http://homematic-forum.de/forum/viewtopic.php?f=48&t=18271
// so i deactivated it for now
_autoReconnect: function () {
// If connected
if (this._isConnected) {
if (window.localStorage) {
window.localStorage.setItem("connCounter", 0);
}
// Stop connection timer
if (this._connTimer) {
clearInterval(this._connTimer);
this._connTimer = null;
}
} else {
// If not connected and the timer not yet started
if (!this._connTimer) {
// Start connection timer
this._connTimer = _setInterval(function (conn) {
if (!conn._isConnected) {
var counter = 0;
if (window.localStorage) {
counter = parseInt(window.localStorage.getItem("connCounter") || 0);
window.localStorage.setItem("connCounter", counter++);
}
// Auto-Reconnect. DashUI can be located in any path.
var url = document.location.href;
var k = url.indexOf('#');
if (k != -1) {
url = url.substring(0, k);
}
if (url.indexOf('.html') == -1) {
url += 'index.html';
}
k = url.indexOf('?');
if (k != -1) {
url = url.substring(0, k);
}
url += '?random=' + Date.now().toString();
var parts = url.split('/');
parts = parts.slice(3);
url = '/' + parts.join('/');
// Detect if running under cordova
var app = document.URL.indexOf('http://') === -1 && document.URL.indexOf('https://') === -1;
if (app && counter > 3) {
url = url.replace('dashui/index.html', 'index.html');
}
$.ajax({
url: url,
cache: false,
success: function (data) {
// Check if it really index.html and not offline.html as fallback
if (data && data.length > 1000) {
if (window.localStorage) {
window.localStorage.setItem("connSettings", true);
}
window.location.reload();
}
}
});
} else {
clearInterval(conn._connTimer);
conn._connTimer = null;
}
}, this._reconnectInterval, this);
}
}
},
getVersion: function (callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._queueCmdIfRequired('getVersion', callback)) {
return;
}
//SignalR
if (this._type === 0) {
this._hub.invoke('getVersion').done(function (version) {
if (callback) {
callback(version);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getVersion', function (version) {
if (callback) {
callback(version);
}
});
}
},
_checkAuth: function (callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('getVersion').done(function (version) {
if (callback)
callback(version);
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getVersion', function (version) {
if (callback)
callback(version);
});
}
},
readFile: function (filename, callback) {
if (!this._isConnected) {
console.log('No connection!');
return;
}
if (this._queueCmdIfRequired("readFile", filename, callback)) {
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('readFile', filename).done(function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('readFile', filename, function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 2) {
//local
// Try load views from local storage
if (filename.indexOf('dashui-views') != -1) {
if (typeof storage !== 'undefined') {
vis.views = storage.get(filename);
if (vis.views) {
callback(vis.views);
return;
} else {
vis.views = {};
}
}
}
// Load from ../datastore/dashui-views.json the demo views
jQuery.ajax({
url: '../datastore/' + filename,
type: 'get',
async: false,
dataType: 'text',
cache: true,
success: function (data) {
try {
vis.views = jQuery.parseJSON(data);
if (typeof vis.views == 'string') {
vis.views = (JSON && JSON.parse(vis.views)) || jQuery.parseJSON(vis.views);
}
} catch (e) {
// TODO Translate
alert('Invalid ' + filename + ' json format');
}
callback(vis.views);
if (!vis.views) {
alert(_('No Views found on Server'));
}
},
error: function (state) {
// TODO Translate
alert('Cannot get ' + location.href + '/../datastore/' + filename + '\n' + state.statusText);
callback([]);
}
});
}
},
touchFile: function (filename) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('touchFile', filename);
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('touchFile', filename);
}
},
writeFile: function (filename, data, callback) {
if (this._type === 0) {
//SignalR
this._hub.invoke('writeFile', filename, JSON.stringify(data)).done(function (isOk) {
if (callback) {
callback(isOk);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('writeFile', filename, data, function (isOk) {
if (callback) {
callback(isOk);
}
});
} else if (this._type == 2) {
if (filename.indexOf('dashui-views') != -1) {
if (typeof storage !== 'undefined') {
storage.set(filename, vis.views);
if (!storage.get('localWarnShown')) {
alert(_('All changes are saved locally. To reset changes clear the cache.'));
storage.set('localWarnShown', true);
}
if (callback) {
callback(true);
}
}
}
}
},
readDir: function (dirname, callback) {
if (this._type === 0) {
//SignalR
this._hub.invoke('readDir', dirname).done(function (jsonString) {
var data;
try {
data = JSON.parse(jsonString);
} catch (e) {
servConn.logError('readDir: Invalid JSON string - ' + e);
data = null;
}
if (callback) {
callback (data);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('readdir', dirname, function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 2) {
if (dirname.indexOf('www/dashui/img') != -1) {
// Load from img the list of files. To make it possible, call "dir /B /O > list.txt" in every img directory.
jQuery.ajax({
url: dirname.replace('www/dashui/', '') + '/list.txt',
type: 'get',
async: false,
dataType: 'text',
cache: true,
success: function (data) {
var files = (data) ? data.split('\n') : [];
if (callback) {
callback(files);
}
},
error: function (state) {
// TODO Translate
alert('Cannot get ' + location.href + dirname.replace('www/dashui/', '') + '/list.txt' + '\n' + state.statusText);
callback([]);
}
});
}
}
},
setPointValue: function (pointId, value) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._queueCmdIfRequired("setPointValue", pointId, value)) {
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('setDataPoint', {id: pointId, val: value});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('setState', [pointId, value]);
} else if (this._type == 2) {
//local
console.log('This is only demo. No point will be controlled.');
}
},
getDataPoints: function (callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._queueCmdIfRequired("getDataPoints", callback)) {
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('getDataPoints').done(function (jsonString) {
var data = {};
if (jsonString === null) {
if (callback) {
callback('Authentication required');
}
} else if (jsonString !== undefined) {
try {
data = (JSON && JSON.parse(jsonString)) || jQuery.parseJSON(jsonString);
} catch (e) {
servConn.logError('getDataPoints: Invalid JSON string - ' + e);
data = null;
if (callback) {
callback('getDataPoints: Invalid JSON string - ' + e);
}
}
}
// Convert array to mapped object {name1: object1, name2: object2}
for (var i = 0, len = data.length; i < len; i++) {
if (data[i]) {
var obj = data[i];
var dp = obj.id;
var o;
data[dp] = obj;
if (localData.uiState['_' + dp + '.Value'] === undefined) {
o = {};
o['_' + dp] = {Value: data[dp].val, Timestamp: data[dp].ts, Certain: data[dp].ack, LastChange: data[dp].lc};
localData.uiState.attr(o);
} else {
o = {};
var id = ' ' + dp;//.replace(/\./g, '\\.');
o[id + '.Value'] = obj.val;
o[id + '.Timestamp'] = obj.ts;
o[id + '.Certain'] = obj.ack;
o[id + '.LastChange'] = obj.lc;
}
}
}
if (callback) {
callback();
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getDatapoints', function (data) {
if (data === null) {
if (callback) {
callback('Authentication required');
}
} else if (data !== undefined) {
for (var dp in data) {
var obj = data[dp];
var o = {};
var id = dp;//.replace(/\./g, '\\.');
if (localData.uiState['_' + dp/*.replace(/\./g, '\\.')*/ + '.Value'] === undefined) {
try {
o['_' + dp + '.Value'] = obj[0];
o['_' + dp + '.Timestamp'] = obj[1];
localData.uiState.attr(o);
} catch (e) {
servConn.logError('Error: can\'t create uiState object for ' + dp + '(' + e + ')');
}
} else {
o['_' + id + '.Value'] = obj[0];
o['_' + id + '.Timestamp'] = obj[1];
o['_' + id + '.Certain'] = obj[2];
o['_' + id + '.LastChange'] = obj[3];
console.log(o);
localData.uiState.attr(o);
}
}
}
if (callback) {
callback();
}
});
} else if (this._type == 2) {
// local
// Load from ../datastore/local-data.json the demo views
jQuery.ajax({
url: '../datastore/local-data' + vis.viewFileSuffix + '.json',
type: 'get',
async: false,
dataType: 'text',
cache: vis.useCache,
success: function (data) {
var _localData = (JSON && JSON.parse(data)) || jQuery.parseJSON(data);
localData.metaIndex = _localData.metaIndex;
localData.metaObjects = _localData.metaObjects;
for (var dp in _localData.uiState) {
try {
// TODO possible problem with legacy
console.log(dp);
localData.uiState.attr(dp, _localData.uiState[dp]);
} catch (e) {
servConn.logError('Cannot export ' + dp);
}
}
callback(null);
},
error: function (state) {
console.log(state.statusText);
localData.uiState.attr('_no', {Value: false, Timestamp: null, Certain: true, LastChange: null});
// Local
if(callback) {
callback(null);
}
}
});
}
},
getDataObjects: function (callback) {
if (!this._isConnected) {
console.log('No connection!');
return;
}
if (this._queueCmdIfRequired("getDataObjects", callback)) {
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('getDataObjects').done(function (jsonString) {
var data = {};
try {
data = JSON.parse(jsonString);
// Convert array to mapped object {name1: object1, name2: object2}
for (var i = 0, len = data.length; i < len; i++) {
if (data[i]) {
data[data[i].id] = data[i];
delete data[data[i].id].id;
}
}
} catch (e) {
servConn.logError('getDataObjects: Invalid JSON string - ' + e);
data = null;
}
if (callback) {
callback(data);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getObjects', function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 2) {
if (callback) {
callback(localData.metaObjects);
}
}
},
getDataIndex: function (callback) {
if (!this._isConnected) {
console.log('No connection!');
return;
}
if (this._type === 0) {
//SignalR
if (callback) {
callback([]);
}
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getIndex', function (data) {
if (callback)
callback(data);
});
} else if (this._type == 2) {
if (callback) {
callback(localData.metaIndex);
}
}
},
addObject: function (objId, obj, callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('addObject', objId, obj).done(function (cid) {
if (callback) {
callback(cid);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('setObject', objId, obj, function (cid) {
if (callback) {
callback(cid);
}
});
}
},
delObject: function (objId) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('deleteObject', objId);
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('delObject', objId);
}
}, // Deprecated
// TODO @Bluefox: Why deprecated? Ursprüngliches Konzept war dass der Value eines Homematic-Programms true/false ist und angibt
// ob ein Programm aktiv/inaktiv ist -> HM-Script Methode .Active()
// Eigentlich wirft der Umbau den Du da vor geraumer Zeit in CCU.IO vorgenommen hast (damit über den Value ein Programm
// angetriggert werden kann) dieses Konzept über den Haufen. Wirkt sich bei mir persönlich an der Stelle nicht aus
// da ich keine Homematic-Programme verwende, aber ...
// ... LessonsLearned: Wir müssen häufiger und mehr kommunizieren bevor wir solche Änderungen vornehmen :)
execProgramm: function (objId) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('programExecute', [objId]);
}
},
httpGet: function (url, callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
this._hub.invoke('httpGet', url).done(function (jsonString) {
if (callback) {
callback(jsonString);
}
});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('httpGet', url, function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 2) {
if (callback) {
callback('');
}
}
},
getStringtable: function (callback) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (this._type === 0) {
//SignalR
//this._hub.invoke('getUrl(url).done(function (jsonString) {
if (callback) {
callback(null);
}
//});
} else if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('getStringtable', function (data) {
if (callback) {
callback(data);
}
});
} else if (this._type == 2) {
if (callback) {
callback(null);
}
}
},
alarmReceipt: function (alarm) {
if (!this._isConnected) {
console.log("No connection!");
return;
}
//if (this._type === 0) {
//SignalR
//this._hub.invoke('getUrl(url).done(function (jsonString) {
//});
//} else
if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('alarmReceipt', alarm);
} else if (this._type == 2) {
if (callback) {
callback(null);
}
}
},
logError: function (errorText) {
console.log("Error: " + errorText);
if (!this._isConnected) {
//console.log("No connection!");
return;
}
//if (this._type === 0) {
//SignalR
//this._hub.server.log(errorText);
//} else
if (this._type == 1) {
//socket.io
if (this._socket === null) {
console.log('socket.io not initialized');
return;
}
this._socket.emit('log', 'error', 'Addon DashUI ' + errorText);
} else if (this._type == 2) {
// Do nothing
}
},
_queueCmdIfRequired: function (func, arg1, arg2, arg3, arg4) {
if (!this._isAuthDone) {
// Queue command
this._cmdQueue.push({func: func, args:[arg1, arg2, arg3, arg4]});
if (!this._authRunning) {
this._authRunning = true;
var that = this;
// Try to read version
this._checkAuth(function (version) {
// If we have got version string, so there is no authentication, or we are authenticated
that._authRunning = false;
if (version) {
that._isAuthDone = true;
// Repeat all stored requests
var __cmdQueue = that._cmdQueue;
// Trigger GC
that._cmdQueue = null;
that._cmdQueue = [];
for (var t = 0, len = __cmdQueue.length; t < len; t++) {
that[__cmdQueue[t].func](__cmdQueue[t].args[0], __cmdQueue[t].args[1], __cmdQueue[t].args[2], __cmdQueue[t].args[3]);
}
} else {
// Auth required
that._isAuthRequired = true;
// What for AuthRequest from server
}
});
}
return true;
} else {
return false;
}
},
authenticate: function (user, password, salt) {
this._authRunning = true;
if (user !== undefined) {
this._authInfo = {
user: user,
hash: password + salt,
salt: salt
};
}
if (!this._isConnected) {
console.log("No connection!");
return;
}
if (!this._authInfo) {
console.log("No credentials!");
}
//SignalR
if (this._type === 0) {
var that = this;
this._hub.invoke('authenticate', that._authInfo.user, that._authInfo.hash, that._authInfo.salt).done(function (error) {
this._authRunning = false;
if (!error) {
that._isAuthDone = true;
if (typeof session !== 'undefined') {
session.set("user", that._authInfo.user);
session.set("hash", that._authInfo.hash);
session.set("salt", that._authInfo.salt);
}
// Repeat all stored requests
var __cmdQueue = that._cmdQueue;
// Trigger garbage collector
that._cmdQueue = null;
that._cmdQueue = [];
for (var t = 0, len = __cmdQueue.length; t < len; t++) {
that[__cmdQueue[t].func](__cmdQueue[t].args[0], __cmdQueue[t].args[1], __cmdQueue[t].args[2], __cmdQueue[t].args[3]);
}
} else {
// Another authRequest should come, wait for this
console.log("Cannot authenticate: " + error);
this._authInfo = null;
}
});
}
}
};