wifi-watch 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 697446ea552c7a3457679d63683eca662ffb8f3a
4
+ data.tar.gz: cbb35fe686254583710005731b65469fb9118eaf
5
+ SHA512:
6
+ metadata.gz: ba64b8fa9cb33a576390acaaf3807c12b3a47a6b23a2a7babe9dd1527412a4d80033c7e86b5f6f9fa457701f8ff3597740e6c13d38b11d649343945a607cbba3
7
+ data.tar.gz: 426294ddb194941801ff65d1ca5969595b9b8311d4d67e866ec1febcd38054ac6e3817cf6e623f6b79aa4663398e64373162eb61605708373e72f421f08698d5
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in wifi-watch.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 John Gorman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # wifi-watch
2
+
3
+ Continuously monitor your network speed and quality!
4
+
5
+ ```
6
+ $ wifi-watch
7
+ PING ns.google.com (216.239.32.10): 56 data bytes
8
+
9
+ Time Ping Run Mode Failed Round Trip
10
+ ----- ---- ---- ---- ------ ----------
11
+ 16:55 300 298 good 0.7% 250.83 ms
12
+ 17:00 300 296 good 1.3% 219.14 ms
13
+ 17:03 136 67 good 1.5% 676.17 ms
14
+ ```
15
+
16
+ Run wifi-watch in a terminal so that you can easily check
17
+ your network quality at this moment and how it has been
18
+ holding up since you began recording hours or days ago.
19
+
20
+ wifi-watch will run ping every second and refresh the
21
+ current line with the current counts. At the end of
22
+ an accounting period the current counts are saved
23
+ as a history line and a new accounting period begins.
24
+
25
+ This can be invaluable in monitoring your home internet
26
+ for systematic service degradation. Service technicians
27
+ pay attention when you can give them exact ping times
28
+ and packet loss history!
29
+
30
+ It is also a very helpful in public wifi environments
31
+ to be able to see how the shared bandwidth is holding up
32
+ on a moment to moment basis.
33
+
34
+ ### Installation
35
+
36
+ wifi-watch is a stand alone ruby script which will run with
37
+ any ruby version and has no dependencies. Clone the repository
38
+ and copy wifi-watch into your path.
39
+
40
+ ```
41
+ git clone https://github.com/jgorman/wifi-watch.git
42
+ sudo cp wifi-watch/bin/wifi-watch /usr/local/bin
43
+ ```
44
+
45
+ ### Usage: wifi-watch [options]
46
+
47
+ ```
48
+ -h, --host host Host to ping [ns.google.com].
49
+ -c, --count seconds Accounting period [600].
50
+ --debug-to file Write ping output to a file for debugging.
51
+ --debug-from file Read ping input from a file for testing.
52
+ -v, --version Version.
53
+ --help This message.
54
+ ```
55
+
56
+ ### Current Period Status Counts
57
+
58
+ The current output line shows counts for the current period.
59
+
60
+ ```
61
+ Time Ping Run Mode Failed Round Trip
62
+ ----- ---- ---- ---- ------ ----------
63
+ 17:03 136 67 good 1.5% 676.17 ms
64
+ ```
65
+
66
+ - Current time.
67
+ - 136 pings attempted so far in the current period.
68
+ - Run of 67 good pings in a row!
69
+ - Status of the last ping: "good" or "fail".
70
+ - Packet loss percentage so far.
71
+ - Round trip time of the last successful ping.
72
+
73
+ ### History Lines
74
+
75
+ Here is the past half hour of my network quality history.
76
+
77
+ In this example things were going great, then my
78
+ connection slowed down over the last 15 minutes.
79
+ I am working in a crowded coffee shop right now
80
+ and perhaps a few of us are watching videos.
81
+
82
+ ```
83
+ Time Ping Run Mode Failed Round Trip
84
+ ----- ---- ---- ---- ------ ----------
85
+ 16:30 300 298 good 0.7% 63.84 ms
86
+ 16:35 300 300 good 0.0% 76.28 ms
87
+ 16:40 300 300 good 0.0% 74.45 ms
88
+ 16:45 300 297 good 1.0% 129.55 ms
89
+ 16:50 300 296 good 1.3% 233.94 ms
90
+ 16:55 300 298 good 0.7% 250.83 ms
91
+ 17:00 300 296 good 1.3% 219.14 ms
92
+ 17:03 136 67 good 1.5% 676.17 ms
93
+ ```
94
+
95
+ - History lines show the end time for each period.
96
+ - Count of good pings over the period.
97
+ - Packet loss percentage.
98
+ - Average round trip time over the entire period.
99
+
100
+ ### Failure Reporting
101
+
102
+ #### Ping success or failure run length.
103
+
104
+ On the current bottom line the run length count resets to 1
105
+ on every transition between "good" and "fail" modes. This way
106
+ we can tell at a glance how long we have been in the current
107
+ state. In a still connected high packet loss environment
108
+ the runs will be short and switch modes often.
109
+
110
+ Here we have lost our internet connection for the last 39 seconds.
111
+
112
+ ```
113
+ Time Ping Run Mode Failed Round Trip
114
+ ----- ---- ---- ---- ------ ----------
115
+ 17:59 207 39 fail 19.3% 62.55 ms
116
+ ```
117
+
118
+ #### Slow DNS lookup.
119
+
120
+ At the beginning of an accounting period ping does a DNS lookup
121
+ to find your target host ip address. Sometimes this can take
122
+ quite a while to either succeed or fail. If the wait is more
123
+ than one second you will see a status message.
124
+
125
+ ```
126
+ Time Ping Run Mode Failed Round Trip
127
+ ----- ---- ---- ---- ------ ----------
128
+ 14:38 10 4 good 60.0% 35.69 ms
129
+ 14:38:52 Waiting for dns lookup of ns.google.com ...
130
+ 14:39 10 10 good 0.0% 49.52 ms
131
+ ```
132
+
133
+ #### Failing DNS lookup.
134
+
135
+ When the network is not connected at the beginning of an
136
+ accounting period the host DNS lookup will fail to resolve.
137
+
138
+ ```
139
+ Time Ping Run Mode Failed Round Trip
140
+ ----- ---- ---- ---- ------ ----------
141
+ 08:40 300 51 good 83.0% 68.65 ms
142
+ 08:41:06 ping: cannot resolve ns.google.com: Unknown host
143
+ 08:42 62 17 fail 27.4% 187.30 ms
144
+ ```
145
+
146
+ #### Wifi login timeout.
147
+
148
+ Sometimes your coffee shop wifi login will time out and you will
149
+ need to login again. Wifi-watch will let you know by showing the
150
+ response message.
151
+
152
+ ```
153
+ 10:45:43 92 bytes from 10.128.128.128: Communication prohibited by filter
154
+ ```
155
+
156
+ ## Testing and Debugging
157
+
158
+ It is easy to capture the raw ping output to a file for later
159
+ replay and testing.
160
+
161
+ ```
162
+ wifi-watch --count 10 --debug-to test1.log
163
+ PING ns.google.com (216.239.32.10): 56 data bytes
164
+
165
+ Time Ping Run Mode Failed Round Trip
166
+ ----- ---- ---- ---- ------ ----------
167
+ 10:06 10 10 good 0.0% 127.41 ms
168
+ 10:06 10 3 good 70.0% 34.28 ms
169
+ 10:06:34 ping: cannot resolve ns.google.com: Unknown host
170
+ 10:06 5 1 fail 20.0% 55.16 ms^C
171
+ ```
172
+
173
+ The ping output file includes the timestamp for each line
174
+ so replaying the file later on should result in
175
+ identical appearing output.
176
+
177
+ ```
178
+ wifi-watch --debug-from test1.log
179
+ PING ns.google.com (216.239.32.10): 56 data bytes
180
+
181
+ Time Ping Run Mode Failed Round Trip
182
+ ----- ---- ---- ---- ------ ----------
183
+ 10:06 10 10 good 0.0% 127.41 ms
184
+ 10:06 10 3 good 70.0% 34.28 ms
185
+ 10:06:34 ping: cannot resolve ns.google.com: Unknown host
186
+ 10:06 5 1 fail 20.0% 55.16 ms
187
+ ```
188
+
189
+ Although the --debug-from output should appear to be the same
190
+ as live ping monitoring there is a difference. Instead of emitting
191
+ every intermediate count on the current line, only the final
192
+ line is printed. This helps keep test cases short and readable.
193
+
194
+ You can run the current test suite with rake test.
195
+
196
+ ## Contributing
197
+
198
+ Bug reports and pull requests are welcome on GitHub at
199
+ https://github.com/jgorman/wifi-watch.
200
+
201
+ If you discover a shortcoming capture the ping output
202
+ using --debug-to and open an issue. Thanks!
203
+
204
+ ## License
205
+
206
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :default => :test
4
+
5
+ desc "Run tests"
6
+ task :test do
7
+ sh %{ test/run_tests }
8
+ end
data/bin/wifi-watch ADDED
@@ -0,0 +1,396 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'ostruct'
5
+ require 'pty'
6
+
7
+ class WifiWatch
8
+
9
+ Default_host = "ns.google.com" # Ping target host.
10
+ Default_count = 600 # Accounting period in seconds.
11
+ Program = "wifi-watch"
12
+ Version = "1.0.0"
13
+
14
+ def run
15
+ @shown_header = false # Have we shown the column headers yet?
16
+ @dns_failing = false # Are DNS lookups currently failing?
17
+ @display_line = nil # The current display line.
18
+ @debug_to = nil # Save timestamped ping output here.
19
+ @debug_from = nil # Read timestamped ping input here.
20
+ @options = get_options()
21
+
22
+ if @options.debug_to
23
+ begin
24
+ @debug_to = File.open(@options.debug_to, "w")
25
+ rescue => e
26
+ puts
27
+ puts "debug_to=#{@options.debug_to}: #{e}"
28
+ puts
29
+ exit
30
+ end
31
+ end
32
+
33
+ if @options.debug_from
34
+
35
+ # Debug mode simulates ping output from a captured --debug-to file.
36
+ begin
37
+ @debug_from = File.open(@options.debug_from, "r")
38
+ rescue => e
39
+ puts
40
+ puts "debug_from=#{@options.debug_from}: #{e}"
41
+ puts
42
+ exit
43
+ end
44
+
45
+ # Call ping_period() for each ping run section.
46
+ until @debug_from.eof?
47
+ ping_period(@debug_from) # Reads up to next "END_OF_PING" line.
48
+ end
49
+ if @dns_failing
50
+ commit_line() # Show that we ended up in dns failure mode.
51
+ end
52
+
53
+ else
54
+
55
+ # Run ping multiple times.
56
+ while true
57
+ count = beautiful_times()
58
+ cmd = "ping -c #{count} #{@options.host}"
59
+ stdin, stdout, pid = PTY.spawn( cmd )
60
+ ping_period(stdin) # Run one accounting period.
61
+ Process.waitall() # Soak up any zombie pings.
62
+ end
63
+
64
+ end
65
+
66
+ rescue Interrupt
67
+ commit_line()
68
+ ensure
69
+ if @debug_to
70
+ @debug_to.close
71
+ end
72
+ end
73
+
74
+ def get_options
75
+ options = OpenStruct.new
76
+ options.host = Default_host
77
+ options.count = Default_count
78
+
79
+ opt_parser = OptionParser.new do |opt|
80
+ opt.banner = "Usage: #{Program} [OPTIONS]"
81
+ opt.separator ""
82
+
83
+ opt.on("-h", "--host host", "Host to ping [#{options.host}].") do |host|
84
+ options.host = host
85
+ end
86
+
87
+ opt.on("-c", "--count seconds", Integer,
88
+ "Accounting period [#{options.count}].") do |count|
89
+ options.count = count
90
+ end
91
+
92
+ opt.on("--debug-to file",
93
+ "Write ping output to a file for debugging.") do |debug_to|
94
+ options.debug_to = debug_to
95
+ end
96
+
97
+ opt.on("--debug-from file",
98
+ "Read ping input from a file for testing.") do |debug_from|
99
+ options.debug_from = debug_from
100
+ end
101
+
102
+ opt.on("-v", "--version", "Version.") do
103
+ puts Version
104
+ exit
105
+ end
106
+
107
+ opt.on("--help", "This message.") do
108
+ puts
109
+ puts opt_parser
110
+ puts
111
+ exit
112
+ end
113
+
114
+ opt.separator ""
115
+ opt.separator "Documentation at https://github.com/jgorman/wifi-watch"
116
+
117
+ end
118
+
119
+ begin
120
+ opt_parser.parse!
121
+ rescue => e
122
+ puts
123
+ puts e
124
+ puts
125
+ puts opt_parser
126
+ puts
127
+ exit
128
+ end
129
+
130
+ return options
131
+ end
132
+
133
+ # Run ping for one accounting period.
134
+ def ping_period(stdin)
135
+
136
+ current_mode = nil # Are we currently "good" or "fail"?
137
+ mode_count = 0 # For how long in a row?
138
+ total_count = 0 # Pings so far.
139
+ totally_good = 0 # Successful pings.
140
+ ping_ms = 0.0 # Latest successful ping time in milliseconds.
141
+ packets_line = '' # Ping packets received summary line.
142
+ round_trip_line = '' # Ping round-trip milliseconds summary line.
143
+ filter_mode = false # Wifi login filter is active.
144
+ line_time = nil # Latest line timestamp.
145
+ first_byte = nil # DNS lookup complete read test byte.
146
+
147
+ # Long DNS lookups can effectively freeze ping for a while.
148
+ # To reproduce: turn VPN off and then on, then turn WiFi off.
149
+ # This logic is impractical to simulate in a meaningful way
150
+ # so we just pass the messages on for later debugging display.
151
+ waiting_start = Time.now
152
+ last_notified = waiting_start
153
+ until first_byte
154
+ begin
155
+ first_byte = stdin.read_nonblock(1)
156
+ rescue IO::EAGAINWaitReadable
157
+ now = Time.now
158
+ if now - last_notified >= 1
159
+ hhmmss_line(now, "Waiting for dns lookup of #{@options.host} ...")
160
+ if @debug_to
161
+ @debug_to.puts "#{now.to_i} DNS_LOOKUP #{@display_line}"
162
+ @debug_to.flush
163
+ end
164
+ last_notified = now
165
+ end
166
+ sleep 0.2 # Be nice to the cpu.
167
+ end
168
+ end
169
+ if last_notified > waiting_start
170
+ commit_line()
171
+ end
172
+
173
+ # Process each line of ping output.
174
+ stdin.each do |line|
175
+
176
+ line.chomp!
177
+ if first_byte
178
+ line = first_byte + line
179
+ first_byte = nil
180
+ end
181
+
182
+ if @debug_from
183
+ # Read from the debugging source file up to the end of this ping run.
184
+ if line == "END_OF_PING"
185
+ break # End this ping accounting period run.
186
+ end
187
+ # Simulate the past by loading the effective time for this line.
188
+ time, line = line.split(" ", 2)
189
+ line_time = Time.at(time.to_i)
190
+ else
191
+ line_time = Time.now
192
+ end
193
+
194
+ if @debug_to
195
+ # Capture this ping output line with the timestamp for later debugging.
196
+ @debug_to.puts "#{line_time.to_i} #{line}"
197
+ @debug_to.flush
198
+ end
199
+
200
+ # DNS failure modes.
201
+ if line =~ /cannot resolve/
202
+ # ping: cannot resolve ns.google.com: Unknown host
203
+ hhmmss_line(line_time, line)
204
+ sleep 1 unless @debug_from # Speed up testing.
205
+ @dns_failing = true
206
+ elsif line =~ /DNS_LOOKUP (.*)/
207
+ # Waiting for dns lookup of ns.google.com ...
208
+ display_line($1)
209
+ @dns_failing = true
210
+ elsif @dns_failing
211
+ # If DNS was previously failing, pop to a fresh line.
212
+ commit_line()
213
+ @dns_failing = false
214
+ end
215
+
216
+ # This indicates a ping success or failure line. Nil means neither.
217
+ new_mode = nil
218
+
219
+ # Parse the line.
220
+ if line =~ /PING/
221
+ #
222
+ # The first ping output line shows the destination host and ip.
223
+ #
224
+ # PING ns.google.com (216.239.32.10): 56 data bytes
225
+ #
226
+ unless @shown_header
227
+ puts line # Show the destination name and ip.
228
+ puts
229
+ puts "Time Ping Run Mode Failed Round Trip"
230
+ puts "----- ---- ---- ---- ------ ----------"
231
+ @shown_header = true # Only show these once per wifi-watch.
232
+ end
233
+
234
+ elsif line =~ /bytes from/
235
+ if line =~ /time=(\S+)/
236
+ #
237
+ # Success! Record the round trip time.
238
+ #
239
+ # 64 bytes from 104.27.146.148: icmp_seq=48 ttl=61 time=24.780 ms
240
+ #
241
+ ping_ms = $1.to_f
242
+ new_mode = 'good'
243
+ if filter_mode
244
+ commit_line() # Keep the filter message line.
245
+ filter_mode = false
246
+ end
247
+ else
248
+ #
249
+ # Here the wifi login has timed out and is blocking packets.
250
+ # Multi line ping output shows both the timeout and filter message
251
+ # lines plus some additional diagnostic lines that we ignore.
252
+ #
253
+ # Request timeout for icmp_seq 5
254
+ # 92 bytes from 10.128.128.128: Communication prohibited by filter
255
+ # Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
256
+ # 4 5 00 5400 6dea 0 0000 40 01 21dd 10.57.228.249 104.27.147.148
257
+ #
258
+ unless filter_mode
259
+ commit_line() # Keep the last unfiltered status line.
260
+ filter_mode = true
261
+ end
262
+ hhmmss_line(line_time, line)
263
+ end
264
+
265
+ elsif line =~ /timeout/
266
+ # Request timeout for icmp_seq 3
267
+ new_mode = 'fail'
268
+
269
+ elsif line =~ /transmitted/
270
+ # 5 packets transmitted, 5 packets received, 0.0% packet loss
271
+ packets_line = line
272
+
273
+ elsif line =~ /round-trip/
274
+ # round-trip min/avg/max/stddev = 0.063/0.082/0.122/0.022 ms
275
+ round_trip_line = line
276
+ end
277
+
278
+ if new_mode
279
+ # Update the counts with success or failure.
280
+ if new_mode != current_mode
281
+ current_mode = new_mode
282
+ mode_count = 0
283
+ end
284
+ mode_count += 1
285
+ totally_good += 1 if current_mode == 'good'
286
+ total_count += 1
287
+ unless filter_mode
288
+ show_stats(line_time, total_count, totally_good,
289
+ current_mode, mode_count, ping_ms)
290
+ end
291
+ end
292
+
293
+ end
294
+
295
+ if @debug_to
296
+ # Insert a ping run separator line into the debugging file.
297
+ @debug_to.puts "END_OF_PING"
298
+ @debug_to.flush
299
+ end
300
+
301
+ # Final summary line.
302
+ if packets_line =~ /(\d+) packets transmitted, (\d+) packets received/
303
+ total_count = $1.to_i
304
+ totally_good = $2.to_i
305
+ if round_trip_line =~ / (\S+) ms/
306
+ avg_ms = $1.split('/')[1].to_f # Extract the average time.
307
+ end
308
+ show_stats(line_time, total_count, totally_good,
309
+ 'good', totally_good, avg_ms)
310
+ end
311
+
312
+ unless @dns_failing
313
+ commit_line() # Leave this summary line as history.
314
+ end
315
+ end
316
+
317
+ # Show the statistics.
318
+ def show_stats(line_time, total_count, totally_good,
319
+ current_mode, mode_count, ms)
320
+ loss = ((total_count - totally_good) * 100.0) / total_count
321
+ line = sprintf("%4d %4d %s %5.1f%% %7.2f ms",
322
+ total_count, mode_count, current_mode, loss, ms)
323
+ hhmm_line(line_time, line)
324
+ end
325
+
326
+ # Make history lines pretty.
327
+ # We want the history minutes to be modulo the accounting minutes.
328
+ # Where possible we want to let the ping counts to be the same.
329
+ # Ping can drift backward by one second and forward by a few seconds each run.
330
+ # Overall the drift is usually forward so when we need to make an adjustment
331
+ # we aim for 10 seconds into the next aligned minute.
332
+ def beautiful_times()
333
+ count = @options.count
334
+
335
+ # Is the target count minute aligned?
336
+ if count % 60 != 0
337
+ return count # Not minute aligned.
338
+ end
339
+
340
+ # Is the target count hour aligned?
341
+ minutes = count / 60
342
+ if 60 % minutes != 0 || minutes < 2
343
+ return count # Not hour aligned and multiple minutes.
344
+ end
345
+
346
+ # See if we are already suitable aligned right now.
347
+ now = Time.now
348
+ mm = now.min
349
+ ss = now.sec
350
+ if mm % minutes == 0 && 1 <= ss && ss <= 50
351
+ return count # Now is minute aligned and within minute drift limits.
352
+ end
353
+
354
+ # Target 10 seconds into the next aligned minute.
355
+ short_mm = minutes - (mm % minutes)
356
+ count = (short_mm * 60) + 10 - ss
357
+ return count
358
+ end
359
+
360
+ def hhmm_line(time, line)
361
+ line = "#{time.strftime('%H:%M')} #{line}"
362
+ display_line(line)
363
+ end
364
+
365
+ def hhmmss_line(time, line)
366
+ line = "#{time.strftime('%H:%M:%S')} #{line}"
367
+ display_line(line)
368
+ end
369
+
370
+ # Rewrite the current display line or save it for final debugging result.
371
+ def display_line(line)
372
+ @display_line = line
373
+ unless @debug_from
374
+ # Display this current line.
375
+ STDOUT.write "\r" # Move to the start of this line.
376
+ STDOUT.write line # Write over it.
377
+ end
378
+ end
379
+
380
+ # If there is a current display line, commit it to history.
381
+ def commit_line()
382
+ if @display_line
383
+ if @debug_from
384
+ # Debug mode show final line value as history.
385
+ puts @display_line
386
+ else
387
+ # Normal mode advance to the next line leaving this line as history.
388
+ puts
389
+ end
390
+ @display_line = nil
391
+ end
392
+ end
393
+
394
+ end
395
+
396
+ WifiWatch.new.run
@@ -0,0 +1,11 @@
1
+ 09:47:38 ping: cannot resolve ns.google.com: Unknown host
2
+ PING ns.google.com (216.239.32.10): 56 data bytes
3
+
4
+ Time Ping Run Mode Failed Round Trip
5
+ ----- ---- ---- ---- ------ ----------
6
+ 09:47 10 10 good 0.0% 54.45 ms
7
+ 09:47 10 5 good 50.0% 76.66 ms
8
+ 09:48:06 ping: cannot resolve ns.google.com: Unknown host
9
+ 09:48 10 10 good 0.0% 72.06 ms
10
+ 09:48 10 3 good 70.0% 82.17 ms
11
+ 09:48:34 ping: cannot resolve ns.google.com: Unknown host
@@ -0,0 +1,9 @@
1
+ 17:42:00 Waiting for dns lookup of ns.google.com ...
2
+ PING ns.google.com (216.239.32.10): 56 data bytes
3
+
4
+ Time Ping Run Mode Failed Round Trip
5
+ ----- ---- ---- ---- ------ ----------
6
+ 17:42 10 6 good 40.0% 76.50 ms
7
+ 17:42:18 Waiting for dns lookup of ns.google.com ...
8
+ 17:42 10 4 good 60.0% 76.68 ms
9
+ 17:42:33 Waiting for dns lookup of ns.google.com ...
@@ -0,0 +1,6 @@
1
+ PING ns.google.com (216.239.32.10): 56 data bytes
2
+
3
+ Time Ping Run Mode Failed Round Trip
4
+ ----- ---- ---- ---- ------ ----------
5
+ 10:31 10 10 good 0.0% 80.47 ms
6
+ 10:31 8 5 fail 62.5% 32.70 ms
@@ -0,0 +1,7 @@
1
+ PING ns.google.com (216.239.32.10): 56 data bytes
2
+
3
+ Time Ping Run Mode Failed Round Trip
4
+ ----- ---- ---- ---- ------ ----------
5
+ 10:45 5 1 fail 20.0% 68.06 ms
6
+ 10:45:43 92 bytes from 10.128.128.128: Communication prohibited by filter
7
+ 10:45 11 3 good 36.4% 61.58 ms
@@ -0,0 +1,129 @@
1
+ 1520606847 ping: cannot resolve ns.google.com: Unknown host
2
+ END_OF_PING
3
+ 1520606848 ping: cannot resolve ns.google.com: Unknown host
4
+ END_OF_PING
5
+ 1520606849 ping: cannot resolve ns.google.com: Unknown host
6
+ END_OF_PING
7
+ 1520606850 ping: cannot resolve ns.google.com: Unknown host
8
+ END_OF_PING
9
+ 1520606851 ping: cannot resolve ns.google.com: Unknown host
10
+ END_OF_PING
11
+ 1520606852 ping: cannot resolve ns.google.com: Unknown host
12
+ END_OF_PING
13
+ 1520606853 ping: cannot resolve ns.google.com: Unknown host
14
+ END_OF_PING
15
+ 1520606854 ping: cannot resolve ns.google.com: Unknown host
16
+ END_OF_PING
17
+ 1520606855 ping: cannot resolve ns.google.com: Unknown host
18
+ END_OF_PING
19
+ 1520606856 ping: cannot resolve ns.google.com: Unknown host
20
+ END_OF_PING
21
+ 1520606857 ping: cannot resolve ns.google.com: Unknown host
22
+ END_OF_PING
23
+ 1520606858 ping: cannot resolve ns.google.com: Unknown host
24
+ END_OF_PING
25
+ 1520606859 PING ns.google.com (216.239.32.10): 56 data bytes
26
+ 1520606859 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=36.533 ms
27
+ 1520606860 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=47.722 ms
28
+ 1520606861 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=35.427 ms
29
+ 1520606862 64 bytes from 216.239.32.10: icmp_seq=3 ttl=44 time=64.084 ms
30
+ 1520606863 64 bytes from 216.239.32.10: icmp_seq=4 ttl=44 time=69.815 ms
31
+ 1520606864 64 bytes from 216.239.32.10: icmp_seq=5 ttl=44 time=40.960 ms
32
+ 1520606865 64 bytes from 216.239.32.10: icmp_seq=6 ttl=44 time=106.540 ms
33
+ 1520606866 64 bytes from 216.239.32.10: icmp_seq=7 ttl=44 time=34.226 ms
34
+ 1520606867 64 bytes from 216.239.32.10: icmp_seq=8 ttl=44 time=39.930 ms
35
+ 1520606868 64 bytes from 216.239.32.10: icmp_seq=9 ttl=44 time=69.299 ms
36
+ 1520606868
37
+ 1520606868 --- ns.google.com ping statistics ---
38
+ 1520606868 10 packets transmitted, 10 packets received, 0.0% packet loss
39
+ 1520606868 round-trip min/avg/max/stddev = 34.226/54.454/106.540/21.892 ms
40
+ END_OF_PING
41
+ 1520606868 PING ns.google.com (216.239.32.10): 56 data bytes
42
+ 1520606868 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=35.391 ms
43
+ 1520606869 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=141.665 ms
44
+ 1520606870 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=131.141 ms
45
+ 1520606871 64 bytes from 216.239.32.10: icmp_seq=3 ttl=44 time=35.320 ms
46
+ 1520606872 64 bytes from 216.239.32.10: icmp_seq=4 ttl=44 time=39.757 ms
47
+ 1520606873 ping: sendto: No route to host
48
+ 1520606874 ping: sendto: No route to host
49
+ 1520606874 Request timeout for icmp_seq 5
50
+ 1520606875 ping: sendto: No route to host
51
+ 1520606875 Request timeout for icmp_seq 6
52
+ 1520606876 ping: sendto: No route to host
53
+ 1520606876 Request timeout for icmp_seq 7
54
+ 1520606877 ping: sendto: No route to host
55
+ 1520606877 Request timeout for icmp_seq 8
56
+ 1520606879
57
+ 1520606879 --- ns.google.com ping statistics ---
58
+ 1520606879 10 packets transmitted, 5 packets received, 50.0% packet loss
59
+ 1520606879 round-trip min/avg/max/stddev = 35.320/76.655/141.665/48.924 ms
60
+ END_OF_PING
61
+ 1520606879 ping: cannot resolve ns.google.com: Unknown host
62
+ END_OF_PING
63
+ 1520606880 ping: cannot resolve ns.google.com: Unknown host
64
+ END_OF_PING
65
+ 1520606881 ping: cannot resolve ns.google.com: Unknown host
66
+ END_OF_PING
67
+ 1520606882 ping: cannot resolve ns.google.com: Unknown host
68
+ END_OF_PING
69
+ 1520606883 ping: cannot resolve ns.google.com: Unknown host
70
+ END_OF_PING
71
+ 1520606884 ping: cannot resolve ns.google.com: Unknown host
72
+ END_OF_PING
73
+ 1520606885 ping: cannot resolve ns.google.com: Unknown host
74
+ END_OF_PING
75
+ 1520606886 ping: cannot resolve ns.google.com: Unknown host
76
+ END_OF_PING
77
+ 1520606887 PING ns.google.com (216.239.32.10): 56 data bytes
78
+ 1520606887 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=40.028 ms
79
+ 1520606888 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=44.796 ms
80
+ 1520606889 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=43.484 ms
81
+ 1520606890 64 bytes from 216.239.32.10: icmp_seq=3 ttl=44 time=238.342 ms
82
+ 1520606891 64 bytes from 216.239.32.10: icmp_seq=4 ttl=44 time=161.573 ms
83
+ 1520606892 64 bytes from 216.239.32.10: icmp_seq=5 ttl=44 time=57.327 ms
84
+ 1520606893 64 bytes from 216.239.32.10: icmp_seq=6 ttl=44 time=36.289 ms
85
+ 1520606894 64 bytes from 216.239.32.10: icmp_seq=7 ttl=44 time=31.354 ms
86
+ 1520606895 64 bytes from 216.239.32.10: icmp_seq=8 ttl=44 time=32.630 ms
87
+ 1520606896 64 bytes from 216.239.32.10: icmp_seq=9 ttl=44 time=34.819 ms
88
+ 1520606896
89
+ 1520606896 --- ns.google.com ping statistics ---
90
+ 1520606896 10 packets transmitted, 10 packets received, 0.0% packet loss
91
+ 1520606896 round-trip min/avg/max/stddev = 31.354/72.064/238.342/66.591 ms
92
+ END_OF_PING
93
+ 1520606896 PING ns.google.com (216.239.32.10): 56 data bytes
94
+ 1520606896 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=38.382 ms
95
+ 1520606897 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=120.228 ms
96
+ 1520606898 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=87.912 ms
97
+ 1520606899 ping: sendto: No route to host
98
+ 1520606900 ping: sendto: No route to host
99
+ 1520606900 Request timeout for icmp_seq 3
100
+ 1520606901 ping: sendto: No route to host
101
+ 1520606901 Request timeout for icmp_seq 4
102
+ 1520606902 ping: sendto: No route to host
103
+ 1520606902 Request timeout for icmp_seq 5
104
+ 1520606903 ping: sendto: No route to host
105
+ 1520606903 Request timeout for icmp_seq 6
106
+ 1520606904 ping: sendto: No route to host
107
+ 1520606904 Request timeout for icmp_seq 7
108
+ 1520606905 ping: sendto: No route to host
109
+ 1520606905 Request timeout for icmp_seq 8
110
+ 1520606907
111
+ 1520606907 --- ns.google.com ping statistics ---
112
+ 1520606907 10 packets transmitted, 3 packets received, 70.0% packet loss
113
+ 1520606907 round-trip min/avg/max/stddev = 38.382/82.174/120.228/33.659 ms
114
+ END_OF_PING
115
+ 1520606907 ping: cannot resolve ns.google.com: Unknown host
116
+ END_OF_PING
117
+ 1520606908 ping: cannot resolve ns.google.com: Unknown host
118
+ END_OF_PING
119
+ 1520606909 ping: cannot resolve ns.google.com: Unknown host
120
+ END_OF_PING
121
+ 1520606910 ping: cannot resolve ns.google.com: Unknown host
122
+ END_OF_PING
123
+ 1520606911 ping: cannot resolve ns.google.com: Unknown host
124
+ END_OF_PING
125
+ 1520606912 ping: cannot resolve ns.google.com: Unknown host
126
+ END_OF_PING
127
+ 1520606913 ping: cannot resolve ns.google.com: Unknown host
128
+ END_OF_PING
129
+ 1520606914 ping: cannot resolve ns.google.com: Unknown host
@@ -0,0 +1,47 @@
1
+ 1520635313 DNS_LOOKUP 17:41:53 Waiting for dns lookup of ns.google.com ...
2
+ 1520635314 DNS_LOOKUP 17:41:54 Waiting for dns lookup of ns.google.com ...
3
+ 1520635315 DNS_LOOKUP 17:41:55 Waiting for dns lookup of ns.google.com ...
4
+ 1520635317 DNS_LOOKUP 17:41:57 Waiting for dns lookup of ns.google.com ...
5
+ 1520635318 DNS_LOOKUP 17:41:58 Waiting for dns lookup of ns.google.com ...
6
+ 1520635319 DNS_LOOKUP 17:41:59 Waiting for dns lookup of ns.google.com ...
7
+ 1520635320 DNS_LOOKUP 17:42:00 Waiting for dns lookup of ns.google.com ...
8
+ 1520635320 PING ns.google.com (216.239.32.10): 56 data bytes
9
+ 1520635320 64 bytes from 216.239.32.10: icmp_seq=0 ttl=46 time=34.544 ms
10
+ 1520635321 64 bytes from 216.239.32.10: icmp_seq=1 ttl=46 time=31.144 ms
11
+ 1520635322 64 bytes from 216.239.32.10: icmp_seq=2 ttl=46 time=61.392 ms
12
+ 1520635323 64 bytes from 216.239.32.10: icmp_seq=3 ttl=46 time=29.985 ms
13
+ 1520635324 64 bytes from 216.239.32.10: icmp_seq=4 ttl=46 time=152.010 ms
14
+ 1520635325 64 bytes from 216.239.32.10: icmp_seq=5 ttl=46 time=149.945 ms
15
+ 1520635327 Request timeout for icmp_seq 6
16
+ 1520635328 Request timeout for icmp_seq 7
17
+ 1520635329 Request timeout for icmp_seq 8
18
+ 1520635331
19
+ 1520635331 --- ns.google.com ping statistics ---
20
+ 1520635331 10 packets transmitted, 6 packets received, 40.0% packet loss
21
+ 1520635331 round-trip min/avg/max/stddev = 29.985/76.503/152.010/53.705 ms
22
+ END_OF_PING
23
+ 1520635332 DNS_LOOKUP 17:42:12 Waiting for dns lookup of ns.google.com ...
24
+ 1520635333 DNS_LOOKUP 17:42:13 Waiting for dns lookup of ns.google.com ...
25
+ 1520635334 DNS_LOOKUP 17:42:14 Waiting for dns lookup of ns.google.com ...
26
+ 1520635335 DNS_LOOKUP 17:42:15 Waiting for dns lookup of ns.google.com ...
27
+ 1520635336 DNS_LOOKUP 17:42:16 Waiting for dns lookup of ns.google.com ...
28
+ 1520635337 DNS_LOOKUP 17:42:17 Waiting for dns lookup of ns.google.com ...
29
+ 1520635338 DNS_LOOKUP 17:42:18 Waiting for dns lookup of ns.google.com ...
30
+ 1520635339 PING ns.google.com (216.239.32.10): 56 data bytes
31
+ 1520635339 64 bytes from 216.239.32.10: icmp_seq=0 ttl=46 time=36.815 ms
32
+ 1520635340 64 bytes from 216.239.32.10: icmp_seq=1 ttl=46 time=26.418 ms
33
+ 1520635341 64 bytes from 216.239.32.10: icmp_seq=2 ttl=46 time=92.105 ms
34
+ 1520635342 64 bytes from 216.239.32.10: icmp_seq=3 ttl=46 time=151.393 ms
35
+ 1520635344 Request timeout for icmp_seq 4
36
+ 1520635345 Request timeout for icmp_seq 5
37
+ 1520635346 Request timeout for icmp_seq 6
38
+ 1520635347 Request timeout for icmp_seq 7
39
+ 1520635348 Request timeout for icmp_seq 8
40
+ 1520635350
41
+ 1520635350 --- ns.google.com ping statistics ---
42
+ 1520635350 10 packets transmitted, 4 packets received, 60.0% packet loss
43
+ 1520635350 round-trip min/avg/max/stddev = 26.418/76.683/151.393/49.838 ms
44
+ END_OF_PING
45
+ 1520635351 DNS_LOOKUP 17:42:31 Waiting for dns lookup of ns.google.com ...
46
+ 1520635352 DNS_LOOKUP 17:42:32 Waiting for dns lookup of ns.google.com ...
47
+ 1520635353 DNS_LOOKUP 17:42:33 Waiting for dns lookup of ns.google.com ...
@@ -0,0 +1,30 @@
1
+ 1520609460 PING ns.google.com (216.239.32.10): 56 data bytes
2
+ 1520609460 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=36.094 ms
3
+ 1520609461 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=28.811 ms
4
+ 1520609462 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=51.550 ms
5
+ 1520609463 64 bytes from 216.239.32.10: icmp_seq=3 ttl=44 time=43.548 ms
6
+ 1520609464 64 bytes from 216.239.32.10: icmp_seq=4 ttl=44 time=137.129 ms
7
+ 1520609465 64 bytes from 216.239.32.10: icmp_seq=5 ttl=44 time=55.223 ms
8
+ 1520609466 64 bytes from 216.239.32.10: icmp_seq=6 ttl=44 time=157.352 ms
9
+ 1520609467 64 bytes from 216.239.32.10: icmp_seq=7 ttl=44 time=32.181 ms
10
+ 1520609468 64 bytes from 216.239.32.10: icmp_seq=8 ttl=44 time=215.623 ms
11
+ 1520609469 64 bytes from 216.239.32.10: icmp_seq=9 ttl=44 time=47.139 ms
12
+ 1520609469
13
+ 1520609469 --- ns.google.com ping statistics ---
14
+ 1520609469 10 packets transmitted, 10 packets received, 0.0% packet loss
15
+ 1520609469 round-trip min/avg/max/stddev = 28.811/80.465/215.623/61.891 ms
16
+ END_OF_PING
17
+ 1520609469 PING ns.google.com (216.239.32.10): 56 data bytes
18
+ 1520609469 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=124.769 ms
19
+ 1520609470 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=121.649 ms
20
+ 1520609471 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=32.698 ms
21
+ 1520609473 ping: sendto: No route to host
22
+ 1520609473 Request timeout for icmp_seq 3
23
+ 1520609474 ping: sendto: No route to host
24
+ 1520609474 Request timeout for icmp_seq 4
25
+ 1520609475 ping: sendto: No route to host
26
+ 1520609475 Request timeout for icmp_seq 5
27
+ 1520609476 ping: sendto: No route to host
28
+ 1520609476 Request timeout for icmp_seq 6
29
+ 1520609477 ping: sendto: No route to host
30
+ 1520609477 Request timeout for icmp_seq 7
@@ -0,0 +1,24 @@
1
+ 1520610336 PING ns.google.com (216.239.32.10): 56 data bytes
2
+ 1520610336 64 bytes from 216.239.32.10: icmp_seq=0 ttl=44 time=45.126 ms
3
+ 1520610337 64 bytes from 216.239.32.10: icmp_seq=1 ttl=44 time=142.804 ms
4
+ 1520610338 64 bytes from 216.239.32.10: icmp_seq=2 ttl=44 time=34.206 ms
5
+ 1520610339 64 bytes from 216.239.32.10: icmp_seq=3 ttl=44 time=68.064 ms
6
+ 1520610340 Request timeout for icmp_seq 4
7
+ 1520610340 92 bytes from 10.128.128.128: Communication prohibited by filter
8
+ 1520610340 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
9
+ 1520610340 4 5 00 5400 6dea 0 0000 40 01 21dd 10.57.228.249 104.27.147.148
10
+ 1520610341 Request timeout for icmp_seq 5
11
+ 1520610341 92 bytes from 10.128.128.128: Communication prohibited by filter
12
+ 1520610341 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
13
+ 1520610341 4 5 00 5400 6dea 0 0000 40 01 21dd 10.57.228.249 104.27.147.148
14
+ 1520610342 Request timeout for icmp_seq 6
15
+ 1520610342 92 bytes from 10.128.128.128: Communication prohibited by filter
16
+ 1520610342 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
17
+ 1520610342 4 5 00 5400 6dea 0 0000 40 01 21dd 10.57.228.249 104.27.147.148
18
+ 1520610343 Request timeout for icmp_seq 7
19
+ 1520610343 92 bytes from 10.128.128.128: Communication prohibited by filter
20
+ 1520610343 Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
21
+ 1520610343 4 5 00 5400 6dea 0 0000 40 01 21dd 10.57.228.249 104.27.147.148
22
+ 1520610344 64 bytes from 216.239.32.10: icmp_seq=8 ttl=44 time=184.792 ms
23
+ 1520610345 64 bytes from 216.239.32.10: icmp_seq=9 ttl=44 time=103.312 ms
24
+ 1520610346 64 bytes from 216.239.32.10: icmp_seq=10 ttl=44 time=61.582 ms
@@ -0,0 +1,11 @@
1
+ 09:47:38 ping: cannot resolve ns.google.com: Unknown host
2
+ PING ns.google.com (216.239.32.10): 56 data bytes
3
+
4
+ Time Ping Run Mode Failed Round Trip
5
+ ----- ---- ---- ---- ------ ----------
6
+ 09:47 10 10 good 0.0% 54.45 ms
7
+ 09:47 10 5 good 50.0% 76.66 ms
8
+ 09:48:06 ping: cannot resolve ns.google.com: Unknown host
9
+ 09:48 10 10 good 0.0% 72.06 ms
10
+ 09:48 10 3 good 70.0% 82.17 ms
11
+ 09:48:34 ping: cannot resolve ns.google.com: Unknown host
@@ -0,0 +1,6 @@
1
+ PING ns.google.com (216.239.32.10): 56 data bytes
2
+
3
+ Time Ping Run Mode Failed Round Trip
4
+ ----- ---- ---- ---- ------ ----------
5
+ 10:31 10 10 good 0.0% 80.47 ms
6
+ 10:31 8 5 fail 62.5% 32.70 ms
@@ -0,0 +1,7 @@
1
+ PING ns.google.com (216.239.32.10): 56 data bytes
2
+
3
+ Time Ping Run Mode Failed Round Trip
4
+ ----- ---- ---- ---- ------ ----------
5
+ 10:45 5 1 fail 20.0% 68.06 ms
6
+ 10:45:43 92 bytes from 10.128.128.128: Communication prohibited by filter
7
+ 10:45 11 3 good 36.4% 61.58 ms
data/test/run_tests ADDED
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+
3
+ dir=`dirname $0`
4
+ wifiwatch="$dir/../bin/wifi-watch"
5
+ ping_logs="$dir/ping_logs"
6
+ expected="$dir/expected"
7
+ results="$dir/results"
8
+
9
+ tests=0
10
+ fail=0
11
+ mkdir -p $results
12
+ rm -f $results/*
13
+
14
+ echo
15
+ for test_path in $ping_logs/*.log; do
16
+ test_name=`basename $test_path .log`
17
+
18
+ echo -n "Running $test_name ... "
19
+ $wifiwatch --debug-from $test_path >$results/$test_name.out
20
+ tests=$(expr $tests + 1)
21
+
22
+ if cmp -s $expected/$test_name.out $results/$test_name.out; then
23
+ echo "Success!"
24
+ else
25
+ fail=$(expr $fail + 1)
26
+ echo "Failed!"
27
+ echo "diff $expected/$test_name.out $results/$test_name.out"
28
+ diff $expected/$test_name.out $results/$test_name.out
29
+ echo
30
+ fi
31
+
32
+ done
33
+
34
+ echo
35
+ echo "$tests tests, $fail errors"
36
+ echo
37
+
38
+ [ "$fail" = 0 ]
39
+
@@ -0,0 +1,17 @@
1
+
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "wifi-watch"
4
+ spec.version = "1.0.0"
5
+ spec.authors = ["John Gorman"]
6
+ spec.email = ["johngorman2@gmail.com"]
7
+
8
+ spec.summary = %q{Continuously monitor your network speed and quality!}
9
+ spec.description = %q{Run wifi-watch in a terminal so that you can easily check your network quality at this moment and how it has been holding up since you began recording hours or days ago.}
10
+ spec.homepage = "https://github.com/jgorman/wifi-watch"
11
+ spec.license = "MIT"
12
+
13
+ spec.files = `git ls-files`.split
14
+ spec.bindir = "bin"
15
+ spec.executables = ["wifi-watch"]
16
+ spec.require_paths = ["lib"]
17
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wifi-watch
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Gorman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Run wifi-watch in a terminal so that you can easily check your network
14
+ quality at this moment and how it has been holding up since you began recording
15
+ hours or days ago.
16
+ email:
17
+ - johngorman2@gmail.com
18
+ executables:
19
+ - wifi-watch
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - ".gitignore"
24
+ - Gemfile
25
+ - LICENSE.txt
26
+ - README.md
27
+ - Rakefile
28
+ - bin/wifi-watch
29
+ - test/expected/dns-down.out
30
+ - test/expected/dns-slow.out
31
+ - test/expected/fail-mode.out
32
+ - test/expected/wifi-login.out
33
+ - test/ping_logs/dns-down.log
34
+ - test/ping_logs/dns-slow.log
35
+ - test/ping_logs/fail-mode.log
36
+ - test/ping_logs/wifi-login.log
37
+ - test/results/dns-down.out
38
+ - test/results/fail-mode.out
39
+ - test/results/wifi-login.out
40
+ - test/run_tests
41
+ - wifi-watch.gemspec
42
+ homepage: https://github.com/jgorman/wifi-watch
43
+ licenses:
44
+ - MIT
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 2.4.5.4
63
+ signing_key:
64
+ specification_version: 4
65
+ summary: Continuously monitor your network speed and quality!
66
+ test_files: []