Skip to content

Commit

Permalink
updated disconnection logic
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Cunningham <dan@digitaldan.com>
  • Loading branch information
digitaldan committed Aug 22, 2022
1 parent 1b6a5af commit 810415e
Show file tree
Hide file tree
Showing 7 changed files with 11,357 additions and 189 deletions.
175 changes: 74 additions & 101 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
var logger = require('./logger.js'),
system = require('./system'),
env = process.env.NODE_ENV || 'production',
config;

config,
offlineNotificationTime;

//load and set our configuration, delete any cache first
var loadConfig = function () {
delete require.cache[require.resolve('./config.json')];
config = require('./config.json');
system.setConfiguration(config);
offlineNotificationTime = system.getOfflineNotificationTime()
}

loadConfig();
Expand Down Expand Up @@ -93,7 +94,8 @@ var flash = require('connect-flash'),
Limiter = require('ratelimiter'),
requesttracker = require('./requesttracker'),
routes = require('./routes'),
MongoConnect = require('./system/mongoconnect');
MongoConnect = require('./system/mongoconnect'),
uuid = require('uuid');

// MongoDB connection settings
var mongoose = require('mongoose');
Expand Down Expand Up @@ -123,58 +125,27 @@ var requestTracker = new requesttracker();
// key is openHAB UUID, value is Date when openHAB was disconnected
var offlineOpenhabs = {};

/**
* Callback for the 'check offline openHABs' scheduled task to notify the owner of an openHAB, that the instance
* is offline.
*
* @param error The error, if an error occured
* @param {Openhab} openhab The openHAB instance
*/
function notifyOpenHABOwnerOffline(openhab) {

openhab.status = 'offline';
openhab.last_online = new Date();
openhab.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving openHAB status: ' + error);
}
});
var disconnectevent = new Event({
openhab: openhab.id,
source: 'openhab',
status: 'offline',
color: 'bad'
});
disconnectevent.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving disconnect event: ' + error);
}
});
notifyOpenHABStatusChange(openhab, 'offline');
}

