Raspberry Pi Internet Speed Monitor

In this Raspberry Pi internet speed monitor tutorial, we will be showing you how you can set up your Raspberry Pi to monitor your internet connection and save the data to view in Grafana or Google Drive.

 Raspberry Pi Internet Speed Monitor

This tutorial is great if you’re interested in monitoring how your download speed, upload speed, and ping are affected over time.

Additionally, this can help you work out what times your network may be at its peak capacity or if you’re suffering from a degraded internet connection.

To achieve this internet speed monitor, we will be showing you how to write a small Python script that interacts with a program called Speedtest CLI from Ookla.

Speedtest CLI is what our internet speed monitor will use to monitor the internet connection.

This program works by polling the popular speedtest.net service to get your ping, download speed, and upload speed.

Equipment List

Below are all the pieces of equipment that we made use of to set up our Raspberry Pi internet speed monitor.

Recommended

Raspberry Pi

Micro SD Card

USB Drive

Ethernet Cable (Recommended) or Wifi dongle (Pi 3 has Wifi inbuilt)

Optional

Raspberry Pi Case

Video

You can watch the video below to learn how to set up an internet speed monitor on the Raspberry Pi.

Alternatively check out the written version of the guide in the next section.

Adblock blocking the video? Support us by subscribing to our ad-free service.

Installing the Speedtest CLI

1. Before we get started with setting up the Raspberry Pi to monitor the internet’s speed, we must first make sure our Raspberry Pi is up to date.

We can update the Raspberry Pi by running the following two commands within the terminal.

sudo apt-get update
sudo apt-get upgrade

2. We now need to install some packages so that we can add the package repository for the Speedtest CLI software.

Run the following command to install gnupg1, apt-transport-https, and dirmngr to your Raspberry Pi.

sudo apt install apt-transport-https gnupg1 dirmngr

The apt-transport-https package is used to add support for the https protocol to the apt package manager. Without it apt will throw errors when connecting to Ookla’s package repository.

Additionally we also install gnupg1, this package is used for secure communication between your Raspberry Pi and the Speedtest.net servers.

Finally, we install the dirmngr package. This package is utilized for handling the addition of the package repository to your Raspberry Pi’s sources list.

3. With the packages we need installed we can now add the GPG key for Ookla’s Speedtest repository to the keychain.

We need this keychain to be able to download the speedtest command line interface to our Raspberry Pi.

wget -q -O - https://packagecloud.io/ookla/speedtest-cli/gpgkey | sudo apt-key add -

4. Next we need to add the Ookla repository to our sources list.

Without adding the repository we won’t be able to install the Speedtest CLI to our Raspberry Pi.

You can add this repository by running the following command.

echo "deb https://packagecloud.io/ookla/speedtest-cli/debian/ $(lsb_release -cs) main" | sudo tee  /etc/apt/sources.list.d/speedtest.list

Within this command, you will notice we use “$(lsb_release -cs)“. This bit of text allows us to insert the release name for our installation of Raspberry Pi OS directly into the command.

5. As we added a new package repository we need to update our package list.

Updating the package list is as simple as running the following command.

sudo apt update

6. Finally, we can install the official Speedtest CLI to our Raspberry Pi from Ookla.

Use the following command to install the package to your device.

sudo apt install speedtest

6. We can now test that we have installed the speedtest software to your Raspberry Pi.

Let us run the following command to start up the speedtest.

speedtest

When you first run the speedtest software on your Raspberry Pi you will be asked to agree to some terms and conditions.

To proceed passed this warning all you need to do is type in “YES” followed by the ENTER key.

Writing our Speed Test Python Script

1. Now that we have Speedtest CLI installed on the Raspberry Pi, we can now proceed to write our Python script that will continually monitor our download and upload speeds.

We can begin creating our Python script for the Raspberry Pi internet speed monitor by running the following command.

cd ~
nano speedtest.py

2. Within this file write the following lines of code. We will explain each important section of the code, so you get an idea of how everything works.

import os
import re
import subprocess
import time

These four lines define all of the libraries that we will be relying on in our script. Below we will explain how each of these libraries will be is used.

import os: The os library is used by the script to interact with the operating system itself.

For this script, we will be using this library to check if a file exists.

import re: The re library allows us to easily do regular expressions by providing a library for handling pattern searches.

We use this to find our wanted values out of the data given to us from the Speedtest CLI.

import subprocess: The subprocess library is essential to this script, as we require it to be able to call another python script.

In our case, we will be using the subprocess library so we can launch up the Speedtest CLI software and retrieve the values returned by it.

import time: We utilize the time library so that we can record both the date and time for each call to the Speedtest CLI software.

This library is what will allow us to track our speed over a length of time.

response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

In this line of code, we utilize the subprocess library to launch a call to the Speedtest CLI and tell it to pipe everything from speedtest to stdout.

By using stdout.read().decode('utf-8') at the end of the call we store the response from the Speedtest CLI to our response variable and decode it to being a useable Python string.

ping = re.search('Latency:\s+(.*?)\s', response, re.MULTILINE)
download = re.search('Download:\s+(.*?)\s', response, re.MULTILINE)
upload = re.search('Upload:\s+(.*?)\s', response, re.MULTILINE)
jitter = re.search('\((.*?)\s.+jitter\)\s', response, re.MULTILINE)

These three lines of code are fairly simple, and all do the same thing.

They use the re library to run a regular expression for a certain piece of text and find the number located next to each piece of text.

For instance, the search for ping finds “Latency: 47.943 ms” but only grabs the number that is between the text.

ping = ping.group(1)
download = download.group(1)
upload = upload.group(1)
jitter = jitter.group(1)

These lines are important as we use the “.group()” function to grab the correct numbers from our regular expressions.

