domotz-remote-pawn
Version:
Domotz Agent
166 lines (143 loc) • 5.91 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2023 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/>.
*
*
* Sends the counters of DHCP requests to the cloud,
* Created by Stefano Cicero <stefano.cicero@domotz.com> on 29/06/23.
*/
var latencyData = { download_loaded: [], upload_loaded: [], unloaded: [] };
function speedTestLatency(resourceLocator) {
var rtdScan = resourceLocator.networkTools.rtd;
var ping = resourceLocator.netPing;
var session;
var q = resourceLocator.q;
var async = resourceLocator.async;
var myConsole = resourceLocator.log.decorateLogs();
var latencyUtils = require('../latency/utils')(resourceLocator);
var engineClient = resourceLocator.engineRequest;
var initialStage = null;
var lodash = resourceLocator.lodash;
const settings = latencyUtils.getSettings(resourceLocator.settingsManager);
const namePhaseConversion = {
download: 'download_loaded',
upload: 'upload_loaded',
unloaded: 'unloaded',
};
function performPingForState(currentStage, samples) {
var deferred = q.defer();
if (!canPerformLatencyMeasurement()) {
return q.reject('latency measurement not enabled');
}
var pingCount = 0;
const stageNameConverted = namePhaseConversion[currentStage];
initialStage = currentStage;
if (stageNameConverted === undefined) {
return q.resolve();
}
if (currentStage !== 'unloaded') {
latencyData[stageNameConverted] = [];
}
myConsole.info('Start latency measurement for stage %s', currentStage);
session = ping.createSession({
networkProtocol: ping.NetworkProtocol.IPv4,
packetSize: settings.packetSize,
retries: 0,
timeout: settings.timeout,
});
function run() {
latencyUtils
.serverLookup(settings.server)
.then(function (serverIP) {
var samplesLen = samples || settings.maxPingNumber;
async.whilst(
function test() {
return initialStage === currentStage && pingCount < samplesLen;
},
function iter(callback) {
pingCount++;
rtdScan.pingDevice(serverIP, 0, session, function (error, resultMs) {
if (stageNameConverted in latencyData && !error) {
myConsole.debug('%s %s rtt: %sms', stageNameConverted, pingCount, resultMs);
latencyData[stageNameConverted].push(resultMs);
}
setTimeout(function () {
callback(null, pingCount);
}, settings.interPingDelay);
});
},
function () {
deferred.resolve();
}
);
})
.catch(function (error) {
deferred.reject(error);
});
}
setTimeout(run, settings.warmupPeriod);
return deferred.promise;
}
function filterValidSamples(samples) {
var maxPingNumber = settings.maxPingNumber;
var l = lodash.filter(samples, function (o) {
return o !== null;
});
l = lodash.map(l, function (elem) {
//replace sub-ms values with 1
return elem === 0 ? 1 : elem;
});
return l.slice(-maxPingNumber);
}
function reportData() {
initialStage = null;
var reportData = {
download_loaded: filterValidSamples(latencyData.download_loaded),
upload_loaded: filterValidSamples(latencyData.upload_loaded),
unloaded: filterValidSamples(latencyData.unloaded),
};
myConsole.debug('Latency samples: %s', JSON.stringify(latencyData));
if (reportData.download_loaded.length > 0 && reportData.upload_loaded.length > 0 && reportData.unloaded.length > 0) {
engineClient.sendWithPromise('/latency', 'POST', reportData).catch(function () {
myConsole.error('Error reporting latency data');
});
} else {
myConsole.info('Latency data not sent, missing valid samples');
}
}
function _setLatencyData(fakeData) {
latencyData = fakeData;
}
function canPerformLatencyMeasurement() {
if (!settings.isLatencyMeasurementActive) {
myConsole.info('latency measurement is disabled by settings');
return false;
} else if (!ping) {
myConsole.info('net-ping is unsupported on this platform');
return false;
}
return true;
}
return {
performPingForState: performPingForState,
reportData: reportData,
settings: settings,
canPerformLatencyMeasurement: canPerformLatencyMeasurement,
_setLatencyData: _setLatencyData,
};
}
module.exports = {
speedTestLatency: speedTestLatency,
};