// This timer runs every minute and checks if there are any openHABs in offline status for more then 300 sec
// Then it sends notifications to openHAB's owner if it is offline for more then 300 sec
// This timer only runs on the job task
if (taskEnv === 'main') {
setInterval(function () {
logger.debug('openHAB-cloud: Checking for offline openHABs (' + Object.keys(offlineOpenhabs).length + ')');
for (var offlineOpenhabUuid in offlineOpenhabs) {
if (Date.now() - offlineOpenhabs[offlineOpenhabUuid] < 5 * 60 * 1000) {
for (const offlineOpenhabUuid in offlineOpenhabs) {
const offlineOpenhab = offlineOpenhabs[offlineOpenhabUuid];
if (Date.now() - offlineOpenhab.date < offlineNotificationTime) {
continue;
}
delete offlineOpenhabs[offlineOpenhabUuid];
logger.debug('openHAB-cloud: openHAB with ' + offlineOpenhabUuid + ' is offline > 300 sec, time to notify the owner');
//check if our connection (connectionId) is still set, if not the user has reconnected
Openhab.findOne({
uuid: offlineOpenhabUuid
connectionId: offlineOpenhab.connectionId
}).exec(function (error, openhab) {
if (!openhab || error) {
return;
}
//if this has not connected to another server, then notify
if (openhab.serverAddress == internalAddress) {
notifyOpenHABOwnerOffline(openhab);
}
logger.debug('openHAB-cloud: openHAB with ' + offlineOpenhabUuid + ' is offline > ' + offlineNotificationTime + ' millis, time to notify the owner');
notifyOpenHABStatusChange(openhab, 'offline');
});
}
}, 60000);
Expand Down Expand Up @@ -209,7 +180,6 @@ var Event = require('./models/event');
var Item = require('./models/item');
var UserDevice = require('./models/userdevice');
var Notification = require('./models/notification');
var OpenhabAccessLog = require('./models/openhabaccesslog');

logger.info('openHAB-cloud: Scheduling a statistics job (every 5 min)');
var every5MinStatJob = require('./jobs/every5minstat');
Expand Down Expand Up @@ -458,41 +428,31 @@ io.use(function (socket, next) {
io.sockets.on('connection', function (socket) {
logger.info('openHAB-cloud: Incoming openHAB connection for uuid ' + socket.handshake.uuid);
socket.join(socket.handshake.uuid);
// Remove openHAB from offline array if needed
delete offlineOpenhabs[socket.handshake.uuid];
Openhab.findOne({
uuid: socket.handshake.uuid
}, function (error, openhab) {
if (!error && openhab) {
logger.info('openHAB-cloud: Connected openHAB with ' + socket.handshake.uuid + ' successfully');
// Make an openhabaccesslog entry anyway
var remoteHost = socket.handshake.headers['x-forwarded-for'] || socket.client.conn.remoteAddress;
var newOpenhabAccessLog = new OpenhabAccessLog({
openhab: openhab.id,
remoteHost: remoteHost,
remoteVersion: socket.handshake.openhabVersion,
remoteClientVersion: socket.handshake.clientVersion
});
newOpenhabAccessLog.save(function (error) {
logger.info('openHAB-cloud: uuid ' + socket.handshake.uuid + ' server address ' + openhab.serverAddress + " my address " + internalAddress);

const prevStatus = openhab.status;
const prevLastOnline = openhab.last_online;

openhab.status = 'online';
openhab.serverAddress = internalAddress;
openhab.connectionId = socket.connectionId = uuid.v1() //we will check this when we handle disconnects
openhab.last_online = new Date();
openhab.openhabVersion = socket.handshake.openhabVersion;
openhab.clientVersion = socket.handshake.clientVersion;
openhab.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving openHAB access log: ' + error);
logger.error('openHAB-cloud: Error saving openHAB: ' + error);
socket.disconnect();
return;
}
});
// Make an event and notification only if openhab was offline
// If it was marked online, means reconnect appeared because of my.oh fault
// We don't want massive events and notifications when node is restarted
logger.info('openHAB-cloud: uuid ' + socket.handshake.uuid + ' server address ' + openhab.serverAddress + " my address " + internalAddress);
if (openhab.status === 'offline' || openhab.serverAddress !== internalAddress) {
openhab.status = 'online';
openhab.serverAddress = internalAddress;
openhab.last_online = new Date();
openhab.openhabVersion = socket.handshake.openhabVersion;
openhab.clientVersion = socket.handshake.clientVersion;
openhab.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving openHAB: ' + error);
}
});

socket.openhabUuid = openhab.uuid;
socket.openhabId = openhab.id;

var connectevent = new Event({
openhab: openhab.id,
source: 'openhab',
Expand All @@ -504,27 +464,58 @@ io.sockets.on('connection', function (socket) {
logger.error('openHAB-cloud: Error saving connect event: ' + error);
}
});
notifyOpenHABStatusChange(openhab, 'online');
} else {
openhab.openhabVersion = socket.handshake.openhabVersion;
openhab.clientVersion = socket.handshake.clientVersion;
openhab.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving openhab: ' + error);
}
});
}
socket.openhabUuid = openhab.uuid;
socket.openhabId = openhab.id;

//notify user that connection is online
if(prevStatus === 'offline' && Date.now() - prevLastOnline > offlineNotificationTime){
notifyOpenHABStatusChange(openhab, 'online');
} else if(prevStatus === 'online') {
logger.warn('openHAB-cloud: connected openhab ' + socket.handshake.uuid + ' was previously marked as online')
}
});
} else {
if (error) {
logger.error('openHAB-cloud: Error looking up openHAB: ' + error);
} else {
logger.warn('openHAB-cloud: Unable to find openHAB ' + socket.handshake.uuid);
}
socket.disconnect();
}
});