Using this we will get the values we are after from the output of the Speedtest CLI software that we can write to our CSV file.

try:
    f = open('/home/pi/speedtest/speedtest.csv', 'a+')
    if os.stat('/home/pi/speedtest/speedtest.csv').st_size == 0:
            f.write('Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps)\r\n')
except:
    pass

This bit of code is straightforward. The code is kept within a try statement so that if any errors occur, it will not stop the script from operating.

Within the try statement, we first open up a call to our speedtest.csv file.

By using, “a+” in the arguments, we tell it that we want to create the file if it doesn’t exist and that any new data should be appended to whatever is already in there.

Afterward, we utilize the os library to check our speedtest.csv files actual size in bytes.

If the file’s bytes is equal to 0, we go ahead.

If the file does exist we proceed on as normal.

f.write('{},{},{},{},{},{}\r\n'.format(time.strftime('%m/%d/%y'), time.strftime('%H:%M'), ping, jitter, download, upload))

Finally, we print out all our data separated by commas.

We use the time library’s strftime() function to insert both the current date and the current time into our formatted string.

After that, we insert our ping, download, and upload.

Below we have an included an example of what the output data will look like on the first run of our code.

Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps)
04/29/21,06:28,18.32,1.21,23.30,7.78

3. Once you have finished writing your code, it should end up looking like what we have displayed below.

import os
import re
import subprocess
import time

response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

ping = re.search('Latency:\s+(.*?)\s', response, re.MULTILINE)
download = re.search('Download:\s+(.*?)\s', response, re.MULTILINE)
upload = re.search('Upload:\s+(.*?)\s', response, re.MULTILINE)
jitter = re.search('\((.*?)\s.+jitter\)\s', response, re.MULTILINE)

ping = ping.group(1)
download = download.group(1)
upload = upload.group(1)
jitter = jitter.group(1)

try:
    f = open('/home/pi/speedtest/speedtest.csv', 'a+')
    if os.stat('/home/pi/speedtest/speedtest.csv').st_size == 0:
            f.write('Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps)\r\n')
except:
    pass

f.write('{},{},{},{},{},{}\r\n'.format(time.strftime('%m/%d/%y'), time.strftime('%H:%M'), ping, jitter, download, upload))

4. You can now save the file by pressing CTRL + X then Y and finally press ENTER.

5. With our script now written we need to make a folder where our speedtest.csv file will be stored. Run the following command to create this folder.

mkdir ~/speedtest

6. Now that we have made the required folder, we can go ahead and test the script.

We can test our script by running the following command.

python3 ~/speedtest.py

7. Once the script has finished executing you can then check out the results by opening up the newly created speedtest.csv.

Let’s open up this file by running the following command on the Raspberry Pi.

nano ~/speedtest/speedtest.csv

8. Within this file, you should see something like what we have below. The column headers and some rows of data.

Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps)
04/29/21,06:28,18.32,1.21,23.30,7.78

There are two different ways you can take this guide.

You can either use InfluxDB and Grafana to store and graph your data, or make use of gDrive to sync your data to Google Drive.

Using Grafana to Display your Speedtest Data

In this section, we will be showing you how you can use Grafana to graph your speed test data quickly.

Setting up InfluxDB for our Internet Speed Monitor

Before you start this section of this internet speed monitor tutorial, you will need to make sure you have installed InfluxDB to your Raspberry Pi or on a separate server.

We will be using this as a place to store the data that our internet speed monitor receives.

1. To start, we need to go ahead and run the following command to start up the InfluxDB command-line tool.

We will be using this tool to create a database where we will store our data.

influx -username admin -password <password>

If you haven’t set up authentication, then you don’t need to worry about specifying the username and password to connect to InfluxDB.

2. Let’s now create a database called “internetspeed“.

Creating a database within InfluxDB is easy as using CREATE DATABASE followed by the database name.

CREATE DATABASE internetspeed

3. Our next step is to create a user called “speedmonitor” that we will be using to interact with our database.

Make sure that you swap out the password “pimylifeup” with something a bit more secure.

Don’t worry about privileges as we will be handling that in the next step.

CREATE USER "speedmonitor" WITH PASSWORD 'pimylifeup'

4. Now assign the new “speedmonitor” user all privileges to our “internetspeed” database.

GRANT ALL ON "internetspeed" to "speedmonitor"

5. With the database created, quit out of the tool by using the following command.

quit

6. The last thing we need to do is install the Python library we need to interact with our Influx database.

sudo apt install python3-influxdb

Saving our Speed Monitor Data to our InfluxDB

1. Now that we have our InfluxDB database created, let’s begin adding data into it by creating a new Python script.

This script will be similar to the one we created earlier, so we will only explain the new things that we are doing.

rm ~/speedtest.py
nano ~/speedtest.py

2. To start off this file, we need to import all the Python libraries we need.

import re
import subprocess
from influxdb import InfluxDBClient

As you can see, we have removed both the “os” and “time” libraries.

Both of these libraries are no longer needed as we don’t need to interact with files, and Influx automatically timestamps data.

We now import the “InfluxDBClient” client, which we will be using to interact with our InfluxDB server.

3. Our next step after importing packages is to call the Speedtest CLI and process the data.

By the end of this code block, we will have just the data that we are after.

response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

ping = re.search('Latency:\s+(.*?)\s', response, re.MULTILINE)
download = re.search('Download:\s+(.*?)\s', response, re.MULTILINE)
upload = re.search('Upload:\s+(.*?)\s', response, re.MULTILINE)
jitter = re.search('\((.*?)\s.+jitter\)\s', response, re.MULTILINE)

ping = ping.group(1)
download = download.group(1)
upload = upload.group(1)
jitter = jitter.group(1)

4. Now here is where things get a little bit different. We need to format that data into a Python dictionary.

The reason for this is that the library expects the data to be in a JSON like format.

