3

Powershell – Use Speedtest CLI to Monitor Broadband speeds – Part 1

After having some speed issues I wanted to create a script to document these into an easy to access table that I could see what was happening. So rather than reinventing the wheel, Ookla offer a Python application that will display your internet speeds from the commandline… if thats your wish; and in my case, it was!

My main wants in this were:

  • Create a PowerShell script to get the information I wanted
  • Output the results to a CSV
  • Use scheduled Tasks to run the script hourly
  • Upload the results to a local web server and display in a HTML table

So to do this I first of all found a script online and set about butchering it… that can be found here!

While this script was complete it didnt suit exactly what I wanted to do. Especially when using the JSON files.

First as with the majority of my scipts I set my working directory so that I’m not looking all over the place for any source files required.

Push-Location (Split-Path -path $MyInvocation.MyCommand.Definition -Parent)

The next notable part is lifted from the script above for the installation of the CLI module:

# Check for Speedtest CLI install, if not exist, download and install.
# Replace the Download URL to where you've uploaded the ZIP file yourself. We will only download this file once. 
# Latest version can be found at: https://www.speedtest.net/nl/apps/cli
Write-Host "Checking for Speedtest CLI..." -ForegroundColor Black -BackgroundColor Green
$DownloadURL = "https://bintray.com/ookla/download/download_file?file_path=ookla-speedtest-1.0.0-win64.zip"
$DownloadLocation = "$($Env:ProgramData)\SpeedtestCLI"
try {
    $TestDownloadLocation = Test-Path $DownloadLocation
    if (!$TestDownloadLocation) {
        Write-Host "Does not Exist, retreiving..." -ForegroundColor Black -BackgroundColor Yellow
        new-item $DownloadLocation -ItemType Directory -force
        Invoke-WebRequest -Uri $DownloadURL -OutFile "$($DownloadLocation)\speedtest.zip"
        Expand-Archive "$($DownloadLocation)\speedtest.zip" -DestinationPath $DownloadLocation -Force
    } 
}
catch {  
    write-host "The download and extraction of SpeedtestCLI failed. Error: $($_.Exception.Message)"  -ForegroundColor Black -BackgroundColor Red
    exit 1
}

We want to get the information from the command to append into a CSV in the format that we want:

# Get Speedtest Data Append to CSV
Write-Host "Running Speedtest..." -ForegroundColor Black -BackgroundColor Green
$SpeedtestResults = & "$($DownloadLocation)\speedtest.exe" --format=csv
$SpeedtestResults >> c:\Speedtests\SpeedTestsNonFormatted.csv

This displays the speeds in bytes, I wanted this to be closer to MB, as my lowly broadband connection hasn’t gotten to the GB levels yet, and I’m not willing to pay for it!
So I create a PSObject to be read the last line in from this CSV and format the output to the final CSV. I have also dropped some columns from the CSV as I feel they are not needed.

Write-Host "Amending Formatting..." -ForegroundColor Black -BackgroundColor Green
# Format the bytes to MB
$csv = Import-Csv c:\Speedtests\SpeedTestsNonFormatted.csv | Select-Object -Last 1 | ForEach-Object {
    [PSCustomObject]@{
        'Date and Time'     = $date
        'Server Name'       = $_.'server name'
        'Server ID'         = $_.'server ID'
        'Latency'           = $_.latency
        'Jitter'            = $_.jitter
        'Packet Loss'       = $_.'packet loss'
        'Download'          = [math]::round($_.download/1MB,2)*10
        'Upload'            = [math]::round($_.upload/1MB,2)*10
        'Download Bytes'    = [math]::round($_.'download bytes'/1MB,2)*10
        'Upload Bytes'      = [math]::round($_.'upload bytes'/1MB,2)*10

    }
} | Export-Csv c:\SpeedTests\Speedtest.csv -Append -NoClobber -NoTypeInformation

And thats it, we have our CSV to do what we will with! I will include what I done with this in another post.

The complete script can be found below:

# SpeedTest Script to record Internet speeds on an hourly basis via a scheduled task
# and record to a CSV file, that can be uploaded to a web server and displayed into 
# a HTML Table. 

