wifi-watch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []