domotz-remote-pawn
Version:
Domotz Agent
187 lines (164 loc) • 6.84 kB
JavaScript
/** 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 (q, cacheUtils, configuration, request, random, distanceCalculator, resetCache) {
resetCache = typeof resetCache !== 'undefined' ? resetCache : true;
if (resetCache) {
console.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) {
console.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) {
console.error("NDT - Cannot fetch servers list: " + JSON.stringify(err));
throw err;
}
if (response.statusCode !== 200) {
const error = {message: body, code: response.statusCode};
console.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;
console.info("NDT - Fetching NDT Server list from: " + queryUrl);
request.get({uri: queryUrl}, function (err, response, body) {
console.info("NDT - Server list response arrived");
try {
handleError(err, response, body);
var rawData = JSON.parse(body);
console.log('2ciao');
const servers = parseServers(rawData);
console.log(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;
});
console.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";
console.error(message);
return deferred.reject({message: message, status: 404});
}
var server = servers.shift();
var hostname = server.service.hostname;
console.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, body) {
if (!error && response.statusCode === 200) {
return deferred.resolve(server);
}
return testServer();
});
};
testServer();
return deferred.promise;
};
var fromAPIItem = function fromAPIItem(item) {
if (!item['service-hostname']) {
console.error("Replacing hostname with ip address for host:" + item['service-locator'][0]);
try {
item['service-hostname'] = item['service-locator'][0].split('//')[1].split(':')[0];
}
catch (error) {
throw error;
}
}
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;