SpeedTester.psm1
#Requires -Version 3 function Start-SpeedTest { <# .SYNOPSIS Report your internet Download and Upload speed. .DESCRIPTION SpeedTester leverages speedtest.net hosting servers. SpeedTester will identify the closest hosting servers to you and pick the one with the lowest latency to perform a test download and upload. It will then report the average Download and Upload in Mbps. Start-SpeedTest does not accept any parameters at this stage. .EXAMPLE Start-SpeedTest .INPUTS None .NOTES Author: Mark Ukotic Website: http://blog.ukotic.net Twitter: @originaluko GitHub: https://github.com/originaluko/ .LINKS #> [CmdletBinding()] Param( ) # Server distance helper function function Get-ServerInfo { param( [Parameter(Mandatory=$true)] $servers ) foreach($server in $servers) { $radius = 6371 [float]$dlat = ([float]$orilat - [float]$server.lat) * 3.14 / 180 [float]$dlon = ([float]$orilon - [float]$server.lon) * 3.14 / 180 [float]$a = [math]::Sin([float]$dlat/2) * [math]::Sin([float]$dlat/2) + [math]::Cos([float]$orilat * 3.14 / 180 ) * [math]::Cos([float]$server.lat * 3.14 / 180 ) * [math]::Sin([float]$dlon/2) * [math]::Sin([float]$dlon/2) [float]$c = 2 * [math]::Atan2([math]::Sqrt([float]$a ), [math]::Sqrt(1 - [float]$a)) [float]$d = [float]$radius * [float]$c New-Object PSObject -Property @{ Distance = $d Country = $server.country Sponsor = $server.sponsor Url = $server.url Host = $server.host } } } # Avg Ping response helper function function Get-AvgPing { param( [Parameter(Mandatory=$true)] $servers ) foreach ($server in $servers) { $test = (Test-Connection -ComputerName $server -Count 4 | measure-Object -Property ResponseTime -Average).average $response = ($test -as [decimal] ) New-Object PSObject -Property @{ 'Destination' = $server 'Avg' = $response } } } # Download Test helper function function Get-DataWCAsync{ param( [Parameter(Mandatory=$true)] $Url, [switch]$IncludeStats ) $wc = New-Object Net.WebClient $wc.UseDefaultCredentials = $false $wc.Headers.Add("Content-Type","application/x-www-form-urlencoded") $wc.Headers.Add("Accept: text/html, application/xhtml+xml, */*") $wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)") $wc.Headers.Add("Cache-Control", "no-cache") $wc.Headers.Add("Referer", "http://www.speedtest.net") $start = Get-Date $null = Register-ObjectEvent -InputObject $wc -EventName DownloadProgressChanged -MessageData @{start=$start;includeStats=$includestats} -SourceIdentifier WebClient.DownloadProgressChanged -Action { filter Get-FileSize { "{0:N2} {1}" -f $( if ($_ -lt 1kb) { $_, 'Bytes' } elseif ($_ -lt 1mb) { ($_/1kb), 'KB' } elseif ($_ -lt 1gb) { ($_/1mb), 'MB' } elseif ($_ -lt 1tb) { ($_/1gb), 'GB' } elseif ($_ -lt 1pb) { ($_/1tb), 'TB' } else { ($_/1pb), 'PB' } ) } $time = ((Get-Date) - $event.MessageData.start) $averagespeed = ($eventargs.BytesReceived * 8 / 1MB) / $time.TotalSeconds $elapsed = $Time.ToString('hh\:mm\:ss') $remainingseconds = ($eventargs.TotalBytesToReceive - $eventargs.BytesReceived) * 8 / 1MB / $averagespeed $receivedsize = $eventargs.BytesReceived | Get-FileSize $totalSize = $eventargs.TotalBytesToReceive | Get-FileSize Write-Progress -Activity (" $url {0:N2} Mbps" -f $averagespeed) -Status ("{0} of {1} ({2}% in {3})" -f $receivedSize,$totalsize,$eventargs.ProgressPercentage,$elapsed) -SecondsRemaining $remainingseconds -PercentComplete $eventargs.ProgressPercentage if ($eventargs.ProgressPercentage -eq 100){ Write-Progress -Activity (" $url {0:N2} Mbps" -f $averagespeed) -Status 'Done' -Completed if ($event.MessageData.includeStats.IsPresent){ $global:down = [Math]::Round($averageSpeed, 2) } } } $null = Register-ObjectEvent -InputObject $wc -EventName DownloadDataCompleted -SourceIdentifier WebClient.DownloadDataCompleted -Action { Unregister-Event -SourceIdentifier WebClient.DownloadProgressChanged Unregister-Event -SourceIdentifier WebClient.DownloadDataCompleted } try { $wc.DownloadDataAsync($url) } catch [System.Net.WebException] { Write-Warning "Download of $url failed" } finally { while ($wc.IsBusy) {} $wc.Dispose() } } # Upload Test helper function function Push-DataWCAsync{ param( [Parameter(Mandatory=$true)] $url, $byteArray, [switch]$includeStats ) $wc = New-Object Net.WebClient $wc.UseDefaultCredentials = $false $wc.Headers.Add("Content-Type","application/x-www-form-urlencoded") $wc.Headers.Add("Accept: text/html, application/xhtml+xml, */*") $wc.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)") $wc.Headers.Add("Cache-Control", "no-cache") $wc.Headers.Add("Referer", "http://www.speedtest.net") $start = Get-Date $null = Register-ObjectEvent -InputObject $wc -EventName UploadProgressChanged -MessageData @{start=$start;includeStats=$includeStats} -SourceIdentifier WebClient.UploadProgressChanged -Action { filter Get-FileSize { "{0:N2} {1}" -f $( if ($_ -lt 1kb) { $_, 'Bytes' } elseif ($_ -lt 1mb) { ($_/1kb), 'KB' } elseif ($_ -lt 1gb) { ($_/1mb), 'MB' } elseif ($_ -lt 1tb) { ($_/1gb), 'GB' } elseif ($_ -lt 1pb) { ($_/1tb), 'TB' } else { ($_/1pb), 'PB' } ) } $Time = ((Get-Date) - $event.MessageData.start) $averageSpeed = ($eventargs.BytesSent * 8 / 1MB) / $Time.TotalSeconds $elapsed = $Time.ToString('hh\:mm\:ss') $remainingSeconds = ($eventargs.TotalBytesToSend - $eventargs.BytesSent) * 8 / 1MB / $averageSpeed $receivedSize = $eventargs.BytesSent | Get-FileSize $totalSize = $eventargs.TotalBytesToSend | Get-FileSize $percent = $eventargs.BytesSent / $eventargs.TotalBytesToSend * 100 $percent = [Math]::Round($percent) Write-Progress -Activity (" $url {0:N2} Mbps" -f $averageSpeed) -Status ("{0} of {1} ({2}% in {3})" -f $receivedSize,$totalSize,$percent,$elapsed) -SecondsRemaining $remainingSeconds -PercentComplete $percent if ($eventargs.ProgressPercentage -eq 100){ Write-Progress -Activity (" $url {0:N2} Mbps" -f $averageSpeed) -Status 'Done' -Completed if ($event.MessageData.includeStats.IsPresent){ $global:upload = [Math]::Round($averageSpeed, 2) } } } # $null = Register-ObjectEvent -InputObject $wc -EventName UploadDataCompleted -SourceIdentifier WebClient.UploadDataCompleted -Action { # Unregister-Event -SourceIdentifier WebClient.UploadProgressChanged -Force # Unregister-Event -SourceIdentifier WebClient.UploadDataCompleted -Force # } try { $wc.UploadDataAsync($url,'POST',$byteArray) } catch [System.Net.WebException] { Write-Warning "Upload of $url failed" } finally { while ($wc.IsBusy) {} $wc.Dispose() Remove-Job * -Force } } Write-Output 'Retrieving configuration...' $uri = 'http://beta.speedtest.net/speedtest-config.php' [xml]$config = Invoke-WebRequest -Uri $uri -UseBasicParsing $ip = $config.settings.client.ip $isp = $config.settings.client.isp Write-Output "Testing from $isp ($ip)" $orilat = $config.settings.client.lat $orilon = $config.settings.client.lon Write-Output 'Retrieving server list...' $uri = 'http://www.speedtest.net/speedtest-servers.php' [xml]$hosts = Invoke-WebRequest -Uri $uri -UseBasicParsing Write-Output 'Selecting best server...' $servers = $hosts.settings.servers.server # Sort the distance of each server $closestserver = Get-ServerInfo -Servers $servers | Sort-Object -Property distance $servers = $closestserver[0],$closestserver[1],$closestserver[2] $serverurlspilt = ($servers).host -split ':8080' $servers = $serverurlspilt[0],$serverurlspilt[2],$serverurlspilt[4] # Get avg ping response $bestserver = Get-AvgPing -servers $servers # Getting lazy and just want lowest latency server asap $index = 0 $minvalue = [decimal]::MaxValue $bestserver.avg | ForEach-Object { if ($minvalue -gt $_) {$minvalue = $_; $minindex = $index}; $index++ } $location = $closestserver[$index].sponsor $distance = $closestserver[$index].distance Write-Output "Hosted by $location [$distance km] ($minvalue ms)" $serverurlspilt = ($closestserver[$index]).url -split 'upload' $url = $serverurlspilt[0] + 'random2000x2000.jpg' Write-Output 'Testing download speed...' Get-DataWCAsync -Url $url -IncludeStats Write-Output "Download: $down Mbps" # Creating a random byte array to avoid bad download data messing with the upload $bytearray = New-Object Byte[] 7864320 (New-Object Random).NextBytes($bytearray) $url = ($closestserver[$index]).url Write-Output 'Testing upload speed...' Push-DataWCAsync -url $url -byteArray $bytearray -includeStats Write-Output "Upload: $upload Mbps" Write-Output 'Tests Completed' } |