public/Invoke-SpeedTest.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<#
    .SYNOPSIS
    Starts a bandwidth test over the internet or on the local private network.

    .DESCRIPTION
    Starts a bandwidth test with iPerf3 over the internet against a public iPerf3 server, or on the local private network against a previously-configured iPerf3 server.

    .PARAMETER Internet
    Forces the bandwitdth test to run over the internet against a public iPerf3 server.
    If a default public iPerf3 server is not specified in the configuration file, the user will be prompted to run Set-SpeedTestConfig.

    .PARAMETER Local
    Forces the bandwidth test to run over the local network against a locally-accessible iPerf3 server.
    If a default server is not specified in the configuration file, the user will be prompted to run Set-SpeedTestConfig.

    .PARAMETER Server
    The hostname or IP address of a server that is running iPerf3 as a listening service.

    .PARAMETER Port
    The port on the iPerf3 server that iPerf3 is listening on.
    This will run the local iPerf3 client on the same port as they must match on the client and the server.
    If Server is specified and Port is not, the default port '5201' will be used.
    
    .PARAMETER PassThru
    Returns a PSCustomObject with the send/receive speeds as properties.

    .EXAMPLE
    Invoke-SpeedTest -Internet
    Runs a bandwidth test against default public iPerf3 server that is stored in the configuration.
    If there is no stored default, you will be prompted to set one.

    .EXAMPLE
    Invoke-SpeedTest -Local
    Runs a bandwidth test against default local iPerf3 server that is stored in the configuration.
    If there is no stored default, you will be prompted to set one.

    .EXAMPLE
    Invoke-SpeedTest -Server local.domain.com
    Runs a bandwidth test against iPerf3 server 'local.domain.com' on default port '5201'.

    .EXAMPLE
    Invoke-SpeedTest -Server 20.19.57.21 -Port 7777
    Runs a bandwidth test against iPerf3 server '20.19.57.21' on port '7777'.

    .EXAMPLE
    Invoke-SpeedTest -Server 20.19.57.21 -Port 7777
    Runs a bandwidth test against iPerf3 server '20.19.57.21' on port '7777'.
    Returns the send/receive speeds as a PSCustomObject with properties.
#>


function Invoke-SpeedTest {
    [CmdletBinding()]
    Param (
        [Parameter(ParameterSetName="Internet")]
        [Switch]
        $Internet,
        [Parameter(ParameterSetName="Local")]
        [Switch]
        $Local,
        [Parameter(Mandatory=$true,
            ParameterSetName="Specified")]
        [ValidateNotNullOrEmpty()]
        [String]
        $Server,
        [Parameter(ParameterSetName="Specified")]
        [ValidateNotNullOrEmpty()]
        [String]
        $Port,
        [Switch]
        $PassThru
    )

    Write-Verbose -Message "Starting speed test."

    Install-ChocolateyGetProvider
    Install-iPerf3

    $config = Get-SpeedTestConfig -PassThru
    $command = "iperf3.exe "
    $usedServer = ""
    $usedPort = ""

    if ($Internet) {
        Write-Verbose -Message "Defaulting to stored Internet speed test server settings."
        if (!($config.defaultInternetServer.defaultServer)) {
            throw "No default Internet server configured - run Set-SpeedTestConfig."
        }
        else {
            $usedServer = $config.defaultInternetServer.defaultServer
            $command = $command + "-c $usedServer "
            if ($config.defaultInternetServer.defaultPort) {
                $usedPort = $config.defaultInternetServer.defaultPort
                $command = $command + "-p $usedPort "
            }
            else {
                $usedPort = $config.defaultPort
                $command = $command + "-p $usedPort "
            }
        }
    }
    elseif ($Local) {
        Write-Verbose -Message "Defaulting to stored Local speed test server settings."
        if (!($config.defaultLocalServer.defaultServer)) {
            throw "No default Local server configured - run Set-SpeedTestConfig."
        }
        else {
            $usedServer = $config.defaultLocalServer.defaultServer
            $command = $command + "-c $usedServer "
            if ($config.defaultLocalServer.defaultPort) {
                $usedPort = $config.defaultLocalServer.defaultPort
                $command = $command + "-p $usedPort "
            }
            else {
                $usedPort = $config.defaultPort
                $command = $command + "-p $usedPort "
            }
        }
    }
    elseif ($Server) {
        Write-Verbose -Message "Server: $Server and port: $Port specified manually."
        $usedServer = $Server
        $command = $command + "-c $usedServer "
        if ($Port) {
            $usedPort = $Port
            $command = $command + "-p $usedPort "
        }
        else {
            $usedPort = $config.defaultPort
            $command = $command + "-p $usedPort "
        }
    }

    $command = $command + "-f m -J"

    Write-Verbose -Message "Executing command: $command"

    $resultsJSON = Invoke-Expression -Command $command
    $resultsPS = $resultsJSON | ConvertFrom-Json

    if ($resultsPS.error) {
        if ($resultsPS.error -match 'unable to connect to server'){
            throw "Catastrophic error occurred: $($resultsPS.error)"
        }
        else {
            Write-Warning -Message "Problem occurred: $($resultsPS.error)"
            $megabitsPerSecSent = 0
            $megabitsPerSecReceived = 0
        }
    }
    else {
        Write-Verbose -Message "Speed test successful; calculating mbps and returning PSCustomObject."
        $megabitsPerSecSent = (($resultsPS.end.sum_sent.bits_per_second) / 1000000.0).ToInt32($null)
        $megabitsPerSecReceived = (($resultsPS.end.sum_received.bits_per_second) / 1000000.0).ToInt32($null)
    }

    if ($PassThru) {
        $returnObj = New-Object -TypeName 'PSCustomObject' @{
            megabitsPerSecSent = $megabitsPerSecSent;
            megabitsPerSecReceived = $megabitsPerSecReceived;
        }

        return $returnObj
    }
    else {
        Write-Host "Results of speed test against server '$usedServer' on port '$usedPort':"
        Write-Host " Send speed: $megabitsPerSecSent mbps"
        Write-Host " Receive speed: $megabitsPerSecReceived mbps"
    }
}