{"id":1130,"date":"2021-02-18T15:45:35","date_gmt":"2021-02-18T15:45:35","guid":{"rendered":"http:\/\/ihni.uk\/?p=1130"},"modified":"2021-02-18T15:45:35","modified_gmt":"2021-02-18T15:45:35","slug":"powershell-use-speedtest-cli-to-monitor-broadband-speeds","status":"publish","type":"post","link":"https:\/\/ihni.uk\/?p=1130","title":{"rendered":"Powershell &#8211; Use Speedtest CLI to Monitor Broadband speeds &#8211; Part 1"},"content":{"rendered":"<p>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, <a href=\"https:\/\/www.speedtest.net\/apps\/cli\">Ookla<\/a> offer a Python application that will display your internet speeds from the commandline&#8230; if thats your wish; and in my case, it was!<\/p>\n<p>My main wants in this were:<\/p>\n<ul>\n<li>Create a PowerShell script to get the information I wanted<\/li>\n<li>Output the results to a CSV<\/li>\n<li>Use scheduled Tasks to run the script hourly<\/li>\n<li>Upload the results to a local web server and display in a HTML table<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<p>So to do this I first of all found a script online and set about butchering it&#8230; that can be found <a href=\"https:\/\/www.cyberdrain.com\/monitoring-with-powershell-monitoring-internet-speeds\/\">here<\/a>!<\/p>\n<p>While this script was complete it didnt suit exactly what I wanted to do. Especially when using the JSON files.<\/p>\n<p>First as with the majority of my scipts I set my working directory so that I&#8217;m not looking all over the place for any source files required.<\/p>\n<p>[powershell]<br \/>\nPush-Location\u00a0(Split-Path\u00a0-path\u00a0$MyInvocation.MyCommand.Definition\u00a0-Parent)<br \/>\n[\/powershell]<\/p>\n<p>The next notable part is lifted from the script above for the installation of the CLI module:<\/p>\n<p>[powershell]<br \/>\n# Check for Speedtest CLI install, if not exist, download and install.<br \/>\n# Replace the Download URL to where you&#8217;ve uploaded the ZIP file yourself. We will only download this file once.<br \/>\n# Latest version can be found at: https:\/\/www.speedtest.net\/nl\/apps\/cli<br \/>\nWrite-Host &quot;Checking for Speedtest CLI&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n$DownloadURL = &quot;https:\/\/bintray.com\/ookla\/download\/download_file?file_path=ookla-speedtest-1.0.0-win64.zip&quot;<br \/>\n$DownloadLocation = &quot;$($Env:ProgramData)\\SpeedtestCLI&quot;<br \/>\ntry {<br \/>\n    $TestDownloadLocation = Test-Path $DownloadLocation<br \/>\n    if (!$TestDownloadLocation) {<br \/>\n        Write-Host &quot;Does not Exist, retreiving&#8230;&quot; -ForegroundColor Black -BackgroundColor Yellow<br \/>\n        new-item $DownloadLocation -ItemType Directory -force<br \/>\n        Invoke-WebRequest -Uri $DownloadURL -OutFile &quot;$($DownloadLocation)\\speedtest.zip&quot;<br \/>\n        Expand-Archive &quot;$($DownloadLocation)\\speedtest.zip&quot; -DestinationPath $DownloadLocation -Force<br \/>\n    }<br \/>\n}<br \/>\ncatch {<br \/>\n    write-host &quot;The download and extraction of SpeedtestCLI failed. Error: $($_.Exception.Message)&quot;  -ForegroundColor Black -BackgroundColor Red<br \/>\n    exit 1<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<p>We want to get the information from the command to append into a CSV in the format that we want:<\/p>\n<p>[powershell]<br \/>\n# Get Speedtest Data Append to CSV<br \/>\nWrite-Host &quot;Running Speedtest&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n$SpeedtestResults = &amp; &quot;$($DownloadLocation)\\speedtest.exe&quot; &#8211;format=csv<br \/>\n$SpeedtestResults &gt;&gt; c:\\Speedtests\\SpeedTestsNonFormatted.csv<br \/>\n[\/powershell]<\/p>\n<p>This displays the speeds in bytes, I wanted this to be closer to MB, as my lowly broadband connection hasn&#8217;t gotten to the GB levels yet, and I&#8217;m not willing to pay for it!<br \/>\nSo 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.<\/p>\n<p>[powershell]<br \/>\nWrite-Host &quot;Amending Formatting&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n# Format the bytes to MB<br \/>\n$csv = Import-Csv c:\\Speedtests\\SpeedTestsNonFormatted.csv | Select-Object -Last 1 | ForEach-Object {<br \/>\n    [PSCustomObject]@{<br \/>\n        &#8216;Date and Time&#8217;     = $date<br \/>\n        &#8216;Server Name&#8217;       = $_.&#8217;server name&#8217;<br \/>\n        &#8216;Server ID&#8217;         = $_.&#8217;server ID&#8217;<br \/>\n        &#8216;Latency&#8217;           = $_.latency<br \/>\n        &#8216;Jitter&#8217;            = $_.jitter<br \/>\n        &#8216;Packet Loss&#8217;       = $_.&#8217;packet loss&#8217;<br \/>\n        &#8216;Download&#8217;          = [math]::round($_.download\/1MB,2)*10<br \/>\n        &#8216;Upload&#8217;            = [math]::round($_.upload\/1MB,2)*10<br \/>\n        &#8216;Download Bytes&#8217;    = [math]::round($_.&#8217;download bytes&#8217;\/1MB,2)*10<br \/>\n        &#8216;Upload Bytes&#8217;      = [math]::round($_.&#8217;upload bytes&#8217;\/1MB,2)*10<\/p>\n<p>    }<br \/>\n} | Export-Csv c:\\SpeedTests\\Speedtest.csv -Append -NoClobber -NoTypeInformation<br \/>\n[\/powershell]<\/p>\n<p>And thats it, we have our CSV to do what we will with! I will include what I done with this in another post.<\/p>\n<p>The complete script can be found below:<\/p>\n<p>[powershell]<\/p>\n<p># SpeedTest Script to record Internet speeds on an hourly basis via a scheduled task<br \/>\n# and record to a CSV file, that can be uploaded to a web server and displayed into<br \/>\n# a HTML Table. <\/p>\n<p># Loosly adapted from: https:\/\/www.cyberdrain.com\/monitoring-with-powershell-monitoring-internet-speeds\/<\/p>\n<p># Set Working Dir<br \/>\nPush-Location\u00a0(Split-Path\u00a0-path\u00a0$MyInvocation.MyCommand.Definition\u00a0-Parent)<\/p>\n<p>$date = Get-Date -Format dd-MM-yyyy_HH:mm <\/p>\n<p># Check for Speedtest CLI install, if not exist, download and install.<br \/>\n# Replace the Download URL to where you&#8217;ve uploaded the ZIP file yourself. We will only download this file once.<br \/>\n# Latest version can be found at: https:\/\/www.speedtest.net\/nl\/apps\/cli<br \/>\nWrite-Host &quot;Checking for Speedtest CLI&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n$DownloadURL = &quot;https:\/\/bintray.com\/ookla\/download\/download_file?file_path=ookla-speedtest-1.0.0-win64.zip&quot;<br \/>\n$DownloadLocation = &quot;$($Env:ProgramData)\\SpeedtestCLI&quot;<br \/>\ntry {<br \/>\n    $TestDownloadLocation = Test-Path $DownloadLocation<br \/>\n    if (!$TestDownloadLocation) {<br \/>\n        Write-Host &quot;Does not Exist, retreiving&#8230;&quot; -ForegroundColor Black -BackgroundColor Yellow<br \/>\n        new-item $DownloadLocation -ItemType Directory -force<br \/>\n        Invoke-WebRequest -Uri $DownloadURL -OutFile &quot;$($DownloadLocation)\\speedtest.zip&quot;<br \/>\n        Expand-Archive &quot;$($DownloadLocation)\\speedtest.zip&quot; -DestinationPath $DownloadLocation -Force<br \/>\n    }<br \/>\n}<br \/>\ncatch {<br \/>\n    write-host &quot;The download and extraction of SpeedtestCLI failed. Error: $($_.Exception.Message)&quot;  -ForegroundColor Black -BackgroundColor Red<br \/>\n    exit 1<br \/>\n}<br \/>\n# Check for Non Formatted CSV, if its not there create it<br \/>\nWrite-Host &quot;Checking if CSV Exists, continuing&#8230;&quot; -ForegroundColor Black -BackgroundColor Yellow<br \/>\nIf(Test-Path c:\\Speedtests\\SpeedTestsNonFormatted.csv){<br \/>\n    Write-Host &quot;CSV Exists, continuing&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n    }<br \/>\nelse{<br \/>\n    Write-Host &quot;Creating CSV File and Headers&quot; -ForegroundColor Black -BackgroundColor Yellow<br \/>\n    &#8216;&quot;Server name&quot;,&quot;Server id&quot;,&quot;Latency&quot;,&quot;Jitter&quot;,&quot;Packet loss&quot;,&quot;Download&quot;,&quot;Upload&quot;,&quot;Download bytes&quot;,&quot;Upload bytes&quot;&#8217; &gt; c:\\Speedtests\\SpeedTestsNonFormatted.csv}<\/p>\n<p># Get Speedtest Data Append to CSV<br \/>\nWrite-Host &quot;Running Speedtest&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n$SpeedtestResults = &amp; &quot;$($DownloadLocation)\\speedtest.exe&quot; &#8211;accept-gdpr &#8211;accept-license &#8211;format=csv<br \/>\n$SpeedtestResults &gt;&gt; c:\\Speedtests\\SpeedTestsNonFormatted.csv<\/p>\n<p>Write-Host &quot;Amending Formatting&#8230;&quot; -ForegroundColor Black -BackgroundColor Green<br \/>\n# Format the bytes to MB<br \/>\n$csv = Import-Csv c:\\Speedtests\\SpeedTestsNonFormatted.csv | Select-Object -Last 1 | ForEach-Object {<br \/>\n    [PSCustomObject]@{<br \/>\n        &#8216;Date and Time&#8217;     = $date<br \/>\n        &#8216;Server Name&#8217;       = $_.&#8217;server name&#8217;<br \/>\n        &#8216;Server ID&#8217;         = $_.&#8217;server ID&#8217;<br \/>\n        &#8216;Latency&#8217;           = $_.latency<br \/>\n        &#8216;Jitter&#8217;            = $_.jitter<br \/>\n        &#8216;Packet Loss&#8217;       = $_.&#8217;packet loss&#8217;<br \/>\n        &#8216;Download&#8217;          = [math]::round($_.download\/1MB,2)*10<br \/>\n        &#8216;Upload&#8217;            = [math]::round($_.upload\/1MB,2)*10<br \/>\n        &#8216;Download Bytes&#8217;    = [math]::round($_.&#8217;download bytes&#8217;\/1MB,2)*10<br \/>\n        &#8216;Upload Bytes&#8217;      = [math]::round($_.&#8217;upload bytes&#8217;\/1MB,2)*10<\/p>\n<p>    }<br \/>\n} | Export-Csv c:\\SpeedTests\\Speedtest.csv -Append -NoClobber -NoTypeInformation<\/p>\n<p>[\/powershell]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After having some speed issues I wanted to create a script to document these into&hellip;<\/p>\n","protected":false},"author":1,"featured_media":988,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[19,11],"tags":[26,45,61,64,77],"class_list":["post-1130","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","category-scripts","tag-csv","tag-html","tag-ookla","tag-powershell","tag-speedtest"],"jetpack_featured_media_url":"https:\/\/ihni.uk\/wp-content\/uploads\/2020\/02\/Powershell.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/posts\/1130","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ihni.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1130"}],"version-history":[{"count":0,"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/posts\/1130\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ihni.uk\/index.php?rest_route=\/wp\/v2\/media\/988"}],"wp:attachment":[{"href":"https:\/\/ihni.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1130"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ihni.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1130"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ihni.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}