# Loosly adapted from: https://www.cyberdrain.com/monitoring-with-powershell-monitoring-internet-speeds/

# Set Working Dir
Push-Location (Split-Path -path $MyInvocation.MyCommand.Definition -Parent)

$date = Get-Date -Format dd-MM-yyyy_HH:mm 

# Check for Speedtest CLI install, if not exist, download and install.
# Replace the Download URL to where you've uploaded the ZIP file yourself. We will only download this file once. 
# Latest version can be found at: https://www.speedtest.net/nl/apps/cli
Write-Host "Checking for Speedtest CLI..." -ForegroundColor Black -BackgroundColor Green
$DownloadURL = "https://bintray.com/ookla/download/download_file?file_path=ookla-speedtest-1.0.0-win64.zip"
$DownloadLocation = "$($Env:ProgramData)\SpeedtestCLI"
try {
    $TestDownloadLocation = Test-Path $DownloadLocation
    if (!$TestDownloadLocation) {
        Write-Host "Does not Exist, retreiving..." -ForegroundColor Black -BackgroundColor Yellow
        new-item $DownloadLocation -ItemType Directory -force
        Invoke-WebRequest -Uri $DownloadURL -OutFile "$($DownloadLocation)\speedtest.zip"
        Expand-Archive "$($DownloadLocation)\speedtest.zip" -DestinationPath $DownloadLocation -Force
    } 
}
catch {  
    write-host "The download and extraction of SpeedtestCLI failed. Error: $($_.Exception.Message)"  -ForegroundColor Black -BackgroundColor Red
    exit 1
}
# Check for Non Formatted CSV, if its not there create it
Write-Host "Checking if CSV Exists, continuing..." -ForegroundColor Black -BackgroundColor Yellow
If(Test-Path c:\Speedtests\SpeedTestsNonFormatted.csv){
    Write-Host "CSV Exists, continuing..." -ForegroundColor Black -BackgroundColor Green
    }
else{
    Write-Host "Creating CSV File and Headers" -ForegroundColor Black -BackgroundColor Yellow
    '"Server name","Server id","Latency","Jitter","Packet loss","Download","Upload","Download bytes","Upload bytes"' > c:\Speedtests\SpeedTestsNonFormatted.csv}

# Get Speedtest Data Append to CSV
Write-Host "Running Speedtest..." -ForegroundColor Black -BackgroundColor Green
$SpeedtestResults = & "$($DownloadLocation)\speedtest.exe" --accept-gdpr --accept-license --format=csv
$SpeedtestResults >> c:\Speedtests\SpeedTestsNonFormatted.csv

Write-Host "Amending Formatting..." -ForegroundColor Black -BackgroundColor Green
# Format the bytes to MB
$csv = Import-Csv c:\Speedtests\SpeedTestsNonFormatted.csv | Select-Object -Last 1 | ForEach-Object {
    [PSCustomObject]@{
        'Date and Time'     = $date
        'Server Name'       = $_.'server name'
        'Server ID'         = $_.'server ID'
        'Latency'           = $_.latency
        'Jitter'            = $_.jitter
        'Packet Loss'       = $_.'packet loss'
        'Download'          = [math]::round($_.download/1MB,2)*10
        'Upload'            = [math]::round($_.upload/1MB,2)*10
        'Download Bytes'    = [math]::round($_.'download bytes'/1MB,2)*10
        'Upload Bytes'      = [math]::round($_.'upload bytes'/1MB,2)*10

    }
} | Export-Csv c:\SpeedTests\Speedtest.csv -Append -NoClobber -NoTypeInformation


Niall

3 Comments

  1. Hi,
    When I run your code, Speedtest.csv only has the date and server data. The rest is blank or 0. SpeedTestsNonFormatted.csv has the ‘speedtest’ data though. I’m new with Powershell but do you know why this is happening?
    Thanks!

    • Hi Dan,

      Let me check the code, I’ve had a few issues with the formatting on the site let me check it and get back to you!

    • Dan I have updated the code to include –accept-gdpr –accept-license, hopefully this should solve your issue 🙂

Leave a Reply

Your email address will not be published.