UNPKG

domotz-remote-pawn

Version:

Domotz Agent

243 lines (217 loc) 9.59 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 10/09/15. */ const MODULE_NAME = 'SPEED_TEST'; var lockSeed = Math.random(); var speedTest = function (message, resourceLocator) { const md5 = resourceLocator.utils.random.md5; const time = resourceLocator.utils.time; const mutex = resourceLocator.utils.mutex; const engineClient = resourceLocator.engineRequest; const settingsManager = resourceLocator.settingsManager; const ndtServers = resourceLocator.networkTools.ndtServers; const speedTest = resourceLocator.networkTools.speedTest; const mlabTest = resourceLocator.networkTools.mlabSpeedTest; const fast = resourceLocator.networkTools.fastSpeedTest; const ooklaServers = resourceLocator.networkTools.ooklaServers; const ooklaSpeedTest = resourceLocator.networkTools.ooklaSpeedTest; const ndt7SpeedTest = resourceLocator.networkTools.ndt7SpeedTest; const ndt7Enabled = settingsManager.isNdt7SuiteEnabled() && ndt7SpeedTest.isAvailable(); var myConsole = resourceLocator.log.decorateLogs(); const cid = message.correlationId || 'From API'; const serverId = message.payload.server_id; const nonInteractive = message.non_interactive; var getSpeedTestSuite = resourceLocator.networkTools.speedTest.getSpeedTestSuite; var SPEED_TEST_SUITES = resourceLocator.networkTools.speedTest.SPEED_TEST_SUITES; const speedTestLatency = resourceLocator.latencyMeasurement; var lockId = md5(lockSeed.toString()); function lock() { return mutex.lock(MODULE_NAME, lockId); } function unlock() { mutex.unlock(MODULE_NAME, lockId); } var results = { stats: { start: new Date(), end: null, elapsed_milliseconds: null, }, speedTest: {}, }; function copyResults(ndtInfo) { myConsole.debug('NDT INFO %s', JSON.stringify(ndtInfo)); results.stats.end = new Date(); results.stats.elapsed_milliseconds = time.getDiff(results.stats); results.speedTest = speedTest.ndtInfoIntoDTO(ndtInfo); return speedTest.filterItems(ndtInfo); } function processOoklaResult(data, cb) { function sendResults(result) { var items = copyResults(result); cb(results); engineClient.sendWithPromise('/network/speed-test', 'POST', items); } if (data.blacklist && data.blacklist.length > 0) { myConsole.warn('(%s): Blacklist servers => %s', cid, JSON.stringify(data.blacklist)); ooklaServers.blacklistServers(data.blacklist); } if (!data.error) { if (data.server) { /* store it as preferred server to perform the interactive speed test */ ooklaServers.setServerAsPreferred(data.server); } myConsole.debug('(%s): Speed test success', cid); sendResults(data.result); } else { myConsole.debug('(%s): Speed test failure => %s', cid, data.error); cb(data.error, data.error); } } function callLegacyTest(msg, cb) { ooklaSpeedTest.main( msg, function (data) { speedTestLatency.reportData(); unlock(); processOoklaResult(data, cb); }, function (currentStage) { speedTestLatency.performPingForState(currentStage).catch(handleLatencyTestError); } ); } function ndtTest(callback) { ndtServers .findById(serverId) .then(speedTest.performSpeedTest) .then(copyResults) .then(function (items) { myConsole.debug('%s NDT CB with results %s', JSON.stringify(results)); callback(results); myConsole.debug('%s NDT Send with promise %s', JSON.stringify(items)); return engineClient.sendWithPromise('/network/speed-test', 'POST', items); }) .catch(function (err) { callback(null, err); }); } function interactiveLegacyTest(callback) { myConsole.info('(%s): interactive mode, searching for %s', cid, serverId); ooklaServers .findById(serverId) .then(function (server) { myConsole.info('(%s): found server: %s', cid, JSON.stringify(server)); var msg = { bestServer: server, serverList: null }; callLegacyTest(msg, callback); }) .catch(function () { myConsole.error('Error finding server'); }); } function nonInteractiveLegacyTest(callback) { myConsole.info('%s (%s): Not interactive mode, selecting N closest servers', MODULE_NAME, cid); ooklaServers .getNearestServers() .then(function (serverList) { myConsole.info('(%s): Nearest Server: %s', cid, JSON.stringify(serverList)); var msg = { bestServer: null, serverList: serverList, }; callLegacyTest(msg, callback); }) .catch(function () { myConsole.error('Error getting nearest server'); }); } function handleLatencyTestError(error) { myConsole.error('Latency test failed: %s', error.toString()); } function reportSpeedTestData(items) { return engineClient.sendWithPromise('/network/speed-test', 'POST', items); } return { describe: function () { return cid + ' - ' + MODULE_NAME; }, execute: function (callback) { if (!lock()) { var msg = MODULE_NAME + ' - (' + cid + '): Another Speed test is currently running'; myConsole.warn(msg); return callback(null, { status: 409, message: msg, }); } var speedTestSuite = getSpeedTestSuite(message); if (speedTestSuite === SPEED_TEST_SUITES.NDT) { ndtTest(callback); } else if (speedTestSuite === SPEED_TEST_SUITES.MLAB) { var suite = ndt7Enabled ? ndt7SpeedTest : mlabTest; var suiteName = ndt7Enabled ? 'NDT7' : 'MLAB'; myConsole.debug('selected %s as speed test suite', suiteName); suite .performSpeedTest() .progress(function (currentStage) { if (currentStage === 'download' || currentStage === 'upload') { speedTestLatency.performPingForState(currentStage).catch(handleLatencyTestError); } else { speedTestLatency.performPingForState(currentStage); } }) .then(suite.formatOutput) .then(copyResults) .then(function (items) { speedTestLatency.reportData(); unlock(); myConsole.debug('%s CB with results %s', suiteName, JSON.stringify(results)); callback(results); myConsole.debug('%s Send with promise %s', suiteName, JSON.stringify(items)); return reportSpeedTestData(items); }) .catch(function (error) { callback(null, error); myConsole.error('Error performing speed test %s', error.toString()); unlock(); }); } else if (speedTestSuite === SPEED_TEST_SUITES.FAST) { fast.performSpeedTest() .progress(function (currentStage) { speedTestLatency.performPingForState(currentStage).catch(handleLatencyTestError); }) .then(fast.formatOutput) .then(copyResults) .then(function (items) { speedTestLatency.reportData(); unlock(); callback(results); return reportSpeedTestData(items); }) .catch(function (error) { myConsole.error('Error performing speed test %s', error.toString()); unlock(); }); } else if (speedTestSuite === SPEED_TEST_SUITES.OOKLA) { nonInteractive ? nonInteractiveLegacyTest(callback) : interactiveLegacyTest(callback); } }, getSpeedTestSuite: getSpeedTestSuite, }; }; module.exports.command = speedTest;