UNPKG

domotz-remote-pawn

Version:

Domotz Agent

191 lines (169 loc) 7.11 kB
/** This file is part of Domotz Agent. * Copyright (C) 2016 Domotz Ltd * * Domotz Agent is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Domotz Agent is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>. **/ /** * * Created by Iacopo Papalini <ipapalini@domotz.com> on 16/09/15. */ const COORDINATE_REGEXP = new RegExp('^([-+]?[0-9]+(.[0-9]+)?)([NSWE])?$'); const CACHE_SCOPE = 'ndt-servers'; var factory = function (resourceLocator, distanceCalculator, resetCache) { var myConsole = resourceLocator.log.decorateLogs(); var q = resourceLocator.q; var cacheUtils = resourceLocator.utils.cache; var configuration = resourceLocator.configuration; var request = resourceLocator.request; var random = resourceLocator.utils.random; resetCache = typeof resetCache !== 'undefined' ? resetCache : true; if (resetCache) { myConsole.info('NDT - Resetting cache, scope = ' + CACHE_SCOPE); cacheUtils.createCache(CACHE_SCOPE).reset(); } function parseServers(serversList) { var servers = []; serversList.forEach(function (item) { try { var server = fromAPIItem(item); servers.push(server); } catch (exception) { myConsole.warn('NDT - Cannot parse NDT server item: ' + JSON.stringify(item)); } }); servers.sort(function (a, b) { return a.location.distance - b.location.distance; }); return servers; } function handleError(err, response, body) { if (err) { myConsole.error('NDT - Cannot fetch servers list: ' + JSON.stringify(err)); throw err; } if (response.statusCode !== 200) { const error = { message: body, code: response.statusCode }; myConsole.error('NDT - Cannot fetch servers list: ' + JSON.stringify(error)); throw error; } } var fetch = function () { var cache = cacheUtils.createCache(CACHE_SCOPE); const CACHE_KEY = 'fetch'; var deferred = q.defer(); cache.get( CACHE_KEY, function () { var queryUrl = configuration.external_scripts.ndt.servers_query_url; myConsole.info('NDT - Fetching NDT Server list from: ' + queryUrl); request.get({ uri: queryUrl }, function (err, response, body) { myConsole.info('NDT - Server list response arrived'); try { handleError(err, response, body); var rawData = JSON.parse(body); myConsole.info('2ciao'); const servers = parseServers(rawData); myConsole.info(servers); deferred.resolve(servers); cache.set(CACHE_KEY, servers); } catch (err) { return deferred.reject(err); } }); }, function (servers) { deferred.resolve(servers); } ); return deferred.promise; }; var findById = function (serverId) { var deferred = q.defer(); fetch().then(function (servers) { servers.every(function (server) { if (server.id === serverId) { deferred.resolve(server); return false; } return true; }); myConsole.warn('NDT - No server found'); deferred.reject({ status: 404, message: 'NOT FOUND' }); }); return deferred.promise; }; var findNearestResponding = function (servers, timeout, maxAttempts) { var deferred = q.defer(); var commonUrl = 'http://%s:7123'; servers = servers.slice(0, maxAttempts); var testServer = function () { if (servers.length === 0) { const message = 'No responsive server found'; myConsole.error('testNdtServer: ' + message); return deferred.reject({ message: message, status: 404 }); } var server = servers.shift(); var hostname = server.service.hostname; myConsole.info('NDT - Connecting to server %s with timeout of %ss ', hostname, timeout); request.get({ timeout: timeout * 1000, uri: require('util').format(commonUrl, hostname) }, function (error, response) { if (!error && response.statusCode === 200) { return deferred.resolve(server); } return testServer(); }); }; testServer(); return deferred.promise; }; var fromAPIItem = function fromAPIItem(item) { if (!item['service-hostname']) { myConsole.error('Replacing hostname with ip address for host:' + item['service-locator'][0]); item['service-hostname'] = item['service-locator'][0].split('//')[1].split(':')[0]; } var server = { id: random.md5(JSON.stringify(item)), service: { type: item['service-type'][0], locator: item['service-locator'], host: item['service-host'][0], hostname: item['service-hostname'], }, location: { siteName: item['location-sitename'] ? item['location-sitename'][0] : null, latitude: NaN, longitude: NaN, state: item['location-state'] ? item['location-state'][0] : null, zipcode: item['location-code'] ? item['location-code'][0] : null, }, }; if ( item['location-latitude'] && COORDINATE_REGEXP.test(item['location-latitude']) && item['location-longitude'] && COORDINATE_REGEXP.test(item['location-longitude']) ) { server.location.latitude = parseFloat([item['location-latitude'][0].match(COORDINATE_REGEXP)[1]][0]); server.location.longitude = parseFloat([item['location-longitude'][0].match(COORDINATE_REGEXP)[1]][0]); } server.location.distance = distanceCalculator.distanceTo(server.location.latitude, server.location.longitude); return server; }; return { fetch: fetch, findNearestResponding: findNearestResponding, findById: findById, fromAPIItem: fromAPIItem, }; }; module.exports.factory = factory;