Monitoring Internet Connection Speed with Speedtest and Sending Data to VizIoT

In this example, we will create a system for automatically monitoring internet channel speed (Download, Upload, and Latency) using the Speedtest CLI, and then configure it to send data to VizIoT for building graphs and analyzing internet connection quality.


What You'll Need

Hardware

  • Any computer with Linux (example uses Debian/Ubuntu).

Required Software

  • Nano — a console editor.
  • cURL — for working with HTTP.
  • cron — for periodic task execution.
  • NodeJS — a JavaScript runtime environment.
  • Speedtest CLI — a utility for measuring connection speed.

Adding and Configuring the Device in VizIoT

  1. Create a new device named "SPEEDTEST".
  2. Add parameters:
    • latency — Milliseconds (ms)
    • download — Megabytes (MB)
    • upload — Megabytes (MB)
  3. In the "General Settings" section, copy the Access Key and Access Password — they will be needed in the script.

Installing NodeJS

Detailed documentation: https://nodejs.org

Installation via NVM (Recommended)

# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

# Activate without restarting the shell
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Install Node.js (e.g., LTS version)
nvm install --lts

# Check versions
node -v
npm -v

Installing Speedtest CLI

Documentation: https://www.speedtest.net/apps/cli

For Debian/Ubuntu:

sudo apt-get install curl
curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | sudo bash
sudo apt-get update
sudo apt-get install speedtest

Verify it's working:

speedtest

Example output:

   Speedtest by Ookla

     Server: My Company - City, ST (id = 12345)
        ISP: My ISP
    Latency:    10.12 ms   (0.53 ms jitter)
   Download:   851.78 Mbps (data used: 1.1 GB)
     Upload:   667.39 Mbps (data used: 0.8 GB)
Packet Loss:     0.0%
 Result URL: https://www.speedtest.net/result/c/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Creating the NodeJS Program

The program will run the Speedtest CLI, get the JSON result, and send the data to the VizIoT server via MQTT.

Create working directories

mkdir -p /var/viziot/speedtest
cd /var/viziot/speedtest

Initialize the project

npm init -y

Install the VizIoT MQTT library

npm install viziot-mqtt-client-nodejs

Creating the Script

Create the file:

nano index.js

Contents of index.js

const viziotMQTT = require('viziot-mqtt-client-nodejs');
const { exec } = require('child_process');

// VizIoT access key and password
let keyDevice = "__________________";
let passDevice = "______________________";

let viziotMQTTClient = new viziotMQTT(keyDevice, passDevice);

function main() {
  viziotMQTTClient.connect(() => {});

  let intervalTime = 60 * 60 * 1000; // 1 hour
  getPacketAndSendToServer();

  setInterval(() => {
    getPacketAndSendToServer();
  }, intervalTime);
}

main();

function getPacketAndSendToServer() {
  // Specify a server ID for consistent results, e.g., "29493"
  // You can find server IDs by running 'speedtest -L'
  speedTest("29493").then((result) => {
    if (result.success && result.data) {
      const packet = {
        date: Math.floor(Date.now() / 1000),
        latency: result.data.latency,
        download: result.data.download,
        upload: result.data.upload
      };

      viziotMQTTClient.sendDataToVizIoT(packet, (err) => {
        if (err) {
            console.log("publish error:", err);
        } else {
            console.log("Data sent:", packet);
        }
      });
    }
  });
}

function speedTest(idServer) {
  return new Promise((resolve) => {
    let command = 'speedtest --json'; // Use 'speedtest' for the official CLI

    if (idServer && !isNaN(idServer)) {
      command += ` --server-id ${idServer}`;
    }

    exec(command, (error, stdout, stderr) => {
      if (error || stderr) {
        console.log("Speedtest error:", error || stderr);
        return resolve({ success: false });
      }

      try {
        const json = JSON.parse(stdout);

        if (
          json.download && json.download.bandwidth &&
          json.upload && json.upload.bandwidth &&
          json.ping && json.ping.latency
        ) {
          resolve({
            success: true,
            data: {
              latency: json.ping.latency,
              download: json.download.bandwidth * 8 / 1000000, // Convert Bytes/s to Mbit/s
              upload: json.upload.bandwidth * 8 / 1000000 // Convert Bytes/s to Mbit/s
            }
          });
        } else {
          console.log("Unexpected JSON format:", json);
          resolve({ success: false });
        }
      } catch (err) {
        console.log("JSON parse error:", err, "Stdout:", stdout);
        resolve({ success: false });
      }
    });
  });
}

Automatic Execution via cron

Open crontab:

crontab -e

Add the following line:

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

Now the script will run when the system starts.


Adding a Widget in the VizIoT Dashboard

  1. Create a new dashboard "SPEEDTEST".
  2. Add a widget of type "Graph".
  3. Select the device SPEEDTEST.
  4. Select the parameters:
    • latency
    • download
    • upload

After this, data will automatically start appearing on the graph.


All Set!

Now your server automatically measures the internet channel speed and sends the data to VizIoT.