NodeJS -> Internet Speed Test Monitoring

An example of monitoring the speed of internet connection using speedtest.net and a Linux-based PC.

What you'll need:

  • Computer: Any computer with a Linux operating system, in this case Debian.
  • Software:
    • Nano — Console-based text editor.
    • cURL — Command-line program for working with HTTP.
    • cron — Daemon for periodic task execution.
    • NodeJS — Server-side platform for working with JavaScript using the V8 engine.
    • SPEEDTEST — Internet connection speed testing service.

Adding and configuring the device:

  1. 1. Add a new device to VizIoT with the name "SPEEDTEST".
  2. 2. Configure the device parameters. Add three parameters:
    1. Key latency with type "Milliseconds, ms"
    2. Key download with type "Megabytes, MB"
    3. Key upload with type "Megabytes, MB"
  3. 3. In the "Basic Settings" of the device, copy the Access Key and Access Password.

Installing NodeJS:

Refer to the NodeJS documentation. Standard installation for Ubuntu or Debian:

# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt-get install -y nodejs

Installing SPEEDTEST:

Refer to the SPEEDTEST documentation. Standard installation for Ubuntu or Debian:

sudo apt-get install gnupg1 apt-transport-https dirmngr
export INSTALL_KEY=379CE192D401AB61
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys $INSTALL_KEY
echo "deb https://ookla.bintray.com/debian generic main" | sudo tee  /etc/apt/sources.list.d/speedtest.list
sudo apt-get update
# Other non-official binaries will conflict with Speedtest CLI
# Example how to remove using apt-get
# sudo apt-get remove speedtest-cli
sudo apt-get install speedtest

The SPEEDTEST utility measures the parameters of your internet connection and displays Download speed, Upload speed, and Latency in the console. Let's test SPEEDTEST in the console. To do this, type the following command in the terminal:

speedtest

You'll receive a response similar to the following text:

Speedtest by Ookla

Server: Kyivstar - Kiev (id = 23493)
ISP: Private Joint-stock Company farlep-invest
Latency:    22.72 ms   (0.11 ms jitter)
Download:    89.86 Mbps (data used: 63.2 MB)
Upload:    93.63 Mbps (data used: 101.5 MB)
Packet Loss: Not available.
Result URL: https://www.speedtest.net/result/c/cc8fd3b0-9087-4961-aa78-1a3e91f24465

Creating a NodeJS Program. The program will execute the Speedtest command, extract the textual result, and retrieve the desired data: Download speed, Upload speed, and Latency.

Create a directory:

mkdir /var/viziot/
mkdir /var/viziot/speedtest

Navigate to the directory:

cd /var/viziot/speedtest

Create a NodeJS project:

npm init

Install the helper module viziot-mqtt-client-nodejs — it facilitates sending data to the VizIoT server using MQTT protocol:

npm install viziot-mqtt-client-nodejs -s

Create a script file:

nano ./index.js

Script content:

'use strict';

// Access key and password for VizIoT
let keyDevice = ___________________;
let passDevice = ____________________________;

let viziotMQTT = require('viziot-mqtt-client-nodejs');
let viziotMQTTClient = new viziotMQTT(keyDevice, passDevice);
viziotMQTTClient.connect(function () {});

function getPacketAndSendToServer() {
	speedTest("*", function (result) {
		console.log(result);
		if(result.type == "ok"){
			let packet = {
				'date': parseInt(new Date().getTime()/1000),
				"latency":result.latency, 
				"download":result.download, 
				"upload":result.upload 
			};
			viziotMQTTClient.sendDataToVizIoT(packet, function (err) {
				if (err) {
					console.log("publish", err);
				}
			});
		}
	});
}



function speedTest(idServer, callBack){
	const { exec } = require("child_process");
	var command = "speedtest"; 
	if(idServer != undefined && idServer != "*" && !isNaN(idServer) && idServer > 0){
		command = "speedtest -s " + idServer;
	}
	console.log("Выполнение команды", command);
	exec(command, (error, stdout, stderr) => {
		if (error) {
			console.log(`error: ${error.message}`);
			callBack({type: "error message"});
			return;
		}
		if (stderr) {
			console.log(`stderr: ${stderr}`);
			callBack({type: "error stderr"});
			return;
		}
		console.log(`stdout: ${stdout}`);
		var arrayString = stdout.replace(new RegExp("\r",'g'), "").split("\n");
		var latency = getValue(arrayString, "Latency", "ms");
		var download = getValue(arrayString, "Download", "Mbps");
		var upload = getValue(arrayString, "Upload", "Mbps");
		if(!isNaN(latency) && !isNaN(download) && !isNaN(upload)){
			callBack({
				"type": "ok", 
				"latency":latency, 
				"download":download, 
				"upload":upload 
			});
			return;
		}else{
			callBack({"type": "error parse","latency":latency, 
				"download":download, 
				"upload":upload });
			return;
		}
	});
}	
function getValue(arrayString, nameParametr, typeMeasure) {
	for (var ii = 0; ii < arrayString.length; ii++) {
		if(arrayString[ii].indexOf(nameParametr + ":") !== -1) {
			return parseFloat(arrayString[ii].replace(new RegExp("^.*" + nameParametr + ": *"), "").replace(new RegExp(" "+ typeMeasure + ".*$"), ""));
		}
	}
	return NaN;
}

getPacketAndSendToServer();
let intervalTime = 1000 * 60 * 5;
setInterval(function () {
	getPacketAndSendToServer();
}, intervalTime);

This script will be launched at system startup. To do this, we will add a record to the cron. Let's open the cron editor:

crontab -e

And at the very end, add a line that will run the script "/var/viziot/speedtest/index.js":

@reboot node /var/viziot/speedtest/index.js > /var/viziot/speedtest/output.txt &

Adding a widget:

  1. Create a new panel named "SPEEDTEST"
  2. Add a widget "SPEEDTEST"
    1. Type: "Graph";
    2. Device: "SPEEDTEST";
    3. Parameters: latency, download, upload;
  3. Done. Await the data to be sent to the server.