speed_data = [
    {
        "measurement" : "internet_speed",
        "tags" : {
            "host": "RaspberryPiMyLifeUp"
        },
        "fields" : {
            "download": float(download),
            "upload": float(upload),
            "ping": float(ping),
            "jitter": float(jitter)
        }
    }
]

Here we set up our dictionary with how InfluxDB expects the data. We gave the measurement a name, “internet_speed“.

We also set a tag called “host” to allow us to separate this out if we decide to handle multiple devices in the same database.

Next, we pass in the fields, which is the download speed, upload speed and ping that we retrieved in the previous bit of code.

We wrap our download, upload and ping variables in the float() function to convert them from a string to a number.

If we don’t use the float() function, Grafana will see these as strings and not interpret them correctly.

5. With all the data we need now on hand, we can now proceed to start using InfluxDB.

The first thing we need to do is to instantiate the InfluxDBClient library and pass in our connection details.

We only pass in the first five parameters for this function, the host, port, username, password, and database name.

If you want to see what data can be set, then you can view the official InfluxDB Python documentation.

client = InfluxDBClient('localhost', 8086, 'speedmonitor', 'pimylifeup', 'internetspeed')

If you are using an InfluxDB server that is not located on your Raspberry Pi, make sure you switch “localhost” with its IP address.

Also, you will need to change “pimylifeup” to the password that you set up earlier in the guide.

6. With a connection now made to our InfluxDB server, we can now write our data point to the server by adding the following line of code.

client.write_points(speed_data)

7. That is all we need to do to pass data to InfluxDB.

When you have finished typing in all the code the file, it should end up looking like what we have below.

import re
import subprocess
from influxdb import InfluxDBClient

response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

ping = re.search('Latency:\s+(.*?)\s', response, re.MULTILINE)
download = re.search('Download:\s+(.*?)\s', response, re.MULTILINE)
upload = re.search('Upload:\s+(.*?)\s', response, re.MULTILINE)
jitter = re.search('\((.*?)\s.+jitter\)\s', response, re.MULTILINE)

ping = ping.group(1)
download = download.group(1)
upload = upload.group(1)
jitter = jitter.group(1)

speed_data = [
    {
        "measurement" : "internet_speed",
        "tags" : {
            "host": "RaspberryPiMyLifeUp"
        },
        "fields" : {
            "download": float(download),
            "upload": float(upload),
            "ping": float(ping),
            "jitter": float(jitter)
        }
    }
]
client = InfluxDBClient('localhost', 8086, 'speedmonitor', 'pimylifeup', 'internetspeed')

client.write_points(speed_data)

8. Save the file by pressing CTRL + X, followed by Y, then ENTER.

Viewing our Internet Speed Data in Grafana

Our next step is to get this database to show up in Grafana.

Before beginning this section, you must make sure that you have Grafana set up on your Raspberry Pi or a separate device.

Grafana is the tool that we will be using to graph and visualize all our data.

1. Once you have Grafana set up, you can proceed on with this tutorial by opening up its web interface.

If you are unsure where this sits, then go to your Raspberry Pi’s or server’s IP address, followed by the port :3000.

IPADDRESS:3000

2. Within the Grafana web interface, we need to add a new data source.

You can do this by hovering over the cog in the sidebar (1.), followed by the “Data Sources” menu option (2.).

Adding a new data source to Grafana

3. In the next menu, you will need to click the “Add data source” button to proceed.

Add Data Source to Grafana Configuration Page

4. On the “Add data source” page, you need to find InfluxDB, hover over it and click the “Select” button.

Add InfluxDB Time series database to Grafana

5. Now we are required to enter the details of your InfluxDB installation.

First, enter the URL for InfluxDB (1.). In our case, this is on the same Raspberry Pi that we are running the software on. If you are doing the same, then use the following URL.

http://localhost:8086

Next, we will need to enter all the details for our database (2.).

If you have followed our guide exactly, the Database should be set to “internetspeed“.

The User should be “speedmonitor”, and finally, the password should be the one you specified, if you used our example one this password would be “pimylifeup“.

Once you have set all the required information, click the “Save & Test” button (3.) located at the bottom of the screen.

Add InfluxDB Details for Grafana

6. The next step is to create a dashboard to display this data.

Hover over the addition icon (+) in the sidebar and click the “Dashboard” option.

Creating a Dashboard in Grafana

6. Over the “New Panel“, click the “Add Query” button.

Add Query to Dashboard

7. We can now set up the graph to read from our database.

Clickselect measurement” (1.) then select our measurement name, which in this case is “internet_speed” (2.)

Select Measurement to query

8. With the measurement set, we now need to set the field data we want to obverse.

Click the text “value” next to the field (1.). From here, select either “download“, “ping” or “upload“.

For this guide, we will be starting with “download” (2.).

Select Field to Display

9. Next, we want to make Grafana treat each result as a distinct individual result.

We can do this by clicking the addition (+) button in the select row (1.).

In the pop-up menu, hover over “Aggregations” and clickdistinct” (2.).

Change data aggregation

10. Finally, let’s give this data a better name so that we can understand it easier.

Set the alias of each of the fields to represent what they contain (1.). For example, with the download speed, we set the name “Download Speed“.

Now click the “Add Query” button (2.) and repeat steps 79 until you have all three fields (download, upload, and ping) added to the graph.

Set Data Alias for Measurement

11. Once you have added each field to the graph, click the spanner and cog symbol in the sidebar.

Configure Grafana Panel

12. In the “Title” option (1.) type in what you want to be displayed above the graph. In this example, we used the title “Network Speed“.

Once that is done, save the dashboard by clicking the save button (2.) in the top right-hand corner of the screen.

Set Panel Name for Grafana