socket.on('disconnect', function () {
logger.info('openHAB-cloud: Disconnected uuid ' + socket.handshake.uuid + ' connectionId ' + socket.connectionId);
Openhab.setOffline(socket.connectionId, function (error, openhab) {
if (error) {
logger.error('openHAB-cloud: Error saving openHAB disconnect: ' + error);
return;
}
if(openhab) {
//we will try and notifiy users of being offline
offlineOpenhabs[openhab.uuid] = {
date: Date.now(),
connectionId: socket.connectionId
}

var disconnectevent = new Event({
openhab: openhab.id,
source: 'openhab',
status: 'offline',
color: 'bad'
});

disconnectevent.save(function (error) {
if (error) {
logger.error('openHAB-cloud: Error saving disconnect event: ' + error);
}
});

//actually would redis be better to store? How would we coordinate who send notification?
} else {
logger.warn(`openHAB-cloud: ${openhab.uuid} Did not mark as offline, another instance is connected`);
}
});
});

/*
on('response') is a method for old versions of openHAB-cloud bundle which served the whole response as a single
chunk, while on('responseHeader|responseContent|responseFinished') is for newer versions which send response
Expand Down Expand Up @@ -942,24 +933,6 @@ io.sockets.on('connection', function (socket) {
});
});
});

socket.on('disconnect', function () {
var self = this;
// Find any other sockets for this openHAB and if any, don't mark openHAB as offline
for (var connectedSocketId in io.sockets.connected) {
var connectedSocket = io.sockets.connected[connectedSocketId];
if (connectedSocket !== self && connectedSocket.openhabUuid === self.handshake.uuid) {
logger.info('openHAB-cloud: Found another connected socket for ' + self.handshake.uuid + ', will not mark offline');
return;
}
}
Openhab.findById(self.openhabId, function (error, openhab) {
if (!error && openhab) {
offlineOpenhabs[openhab.uuid] = Date.now();
logger.info('openHAB-cloud: Disconnected ' + openhab.uuid);
}
});
});
});

function notifyOpenHABStatusChange(openhab, status) {
Expand Down
17 changes: 0 additions & 17 deletions models/accesslog.js

This file was deleted.

12 changes: 11 additions & 1 deletion models/openhab.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ var OpenhabSchema = new Schema({
last_online: { type: Date }, // last seen this openHAB online
last_email_notification: {type: Date}, // last notification about openHAB being offline for long time
status: {type: String, default: "offline"}, // current openHAB status (online/offline)
serverAddress: {type: String} // the host:port that this openhab is connected to
serverAddress: {type: String}, // the host:port that this openhab is connected to
connectionId: {type: String} // the local instance ID needed when marking openHABs offline
});

// Index for lookups by uuid
Expand All @@ -25,6 +26,8 @@ OpenhabSchema.index({uuid:1});
OpenhabSchema.index({account:1});
// Index for lookups by status
OpenhabSchema.index({status:1, last_online:1});
// Index for lookups by connectionId
OpenhabSchema.index({connectionId:1});

OpenhabSchema.methods.authenticate = function(openhabUuid, openhabSecret, callback) {
this.model('Openhab').findOne({uuid: openhabUuid, secret: openhabSecret}, function(error, openhab) {
Expand All @@ -40,4 +43,11 @@ OpenhabSchema.methods.authenticate = function(openhabUuid, openhabSecret, callba
});
}

OpenhabSchema.statics.setOffline = function(connectionId, callback) {
this.model('Openhab').findOneAndUpdate(
{ connectionId: connectionId },
{ $set: { status: 'offline', last_online: new Date()}},
callback );
}

module.exports = mongoose.model('Openhab', OpenhabSchema);
16 changes: 0 additions & 16 deletions models/openhabaccesslog.js

This file was deleted.

Loading

0 comments on commit 810415e

Please sign in to comment.