20221108 Internet Speed Test
Missie:
Een Internet Speed Test applicatie met een CLI tool, Python, InfluxDB en Grafana.
We gaan eerst een CLI tool installeren om de internet snelheid te meten.
Daarna gaan we het tooltje automatiseren d.m.v. een Python script.
Persoonlijk ben ik, vanwege het gekluns met het inspringen, niet zo'n fan van Python maar vanwege de eenvoud
en de reproduceerbaarheid ga ik het toch doen.
De data wordt in een InfluxDB database gestopt om een historie te verkrijgen.
Daarna haalt Grafana de waarden uit de InfluxDB database op, om ze netjes in een plaatje te presenteren.
Stap 1 - Breng het besturingssysteem op de laatste stand.
Open een terminal venster en type de volgende commando’s:
sudo apt update && sudo apt upgrade
Stap 2 - Installeer het CLI tool.
Het CLI tooltje kan geïnstalleerd worden met het volgende commando:
sudo apt install apt-transport-https gnupg1 dirmngr lsb-release
Met dit commando worden gnupg1, apt-transport-https, dirmngr en lsb-release geïnstalleerd.
apt-transport-https is het pakket voor https protocol ondersteuning. Zonder dit pakket geeft apt een fout als het
naar het Ookla pakket wil verbinden.
gnupg1 zogt voor de communicatie tussen je RaspPi en de speedtest.net servers.
dirmngr dient om de toevoegingen van de pakket repository af te handelen.
lsb-release gebruiken we om de release naam van het besturingssysteem te achterhalen.
Met de pakketten die we nodig hebben, kunnen we nu de GPG-sleutel voor Ookla's Speedtest-repository aan de sleutelhanger toevoegen.
We hebben deze "sleutelhanger" nodig om de speedtest-opdrachtregelinterface naar onze Raspberry Pi te kunnen downloaden met het volgende commando:
curl -L https://packagecloud.io/ookla/speedtest-cli/gpgkey | gpg --dearmor | sudo tee /usr/share/keyrings/speedtestcli-archive-keyring.gpg >/dev/null
Vervolgens moeten we de Ookla-repository toevoegen aan onze bronnenlijst.
Zonder de repository toe te voegen, kunnen we de Speedtest CLI niet op onze Raspberry Pi installeren.
Deze repository kan worden toegevoegd met de volgende opdracht.
echo "deb [signed-by=/usr/share/keyrings/speedtestcli-archive-keyring.gpg] https://packagecloud.io/ookla/speedtest-cli/debian/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/speedtest.list
Binnen deze opdracht zul je merken dat we $(lsb_release -cs) gebruiken. Met dit stukje tekst kunnen we de releasenaam voor onze installatie van
RaspPi OS rechtstreeks in de opdracht invoegen.
Omdat we een nieuwe pakketrepository hebben toegevoegd, moeten we onze pakketlijst bijwerken met de volgende opdracht:
sudo apt update
Daarna kunnen we de officiƫle Speedtest CLI van Ookla installeren op onze RaspPi met het volgend commando:
sudo apt install speedtest
Stap 3 - Speedtest voor de eerste keer uitvoeren.
Met het volgende commando kunnen we speedtest uitvoeren:
speedtest
De eerste keer dat je speedtest uitvoert, moet je een aantal licentie vragen met YES beantwoorden.
De output van speedtest ziet er als volgt uit:
De uitstoot van speedtest kun je stoppen met Ctrl + c
Stap 4 - Speedtest automatiseren m.b.v. een Python script.
Eerst maken we een directory aan om het speedtest script in onder te brengen met:
mkdir ~/speedtest
Daarna wisselen we naar deze direcory met:
cd ~/speedtest
In deze directory leggen we een nieuw bestand aan met de naam speedtest.py met het volgende commando:
touch speedtest.py
Met het ls commando kun je controleren of het bestand is aangemaakt.
Met het volgende command gaan we dit bestand editeren:
nano speedtest.py
De nano editor opent en we gaan de regels 1 t/m 4 toevoegen:
import os
import re
import subprocess
import time
Uitleg:
import os Hiermee word de operating system library ingevoegd.
import re Hiermee kunnen reguliere commando’s worden uitgevoerd.
import subprocess Noodzakelijk om een ander Python script te kunnen oproepen.
import time Hiermee wordt het mogelijk datum en tijd van de actie toe te voegen.
Dan voegen we de volgende regel, 5, in het Python script toe:
response = subprocess.Popen('/usr/bin/speedtest --accept-license --accept-gdpr', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')
In deze regel code gebruiken we de subprocesbibliotheek om een oproep naar de Speedtest CLI te starten en deze te vertellen dat alles van speedtest naar
de standaard output stdout moet worden gestuurd.
Door stdout.read().decode('utf-8') aan het einde van de oproep te gebruiken, slaan we de response van de Speedtest CLI op in onze responsvariabele en decoderen het tot een bruikbare Python-string.
Dan voegen we de volgende regels, 6 t/m 9 aann het Python script toe:
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('Latency:.*?jitter:\s+(.*?)ms', response, re.MULTILINE)
Deze regels zijn vrij simpel en doen eigenlijk allemaal hetzelfde: ze gebruiken de re-bibliotheek om een stukje van de response te filteren.
Dan voegen we de volgende regels, 10 t/m 13 aann het Python script toe:
ping = ping.group(1)
download = download.group(1)
upload = upload.group(1)
jitter = jitter.group(1)
Om de juiste .group() te verkrijgen is dit belangrijk.
Op deze manier wordt alles zo gerangschikt dat het naar een .csv bestand kan worden geschreven.
Dat doen we met de regels 14 t/m 19:
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
Rechttoe rechtaan code zou ik zeggen.
Het try statement wordt het bestand speedtest.csv geopend met het argument a+.
Met a+ zeggen we tevens dat het bestand aangemaakt moet worden als het niet bestaat.
Als het bestaat wordt informatie toegevoegd. Regel 20.
f.write('{},{},{},{},{},{}\r\n'.format(time.strftime('%m/%d/%y'), time.strftime('%H:%M'), ping, jitter, download, upload))
Ten slotte printen we al onze gegevens gescheiden door komma’s.
We gebruiken de functie strftime() van de tijdbibliotheek om de huidige datum en de huidige tijd in onze opgemaakte tekenreeks in te voegen.
Daarna voegen we onze ping, download en upload in.
Hieronder is een voorbeeld opgenomen van hoe de uitvoergegevens eruit zullen zien bij de uitvoering van onze code.
Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps) 04/29/21,06:28,18.32,1.21,23.30,7.78
Om het intypen van de code niet al te ingewikkeld te maken, hier de code als download: Let op: in Python zijn 4 spates geen tab teken!!.
Als deze regels zijn toegevoegd kun je de editor afsluiten met de volgende toetsenvolgorde:
Ctrl+X, dan Y en daarna ENTER.
Stap 5 - Resultaat?
Met het volgende commando kun je de uitvoering van het script starten. De eerste keer zal dat ietsje langer duren dan je misschien gewend bent.
python3 speedtest.py
Als de uitvoering van het script klaar is, heb je een nieuw bestand in je directory: speedtest.csv.
Bekijk de inhoud van het bestand met het commando:
nano speedtest.csv
In het bestand zou je het volgende moeten zien:
Date,Time,Ping (ms),Jitter (ms),Download (Mbps),Upload (Mbps)
04/29/21,06:28,18.32,1.21,23.30,7.78
Stap 6 - De data in InfluxDB opslaan.
Ga naar je home directory met de opdracht:
cd ~
Dan log je in InfluxDB in met:
influx -username admin -password <password>
Maak een database aan met de naam InternetSpeed met het volgende commando:
CREATE DATABASE InternetSpeed
Maak een gebruiker aan met de naam SpeedTester en een password met het volgende commando:
CREATE USER "SpeedTester" WITH PASSWORD '<password>'
Geef deze gebruiker alle rechten op de database met:
GRANT ALL ON "InternetSpeed" to "SpeedTester"
Verlaat de InfluxDB command prompt met:
quit
Vervolgens moeten we nog de Python bibliotheek voor InfluxDB installeren met:
sudo apt install python3-influxdb
In het Python script gaan we enkele zaken toevoegen, zonder uitleg. Deze spreekt voor zich.
import re
import subprocess
from influxdb import InfluxDBClient
De os en de time libraries kunnen weg.
Het middengedeelte (de regels t/m 14) blijven gelijk.
In plaats van naar een .csv bestand moeten we nu de data naar InfluxDB schrijven.
We gaan dat doen met een JSON string:
SpeedData = [
{
"measurement" : "InternetSpeed",
"tags" : {
"host": "PiDomo"
},
"fields" : {
"download": float(download),
"upload": float(upload),
"ping": float(ping),
"jitter": float(jitter)
}
}
]
De tag host voegen we toe om eventuele latere RaspPi’s te kunnen toevoegen en onderswcheid te kunnen maken.
Verder moeten we voor de getallen de float() funtie toevoegen, anders ziet Grafana dit als strings.
Dan moet het geheel naar InfluxDB met:
client = InfluxDBClient('localhost', 8086, 'user', 'password', 'database')
Daarna schrijven we het naar de database met:
client.write_points(SpeedData)
De code kun je hier beneden downloaden.
Denk er aan de gegevens voor de database, de gebruiker en het wachtwoord aan te passen.
Start het script enkele malen met:
python3 speedtestInfluxDB.py
Kijk of er data in de InfluxDB database arriveert.
Als dat zo is kunnen we verder met de volgende stap.
Stap 7 - het Python script automatiseren.
Het automatiseren van het script gaat eenvoudig met het crontab programma.
Om de editor van crontab te starten gebruik je het volgende commando:
crontab -e
Hier voeg je de volgende regel in:
*/10 * * * * python3 /home/pi/speedtest/speedtestInfluxDB.py
Deze regel voert het programma elke 10 minuten uit.
Simpel en doeltreffend. Sluit de editor af met Ctrl+X, dan Y en daarna ENTER.
Let op: Als je crontab de eerste keer gebruikt is er waarschijnlijk nog geen configuratie bestand.
Je moet dan je gewenste editor kiezen. nano = 1.
Stap 8 - De data met Grafana zichtbaar maken.
Ga naar de Grafana webpagina met het IP adres en poort 3000 in je browser.
In Grafana ga naar het tandwiel bovenin en dan naar het tanwiel links en dan naar Data Sources.
Ga naar Add data source en kies voor InfluxDB met Select.
Daar moeten we een en ander invullen.
Bij URL zet je http://localhost:8086
Bij Database zet je de naam van de database InternetSpeed.
Bij User zet je de naam van de gebruiker SpeedTester.
Bij Password vul je het wachtwoord in
Daarna klik je op Save and test.
Grafana zal OK melden als dat zo is.
Als dat niet zo is, moet er onderzocht worden wat er mis is gegaan.
Let op: Als de database geen data bevat, kun je NIET verbinden!! Logisch toch.
Dan gaan we het dashboard voor de applicatie maken.
De opzet van de Grafana interface verandert nog wel eens, daarom wordt hier geen exacte locatie voor het klikken gegeven.
In het hoofdscherm links staan 4 hokjes in een icoon, klik daarop en daarna op + New dashboard.
Dan Add new panel en daar kun je veel invullen.
We gaan eerst met de Query inspector aan de slag.
Voor het opzetten van een dashboard zijn er veel mogelijkheden en opvattingen.
Hier beneden een mogelijk eindresultaat.
Een vrij complete beginnercursus vind je op Youtube.
Een boek over Grafana 7.0 vind je hier