13. Give a name to your dashboard (1.). This name can be anything you want. We called our “Network Speed Monitor“.

Now you save this new dashboard by clicking the “Save” button (2.).

Save Grafana Dashboard

14. With everything done, you should now be able to see your data displayed in a nice graph.

Internet Speed Monitor Dashboard Ready

Automating your Speed Monitor script with Grafana

Automating your script so that it runs periodically is a reasonably straightforward process.

1. The easiest way to automate your script to run every so often is to make use of the crontab.

You can modify the crontab by running the following command on your Raspberry Pi.

crontab -e

If you are asked what editor you want to use, we recommend you select nano as its the easiest to use.

2. Within this file, add the following cronjob to the bottom.

This cronjob will run every 30 minutes. If you want to work out a different timing, we recommend that you make use of our Crontab generator.

*/30 * * * * python3 /home/pi/speedtest.py

As you can see, this is an effortless way of getting your internet speed tested regularly and not require you to run the script manually.

3. Once done, you can save the file by pressing CTRL + X, then Y, followed by ENTER.

The crontab will automatically be updated and will begin to run your script immediately.

Uploading your Internet Speed Data to Google Drive

In this section, we will be showing you how you can automatically sync your data with your Google Drive account.

Uploading Speed Test Data to Google Drive

1. Before you begin this section, you must have completed our compiling and running gDrive guide.

We will be using that software to complete the following steps.

2. With gDrive setup on your Raspberry Pi, we can now prepare it for our speed test data.

Let’s start by using gDrive to create a new folder on your Google Drive to store our speedtest.csv file.

We can do that by using the following command within the terminal.

gdrive mkdir speedtest

This command will show you a message saying the directory was created. This message will also show you an ID.

We will need this ID for our next few steps, so write it down somewhere safe.

3. With the folder now created, we can use its ID to upload a file to it.

For this test, we will be uploading our speedtest.csv file.

Run the following command and make sure you replace YOUR_FOLDER_ID with the id you retrieved in the previous step.

gdrive sync upload ~/speedtest YOUR_FOLDER_ID

On the initial sync, you should see a message like below appear on the command line.

This message tells you that the file has been successfully synced to your Google Drive account.

Starting sync...
Collecting local and remote file information...
Found 1 local files and 0 remote files

1 remote files are missing
[0001/0001] Uploading speedtest.csv -> speedtest/speedtest.csv
Sync finished in 3.119979351s

4. With Google Drive now successfully syncing with the Raspberry Pi, we can move onto automating the whole process so that we upload the speedtest.csv every time we edit it.

Automating the Raspberry Pi Internet Speed Monitor for Google Drive

1. The next big thing to do with your Raspberry Pi Internet Speed Monitor is to automate it.

To do the automation, we will be writing a simple bash script. This script will be called by crontab so that it will be run routinely.

Begin writing the bash script by running the following Linux command on your Raspberry Pi.

nano ~/speedtest.sh

2. Within this file, we want to enter the following lines.

Make sure that you replace YOUR_FOLDER_ID with the ID that you received when you created the folder on Google drive.

#!/bin/bash
python3 /home/pi/speedtest.py
/usr/local/bin/gdrive sync upload  /home/pi/speedtest YOUR_FOLDER_ID

3. Now save the file by pressing CTRL + X then Y and then finally ENTER.

4. Before we set up the crontab for our bash script, we must first give the script execution privileges.

We can achieve this by running the following command within the terminal.

sudo chmod +x /home/pi/speedtest.sh

5. Now with everything done, we can finally move onto setting up the crontab.

Begin editing the crontab by running the following command on your Raspberry Pi. If you are asked what editor you want to use, we recommend you select Nano (Typically number 2).

crontab -e

6. Add the following line at the bottom of the file. This line will tell crontab that it should run our bash script once every hour.

If you want to change the behavior of the crontab, you can look at our Crontab generator to work out your desired values.

0 * * * * /home/pi/speedtest.sh

7. You should now have your speed test monitor up and running with the script updating your speedtest.csv file on an hourly basis.

We hope by the end of this Raspberry Pi internet speed monitor tutorial you should now have your Raspberry Pi automatically running internet speed tests on your connection and uploading that data to Google on an hourly basis.

If you have any thoughts, feedback or anything else, then be sure to head over to the forums.

