diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 1b219aa..b7b6b9b 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -5,4 +5,5 @@ - Fix command line break when executing command before starting the server (#47). - FIX Client handler after connection update (#51) - FIX Remove old device registration on the new registration (#52) -- Add Travis CI files and changes to enable it in the package.json (#55). \ No newline at end of file +- Add Travis CI files and changes to enable it in the package.json (#55). +- Add Check lifetime and unregister devices (#56) \ No newline at end of file diff --git a/config-mongo.js b/config-mongo.js index c27f52a..c4fd4d7 100644 --- a/config-mongo.js +++ b/config-mongo.js @@ -4,6 +4,7 @@ var config = {}; //-------------------------------------------------- config.server = { port: 5683, // Port where the server will be listening + lifetimeCheckInterval: 1000, // Minimum interval between lifetime checks in ms udpWindow: 100, defaultType: 'Device', logLevel: 'FATAL', diff --git a/config.js b/config.js index fe988a2..160d1f1 100644 --- a/config.js +++ b/config.js @@ -4,6 +4,7 @@ var config = {}; //-------------------------------------------------- config.server = { port: 5683, // Port where the server will be listening + lifetimeCheckInterval: 1000, // Minimum interval between lifetime checks in ms udpWindow: 100, defaultType: 'Device', logLevel: 'FATAL', diff --git a/lib/lwm2m-server.js b/lib/lwm2m-server.js index 8f7a165..ff69265 100644 --- a/lib/lwm2m-server.js +++ b/lib/lwm2m-server.js @@ -141,6 +141,7 @@ function start(config, startCallback) { status = 'ERROR'; } else { status = 'RUNNING'; + registry.checkLifetime(config.lifetimeCheckInterval); } startCallback(error, results); diff --git a/lib/services/server/inMemoryDeviceRegistry.js b/lib/services/server/inMemoryDeviceRegistry.js index fd6e832..8a46980 100644 --- a/lib/services/server/inMemoryDeviceRegistry.js +++ b/lib/services/server/inMemoryDeviceRegistry.js @@ -26,7 +26,12 @@ var registry = {}, idCounter = 1, errors = require('../../errors'), - _ = require('underscore'); + _ = require('underscore'), + logger = require('logops'), + context = { + op: 'LWM2MLib.MemoryDeviceRegistry' + }, + checkLifetimeInterval; /** * Gets the device that has the device name passed as a parameter (should be unique) or return a DeviceNotFound error @@ -147,6 +152,47 @@ function list(callback) { callback(null, result); } + +/** + * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update + * is not received within this lifetime. + * + * @param {Object} lifetimeCheckInterval Minimum interval between lifetime checks in ms + */ +function checkLifetime(lifetimeCheckInterval) { + checkLifetimeInterval = setInterval(function(){ + list(function(error, deviceList){ + if (!error && deviceList) { + deviceList.forEach(function(device){ + if (device.lifetime && + new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { + unregister(device.id, function(err, obj){ + if (err) { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', + obj.name, err.name, err.code); + } + else { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended successfully', + obj.name); + } + }); + } + }); + } + }); + }, lifetimeCheckInterval); +} + +/** + * Stops checking for device lifetime. + */ +function stopLifetimeCheck() { + clearInterval(checkLifetimeInterval); + checkLifetimeInterval = null; +} + /** * Initializes the device registry based on the parameter found in the configuration. For this in memory registry this * function doesn't do anything. @@ -154,6 +200,9 @@ function list(callback) { * @param {Object} config Configuration object. */ function init(config, callback) { + if (config.logLevel) { + logger.setLevel(config.logLevel); + } callback(null); } @@ -163,5 +212,7 @@ exports.get = getObject; exports.update = update; exports.clean = clean; exports.list = list; +exports.checkLifetime = checkLifetime; +exports.stopLifetimeCheck = stopLifetimeCheck; exports.getByName = getByName; exports.init = init; diff --git a/lib/services/server/informationReporting.js b/lib/services/server/informationReporting.js index 314768d..3665fa6 100644 --- a/lib/services/server/informationReporting.js +++ b/lib/services/server/informationReporting.js @@ -193,6 +193,11 @@ function clean(callback) { } subscriptions = {}; + + if (registry){ + registry.stopLifetimeCheck(); + } + callback(); } diff --git a/lib/services/server/mongodbDeviceRegistry.js b/lib/services/server/mongodbDeviceRegistry.js index 9f17dd7..ae507f8 100644 --- a/lib/services/server/mongodbDeviceRegistry.js +++ b/lib/services/server/mongodbDeviceRegistry.js @@ -25,7 +25,12 @@ var errors = require('../../errors'), dbService = require('../model/dbConn'), - Device = require('../model/Device'); + Device = require('../model/Device'), + logger = require('logops'), + context = { + op: 'LWM2MLib.MomgodbDeviceRegistry' + }, + checkLifetimeInterval; /** * Generic function to retrieve a device based on a parameter value. This is an auxiliary function meant to abstract @@ -129,6 +134,7 @@ function register(object, callback) { deviceObj.lifetime = object.lifetime; deviceObj.name = object.name; deviceObj.type = object.type; + deviceObj.creationDate = object.creationDate; deviceObj.save(innerCb); } @@ -170,7 +176,13 @@ function update(id, obj, callback) { callback(error); } else { objDAO.id = obj.id; - objDAO.type = objDAO.type; + objDAO.address = obj.address; + objDAO.port = obj.port; + objDAO.path = obj.path; + objDAO.lifetime = obj.lifetime; + objDAO.name = obj.name; + objDAO.type = obj.type; + objDAO.creationDate = obj.creationDate; objDAO.save(toObject(callback)); } }); @@ -188,6 +200,46 @@ function list(callback) { query.exec(callback); } +/** + * If Lifetime Resource exists, then the registration SHOULD be removed by the Server if a new registration or update + * is not received within this lifetime. + * + * @param {Object} lifetimeCheckInterval Minimum interval between lifetime checks in ms + */ +function checkLifetime(lifetimeCheckInterval) { + checkLifetimeInterval = setInterval(function(){ + list(function(error, deviceList){ + if (!error && deviceList) { + deviceList.forEach(function(device){ + if (device.lifetime && + new Date() - new Date(device.creationDate) > Number(device.lifetime) * 1000) { + unregister(device.id, function(err, obj){ + if (err) { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended up in error [%s] with code [%s]', + obj.name, err.name, err.code); + } + else { + logger.debug(context, + 'Lifetime unregistration for device [%s] ended successfully', + obj.name); + } + }); + } + }); + } + }); + }, lifetimeCheckInterval); +} + +/** + * Stops checking for device lifetime. + */ +function stopLifetimeCheck() { + clearInterval(checkLifetimeInterval); + checkLifetimeInterval = null; +} + /** * Initializes the device registry based on the parameter found in the configuration. The MongoDB config object should * contain at least the host string needed to connect to MongoDB and the database name where to store the device info. @@ -196,9 +248,11 @@ function list(callback) { * * @param {Object} config Configuration object containing a deviceRegistry attribute with the info. */ - -function init(newConfig, callback) { - dbService.init(newConfig.deviceRegistry.host, newConfig.deviceRegistry.db, callback); +function init(config, callback) { + if (config.logLevel) { + logger.setLevel(config.logLevel); + } + dbService.init(config.deviceRegistry.host, config.deviceRegistry.db, callback); } exports.register = register; @@ -207,5 +261,7 @@ exports.get = getObject; exports.update = update; exports.clean = clean; exports.list = list; +exports.checkLifetime = checkLifetime; +exports.stopLifetimeCheck = stopLifetimeCheck; exports.getByName = getByName; exports.init = init; diff --git a/lib/services/server/registration.js b/lib/services/server/registration.js index 450c995..8500b45 100644 --- a/lib/services/server/registration.js +++ b/lib/services/server/registration.js @@ -76,7 +76,8 @@ function storeDevice(queryParams, req, callback) { name: queryParams.ep, lifetime: queryParams.lt, address: req.rsinfo.address, - port: req.rsinfo.port + port: req.rsinfo.port, + creationDate: new Date() }; logger.debug(context, 'Storing the following device in the db:\n%s', JSON.stringify(device, null, 4)); diff --git a/lib/services/server/updateRegistration.js b/lib/services/server/updateRegistration.js index 3ca76af..07d2969 100644 --- a/lib/services/server/updateRegistration.js +++ b/lib/services/server/updateRegistration.js @@ -61,9 +61,10 @@ function endUpdate(req, res) { function updateRegister(req, queryParams, obj, callback) { logger.debug(context, 'Updating device register with lifetime [%s] and address [%s].', queryParams.lt, req.rsinfo.address); - obj.lifetime = queryParams.lt; + obj.lifetime = queryParams.lt || obj.lifetime; obj.address = req.rsinfo.address; obj.port = req.rsinfo.port; + obj.creationDate = new Date(); callback(null, obj); }