135 Comments

  1. Avatar for Thea Parayno
    Thea Parayno on

    how can i solve this error?

    pi@raspberrypi:~ $ python3 ~/speedtest.py
    usage: speedtest [-h] [--no-download] [--no-upload] [--bytes] [--share]
                     [--simple] [--csv] [--csv-delimiter CSV_DELIMITER]
                     [--csv-header] [--json] [--list] [--server SERVER]
                     [--exclude EXCLUDE] [--mini MINI] [--source SOURCE]
                     [--timeout TIMEOUT] [--secure] [--no-pre-allocate]
                     [--version]
    speedtest: error: unrecognized arguments: --accept-license --accept-gdpr
    Traceback (most recent call last):
      File "/home/pi/speedtest.py", line 13, in 
        ping = ping.group(1)
    AttributeError: 'NoneType' object has no attribute 'group'
    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Thea,

      That error indicates to me that you are not using the correct speedtest package.

      You need to uninstall your existing one and utilize the one installed through this guide.

      Cheers,
      Emmet

  2. Avatar for Giles Ogram
    Giles Ogram on

    Hi Emmet, thanks for the great set of instructions. I have just followed the guides for this (and Influx/Grafana) and seem to be having an issue with the SpeedTest from Ookla.
    I can get a link of servers from speedtest -L and have tested Speedtest via the website directly.
    However running the script (speedtest.py) or speedtest I get the following error:
    Speedtest by Ookla

    Server: Hey! Broadband LTD – High Wycombe (id = 42694)
    ISP: Internal Systems Limited
    [error] Error: [11] Cannot read: Resource temporarily unavailable

    Any thoughts?

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Giles,

      That is strange, my only suggestion would be to try a different server and see if the issue persists.

      Hopefully someone else may have a better idea of why this would be only occurring on your Raspberry Pi, but at the moment I cant think of any reason.

      Cheers,
      Emmet

    2. Avatar for Giles Ogram
      Giles Ogram on

      Hi Emmet,
      It is something being blocked on a firewall. I moved the Pi back home and it worked fine.
      Graphs being produced.
      Many thanks

  3. Avatar for Patrick
    Patrick on

    Hi
    Thanks for this very great tut!

    Question: Is there a way to select which server it will be use for testing?

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Patrick,

      Yes you definitely can select a specific server to perform the tests against. It should also give you more reliable and consistent results.

      1. To list the servers that are nearest to your location you can run the following command.

      speedtest -L

      This command will produce a list containing the ID, Name, Location, and Country for each server.

          ID  Name                           Location             Country
      ==============================================================================
       18714  Telstra                        Windsor              Australia
       16207  Vocus Communications           Melbourne            Australia
       13057  Swoop Broadband                Melbourne            Australia

      For the next step you will need to make a note of the numerical ID for the server.

      2. Once you have an ID you can include it as part of the call to the speedtest CLI.

      All you need to use is the “-s” followed by the server ID.

      speedtest -s SERVERID

      3. You will also need to modify the following line within the speedtest.py file.

      For example if we wanted to set the server id we would take the following line

      response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

      And modify that into the following. Make sure to replace SERVERID with your ID.

      response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr -s SERVERID', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

      Let me know if you need any further assistance.

      Cheers,
      Emmet

  4. Avatar for Niall
    Niall on

    Hi why do i keep getting this error when trying to write the second python script?

    pi@raspberrypi:~ $ rm ~/speedtest.py
    rm: remove write-protected regular file ‘/home/pi/speedtest.py’?

    Thanks,
    Niall

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Niall,

      This was caused by us using “sudo” to create the first Python script. I’ve modified the tutorial so we no longer do that as it wasn’t required.

      You can remove the file by placing “sudo” in front of the rm command like below.
      sudo rm ~/speedtest.py

      Cheers,
      Emmet

  5. Avatar for Pete Bosch
    Pete Bosch on

    Alright – maybe it’s because I have a short attention span, and maybe it’s because I know enough to get myself into trouble, but not enough to get myself out of it, and maybe it’s because github doesn’t have a commentary feature for easily letting an author know when things have gone sideways, but after trying several docker-based github “solutions” to this problem, and having each of them fail in a different way, I came across this one, and with some minor hiccups (one related to Grafana’s U/I changing, and the other related to the [internetspeed/internet_speed] mixup in the tutorial – easy to fix – I got this working.

    With your “talk to me like a fifth-grader” approach, I understand *why* it works, too. To the point that when it didn’t (see above), I knew where to look, and for what.

    Except for the internet_speed/internetspeed thing, I’d have given this tutorial a five-star rating (though there’s nowhere to enter it) and unlike Amazon, for me a five star is rare. Fix that one little consistency issue, and you’ll have my admiration, loyalty, and return visits. Thank you for the Influx and Grafana lessons, as well as the structural guidance!

  6. Avatar for Thierry
    Thierry on

    This is what I am getting after running speedtest.py:

    Traceback (most recent call last):
      File "./speedtest.py", line 25, in 
        f.write('{},{},{},{},{},{}\r\n'.format(time.strftime('%m/%d/%y'), time.strftime('%H:%M'), ping, jitter, download, upload))
    NameError: name 'f' is not defined
    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Thierry,

      That error typically occurs when you haven’t created the “speedtest” directory within the users directory.

      Make sure that you run the following command before running the script.

      mkdir ~/speedtest

      Cheers,
      Emmet

  7. Avatar for Alex
    Alex on

    Hi Emmet,

    I have been getting an update error when running
    sudo apt-get update
    and it returned this

    Hit:1 http://raspbian.raspberrypi.org/raspbian buster InRelease
    Hit:2 http://archive.raspberrypi.org/debian buster InRelease
    Hit:3 https://repos.influxdata.com/debian buster InRelease
    Hit:4 https://packages.grafana.com/oss/deb stable InRelease
    Err:5 https://ookla.bintray.com/debian generic InRelease
      403  Forbidden [IP: 35.157.24.53 443]
    Reading package lists... Done
    E: Failed to fetch https://ookla.bintray.com/debian/dists/generic/InRelease  403  Forbidden [IP: 35.157.24.53 443]
    E: The repository 'https://ookla.bintray.com/debian generic InRelease' is no longer signed.
    N: Updating from such a repository can't be done securely, and is therefore disabled by default.
    N: See apt-secure(8) manpage for repository creation and user configuration details.

    Any help will be greatly appreciated.

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Alex,

      It looks like Ookla have decided to deprecate their old repository. This makes it a little painful but fixable.

      1. First, we need to remove the current file that references the old Bintray repository.

      /etc/apt/sources.list.d/speedtest.list

      2. Next, perform an update of the package list so that it becomes aware that this repository is no longer available as a source.

      sudo apt update

      3. Now to be able to install the new version from the new repository you will need to remove the existing version of Speedtest.

      sudo apt remove speedtest

      4. Now, please refollow steps 36 of the “Installing the Speedtest CLI” section.

      Cheers,
      Emmet

  8. Avatar for Peter Berntson
    Peter Berntson on

    I can’t get past the testing of speediest. I get the following error

    pi@PKBPi-02:~ $ speedtest
    [2021-07-01 21:52:18.998] [error] Configuration – Couldn’t resolve host name (HostNotFoundException)
    [2021-07-01 21:52:18.999] [error] Configuration – Cannot retrieve configuration document (0)
    [2021-07-01 21:52:18.999] [error] ConfigurationError – Could not retrieve or read configuration (Configuration)
    [2021-07-01 21:52:18.999] [error] ConfigurationError – Could not retrieve or read configuration (Configuration)
    [error] Configuration – Could not retrieve or read configuration (ConfigurationError)

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Peter,

      It appears to me that your Raspberry Pi is for some reason unable to contact the Ookla speedtest servers.

      Please try and verify that you can connect to https://www.speedtest.net/ from your Pi.

      Cheers,
      Emmet

      Cheers,
      Emmet

  9. Avatar for Tim
    Tim on

    Hey Emmet,

    Thanks for all your help. The switch to the new Ookla repository has worked. I really appreciate the swift responses and desire to help out. Keep up the good work.

    Cheers,
    Tim

  10. Avatar for Tim
    Tim on

    Hi Emmet,

    Thanks for your response. I’ve added :80 and still no change. Error message is the same as before.

    I’ve swapped wifi networks and even used my mobile to connect, but same outcome each time. I can see keyserver.ubuntu.com via a web browser, so it looks like its an issue connecting to the service rather than the server??

    Thanks for your continued help.

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Tim,

      This is indeed strange, I tested it on my Pi and am not having any issues.

      I’ll try and look up an alternative way of completing this step that doesn’t require the connection to the Ubuntu keyserver.

      Cheers,
      Emmet

    2. Avatar for Emmet
      Emmet on
      Editor

      Hi Tim,

      Just letting you know I have now updated the tutorial to use the newer repository the Ookla team is using.

      The advantage of this new method in your case is that it is not relying on the Ubuntu keyserver to retrieve the GPG key.

      Let me know if you can now install the Speedtest CLI using this new method.

      Cheers,
      Emmet

  11. Avatar for Sam
    Sam on

    Great, easy to follow tutorial. I am having in ssue with Grafana. The data source is working fine but when i go to add a query i click in “Select Measurement” and i just see “No Options Found” I assume this has something to do with the InfluxDB, but that all seems to be working fine. Any ideas?

    1. Avatar for Sid
      Sid on

      Having the same issue as well. Hopefully they get back to us soon.

    2. Avatar for Craig H
      Craig H on

      Same issue here as well.
      Tried changing ‘localhost’ to ip address, but made no difference.
      Its funny how Grafana says the data source is working but nothing comes up in the query options, like it’s looking in the wrong place

    3. Avatar for Bas
      Bas on

      I am on the same boat as well. Not sure what is the issue.

    4. Avatar for Emmet
      Emmet on
      Editor

      Hi Guys,

      I have tried looking into this but so far have been unable to reproduce any issues with selecting the measurement.

      If you load up InfluxDB’s command line tool, is there data within the database? If you need steps on how to check this, let me know.

      Cheers,
      Emmet

    5. Avatar for Dominik
      Dominik on

      Hello Emmet,

      Having same issue here, any chance you can provide me the steps on how to check, if theres data in the database?

      Thanks!

    6. Avatar for Emmet
      Emmet on
      Editor

      Hi Dominik,

      1. Start by opening up the InfluxDB command line interface.

      influx -username admin -password [password]

      If you didn’t setup authentication when you setup InfluxDB on your Raspberry Pi you can skip providing the username and password.

      2. Once you are have the Influx command line up, we can now tell it we want to interact with our internet speed monitors database.

      USE internetspeed

      You should see a message like below appear after running this command.

      Using database internetspeed

      3. Now that we have the database selected we can run a little statement to select all data from our “internet_speed” measurement.

      The use of the asterisk in this command is telling it to fetch all columns, so this will give us the time, download, host, jitter, ping and upload data for every call that has been made.

      SELECT * FROM internet_speed

      If you Raspberry Pi internet speed monitor has been working correctly you should see some data.

      For example when I set this project back up the other day and ran it a few times I ended up with the following dataset.

      name: internet_speed
      time                download host                jitter ping  upload
      ----                -------- ----                ------ ----  ------
      1625024848304554627 30.82    RaspberryPiMyLifeUp 0.48   30.63 9.16
      1625025091507779243 27.68    RaspberryPiMyLifeUp 0.26   29.06 9.1
      1625025134683585419 28.02    RaspberryPiMyLifeUp 0.5    28.94 9.04
      1625025187087986768 28.28    RaspberryPiMyLifeUp 3.12   35.2  9.16
      1625028445828864388 27.51    RaspberryPiMyLifeUp 4.47   28.7  8.67
      1625028550445376252 29       RaspberryPiMyLifeUp 0.54   17.9  9.19
      1625028916099651402 28.55    RaspberryPiMyLifeUp 0.22   29.12 9.14

      Cheers,
      Emmet

    7. Avatar for RandomCitizen
      RandomCitizen on

      I had the same issue, I figured out that when you are busy with the “add query” section and you click on “measurement”, you are expecting to see “internet_speed” in the drop down menu, I did not, so I just typed it, a little wheel spun for a few seconds and then I clicked on the “internet_speed” and continued and it worked.

    8. Avatar for Dominik
      Dominik on

      Just fixed the issue guys LOL

      Make sure to run the script at least once before trying to add it to Grafana. 🙂

  12. Avatar for Tim
    Tim on

    Great tutorial, but I’m falling at the first hurdle here. Can’t get the GPG keys into the repository:

    pi@raspberrypi:~ $ sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 379CE192D401AB61
    Executing: /tmp/apt-key-gpghome.N6xXUdF5Us/gpg.1.sh –keyserver keyserver.ubuntu.com –recv-keys 379CE192D401AB61
    gpg: keyserver receive failed: Server indicated a failure

    This is a brand new Pi with no other software on it. Any ideas where I’m going wrong?

    Thanks

    1. Avatar for Emmet
      Emmet on
      Editor

      HI Tim,

      This seems like a a strange issue. From the looks of it your Raspberry Pi is failing to connect to the Ubuntu key server.

      It could be a firewall or something else for some reason messing with the connection to the key server, or the key server itself was experiencing issue at the time.

      To get around this we can attempt making the connection by using a more standard port such as port 80 (the default is 11371 when connecting to a keyserver).

      sudo apt-key adv --keyserver keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61

      Let me know if that helps you with the issue you are running into.

      Cheers,
      Emmet

  13. Avatar for John
    John on

    I needed to add --accept-license and --accept-gdpr

    response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')
  14. Avatar for Ricardo Souza
    Ricardo Souza on

    Thanks for the quick reply, Emmet! I thought I had installed the client via brew correctly but attempting to run commands like “speedtest -v” gives me errors. I will try it again and report back. Just a quick question: how do I completely uninstall it using Homebrew, just in case something went wrong in my previous install?
    Thanks again and best regards.

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Ricardo,

      What sort of errors is it giving you? Might help diagnose the issues that you are having.

      Removing the package completely should be as simple as running the command below.

      brew uninstall speedtest --force

      Cheers,
      Emmet

  15. Avatar for Ric Souza
    Ric Souza on

    This is indeed an Awesome guide! Thank you for sharing it.
    I used the original guide and installed it all on my Mac Mini successfully, way back when. I now tried to follow this new version and everything stopped working! 🙁
    Has anyone tried “adapting” this latest guide to make it work on a Mac?
    Thanks in advance!
    Cheers!

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Ric,

      Sorry to hear that you are having issues getting this to run on a mac mini. I don’t currently have a mac I can test this on, but you should be able to get it to work by installing the Ookla Speedtest CLI through Homebrew.

      If you have homebrew installed you should be able to run the following three commands to install the Ookla speedtest CLI.

      brew tap teamookla/speedtest
      brew update
      brew install speedtest --force

      If there is enough interest I can try and get my hands on a Mac device like the mini and write up a proper guide.

      Cheers,
      Emmet

  16. Avatar for s_dal
    s_dal on

    Like everyone else said, this is an incredibly well written and easy to follow tutorial. However I have the following error (i can run speedtest fine from the command line)

    License acceptance recorded. Continuing.

    [error] Cannot open socket: Timeout occurred in connect.
    Traceback (most recent call last):
    File “/home/pi/speedtest.py”, line 15, in
    upload = upload.group(1)
    AttributeError: ‘NoneType’ object has no attribute ‘group’

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi s_dal,

      That error would be occurring if for some reason speedtest isn’t getting a result from Ookla.

      What makes it strange is that you aren’t having any issues when running it manually.

      The Ookla Speedtest client doesn’t give us the ability to increase the timeout. But we could attempt picking a specific server to test speeds off of.

      Try running the following command to list the servers that are located near you.

      speedtest -L

      That should give you a list like we have below.

      Make a note of the ID for the server you want try connecting to.

          ID  Name                           Location             Country
      ==============================================================================
       18712  Telstra                        Hobart               Australia
       22006  TasmaNet Pty Ltd               Hobart               Australia
       12403  Launtel                        Hobart               Australia
      

      Once you have an ID handy. Modify the following line in the Python script.

      response = subprocess.Popen('/usr/bin/speedtest --accept-license', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

      Change that so that it now references the specific server we want to test against.

      Make sure that you replace SERVERID with the ID you retrieved from the previous list.

      response = subprocess.Popen('/usr/bin/speedtest --accept-license -s SERVERID', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')

      Then attempt to rerun the speedtest python script.

      With any luck this will hopefully solve the strange timeout error that you are running into.

      Cheers,
      Emmet

    2. Avatar for s_dal
      s_dal on

      Hi Emmet,

      Thank you so much for the reply. Unfortunately, when I try speedtest -L I get the response
      “speedtest: error: unreognized arguments: -L”

      I removed and reinstalled speedtest but same result.

    3. Avatar for Emmet
      Emmet on
      Editor

      Hi s_dal,

      Can you please try running the following command and let me know what it returns.

      speedtest -V

      Cheers,
      Emmet

    4. Avatar for s_dal
      s_dal on

      Hi Emmet, sorry for the delay in replying! I assume you were after the speedtest version, because it doesn’t recognise -v either.

      pi@raspberrypi:~ $ speedtest -v
      usage: speedtest [-h] [--no-download] [--no-upload] [--single] [--bytes]
                       [--share] [--simple] [--csv] [--csv-delimiter CSV_DELIMITER]
                       [--csv-header] [--json] [--list] [--server SERVER]
                       [--exclude EXCLUDE] [--mini MINI] [--source SOURCE]
                       [--timeout TIMEOUT] [--secure] [--no-pre-allocate]
                       [--version]
      speedtest: error: unrecognized arguments: -v
      pi@raspberrypi:~ $ speedtest --version
      speedtest-cli 2.1.3
      Python 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
    5. Avatar for Emmet
      Emmet on
      Editor

      Hi s_dal,

      It looks like you are using the old version of this guide that relied on the 3rd party speedtest-cli python script.

      We have updated the tutorial to use the official CLI provided from Ookla as the old script was proving unreliable and inaccurate.

      You can try removing the speedtest-cli Python package you can run the following command on your system.

      sudo pip3 uninstall speedtest-cli

      Cheers,
      Emmet

  17. Avatar for Jason Etten
    Jason Etten on

    I am having an issue. The speedtest works on the pi. I am unable to get the script to run.
    I get errors. Any help would be appreciated.

    To accept the message please run speedtest interactively or use the following:
    
        speedtest --accept-license
    Traceback (most recent call last):
      File "/home/pi/speedtest.py", line 12, in 
        ping = ping.group(1)
    AttributeError: 'NoneType' object has no attribute 'group'
    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Jason,

      This looks like the error is being caused by the speedtest CLI tool not having its license accepted.

      As the script doesn’t verify that we have received back the data we wanted it runs into any error when it tries to filter the text.

      We have adjusted the commands used by the Python script so that it automatically passes in “--accept-license“.

      Please try the updated version of the script and let me know if you still run into issues.

      Cheers,
      Emmet

  18. Avatar for Adam Orcutt
    Adam Orcutt on

    Really love all that you do. I’m late to the Raspberry PI Nation but have acquired as quickly as possible many Pi 4’s and Pi Xero’s (1.3 and otherwise) to use as Roon and Squeezebox endpoints, Pi-Holes, etc…. and am delving int this to setup netowork monitoring my father’s newly rolled out Starlink Satellite. I have a multi-wan setup and am wondering how I might integrate the ISP provider information into the InfluxDB dataset?

    Many thanks for all the great work you do!

    1. Avatar for Martin
      Martin on

      Adam can you please advise how you structured the queries to get the panels with the recent/start timestamps and also the averages. I can’t seem to get the results or display them correctly.
      Thanks

    2. Avatar for Ric Souza
      Ric Souza on

      First of all, congrats on the AWESOME dashboard and thanks for sharing it – I’m sure I’m not the only one full of envy upon seeing it!!! LOL
      I’d love to build it and it would be great if you could provide a quick set of instructions on how you did it.
      Thanks in advance

    3. Avatar for Martin
      Martin on

      Hi Ric.
      I built the following for mine: https://snipboard.io/zJ3DMx.jpg
      A bit different to Adam’s but on a similar theme. I can share the settings for the Grafana panels if it will help as I struggled for a while to get them displaying properly.

    4. Avatar for MTR
      MTR on

      WOW – this dashboard in Grafana looks great @Martin!
      Can you provide us with the .json file for this?

    5. Avatar for Ric Souza
      Ric Souza on

      Thanks, Martin! I’m only now getting around to checking out your JSON file. I finally got it all running on my Mac Mini but gave up trying to get the speedtest.sh script scheduled to run every 30 minutes! It ran fine on Terminal but it would either not run at all or give me all sorts of errors when trying to run on schedule – and I tried it with cron and with launchd with no success. So I threw the towel and set it all up again from scratch on a RPi4, since my RPi3 was capping the measurements at 100Mbps (I have a 300Mbps connection). I see where you said I might have to change Grafana database name and hostname but I’m not finding what / where the details of my setup should be. Did you mean my InfluxDB database name (yours seem to be “internet_speed” where as the guide’s is “internetspeed”)? Where would the “host” be? I followed the guide to the letter.
      Thanks again and my apologies for the dumb questions!
      Cheers

    6. Avatar for Theodore
      Theodore on

      Adaaaam, this is awesome! Thank you so much!

  19. Avatar for Jason
    Jason on

    I had the original Speedtest running for a while. I tried to update according to this turorial. I am getting an error when I run the ‘Speedtest’ command to get speedtest running.

    Retrieving speedtest.net configuration...
    Traceback (most recent call last):
      File "/usr/local/bin/speedtest", line 11, in 
        sys.exit(main())
      File "/usr/local/lib/python2.7/dist-packages/speedtest.py", line 1884, in main
        shell()
      File "/usr/local/lib/python2.7/dist-packages/speedtest.py", line 1780, in shell
        secure=args.secure
      File "/usr/local/lib/python2.7/dist-packages/speedtest.py", line 1027, in __init__
        self.get_config()
      File "/usr/local/lib/python2.7/dist-packages/speedtest.py", line 1113, in get_config
        map(int, server_config['ignoreids'].split(','))
    ValueError: invalid literal for int() with base 10: ''

    Any suggstions?

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Jason,

      We have updated the tutorial since the earlier versions to use the official command line tool from Ookla.

      The old tutorial requires you to update the old Python package for it to continue to work. Please check out reply to Chris below.

      Cheers,
      Emmet

  20. Avatar for Chris
    Chris on

    I’ve had this running for about a year as a network monitor in the garden to check wifi performance for a few IP cameras. We have a hedgehoghouse and many hog visitors, its great to watch their goings on.
    Recently the network monitor threw up some errors and is not providing an output for Grafana. I hadn’t updated the OS in a while so I thought some of the updated packages may resolve the issue, unfortunately not. I’d rather fix than have to rework it. Can I ask for some help to figure out what’s going on. Here’s the output when I run: speedtest-cli –simple

    File "/usr/local/bin/speedtest-cli", line 10, in 
        sys.exit(main())
      File "/usr/local/lib/python3.7/dist-packages/speedtest.py", line 1986, in main
        shell()
      File "/usr/local/lib/python3.7/dist-packages/speedtest.py", line 1875, in shell
        secure=args.secure
      File "/usr/local/lib/python3.7/dist-packages/speedtest.py", line 1091, in __init__
        self.get_config()
      File "/usr/local/lib/python3.7/dist-packages/speedtest.py", line 1174, in get_config
        map(int, server_config['ignoreids'].split(','))
    ValueError: invalid literal for int() with base 10: ''

    BTW, a great tutorial, many thanks for taking the time to share such a useful project.

    1. Avatar for Emmet
      Emmet on
      Editor

      Hi Chris,

      I took a quick look into this and it appears that the Speedtest website changed a few things somewhat recently.

      They released a newer version that should fix the error that you are facing. You should be able to update the speedtest-cli python package by running the following command.

      pip install speedtest-cli --upgrade

      Cheers,
      Emmet

Leave a Reply

Your email address will not be published. Required fields are marked *