wifi-wand 2.19.1 → 2.20.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9da3f2d69b3deb5046f7ea3394a43235733d9784c41bf372febdcca09c5d15d
4
- data.tar.gz: 63f83f663cb0ad11f8fe5087aeda730e8dcd4a5108dad4b84c653d37cd2cd21e
3
+ metadata.gz: f6064b0904166cac0ccc9768c6bd385f422616d42418e6c42db8f38235fde354
4
+ data.tar.gz: 07a0a469d659dd82a5fbb80562dfbef16629aa2344ca22134e1f92c585717cac
5
5
  SHA512:
6
- metadata.gz: 0be501742d8ad2e8ac317bf622b6f448af53293a8b90e563768aba12cf49a79488b3e8897928300be1150c6d021aa531c2fb809db0e9ff1346813268b347693c
7
- data.tar.gz: a645d6e65afb64c19bbca0dd3443fc1b92067084897384df8da330df876093bfd5906b754dc18826b59810aeab65050dc9a64918692a4f291361ada7f87a9b2c
6
+ metadata.gz: 4366219cfc3d754a69f21055ee489e2e458d7d969f6103353b203acbf8bc2d3419389288e90dc039c350f77bb8dbe90d8821e61e884fa8098483036810a7f9eb
7
+ data.tar.gz: cd4fe96013c357f5cea0e09d740ef723a460c046b0f8f48d2726b957675e87f305455a6f46f91d38d50b49c27ba87c8a7b7cdb39c55333a02e60cd689b0dc1b7
data/RELEASE_NOTES.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## v2.20.0
2
+
3
+ * Change detect_wifi_interface and available_network_names to use system_profiler JSON output.
4
+ * Previously, detect_wifi_interface parsed human readable text; parsing JSON is more reliable.
5
+ * Previously, available_network_names used Swift and CoreLAN and required XCode installation.
6
+
7
+
1
8
  ## v2.19.1
2
9
 
3
10
  * Fix connected_network_name when wifi is on but no network is connected.
@@ -219,9 +219,17 @@ When in interactive shell mode:
219
219
  if post_processor
220
220
  puts post_processor.(info)
221
221
  else
222
- puts model.wifi_on? \
223
- ? "Available networks are:\n\n#{fancy_string(info)}" \
224
- : "Wifi is off, cannot see available networks."
222
+ message = if model.wifi_on?
223
+ <<~MESSAGE
224
+ Available networks, in descending signal strength order,
225
+ and not including any currently connected network, are:
226
+
227
+ #{fancy_string(info)}"
228
+ MESSAGE
229
+ else
230
+ "Wifi is off, cannot see available networks."
231
+ end
232
+ puts message
225
233
  end
226
234
  end
227
235
  end
@@ -14,17 +14,16 @@ class BaseModel
14
14
  def initialize(options)
15
15
  @verbose_mode = options.verbose
16
16
 
17
- if options.wifi_interface && (! is_wifi_interface?(options.wifi_interface))
18
- raise Error.new("#{options.wifi_interface} is not a Wi-Fi interface.")
17
+ if options.wifi_interface
18
+ if is_wifi_interface?(options.wifi_interface)
19
+ @wifi_interface = options.wifi_interface
20
+ else
21
+ raise Error.new("#{options.wifi_interface} is not a Wi-Fi interface.")
22
+ end
19
23
  end
20
- @wifi_interface = options.wifi_interface
21
24
  end
22
25
 
23
-
24
-
25
-
26
26
  def run_os_command(command, raise_on_error = true)
27
-
28
27
  if verbose_mode
29
28
  puts CommandOutputFormatter.command_attempt_as_string(command)
30
29
  end
@@ -46,16 +45,15 @@ class BaseModel
46
45
 
47
46
 
48
47
  # This method returns whether or not there is a working Internet connection,
49
- # which is defined as name resolution and HTTP get being successful.
50
- # Domains attempted are google.com and baidu.com. Success is either being successful.
48
+ # which is defined as success for both name resolution and an HTTP get.
49
+ # Domains attempted are google.com and baidu.com.
50
+ # Success is defined as either being successful.
51
51
  # Commands for the multiple sites are run in parallel, in threads, to save time.
52
52
  def connected_to_internet?
53
- return nil unless wifi_on? # no need to try
53
+ return false unless wifi_on? # no need to try
54
54
 
55
55
  # We cannot use run_os_command for the running of external processes here,
56
56
  # because they are multithreaded, and the output will get mixed up.
57
-
58
- # First pass to fail quickly if name resolving does not work.
59
57
  test_using_dig = -> do
60
58
  domains = %w(google.com baidu.com)
61
59
  puts "Calling dig on domains #{domains}..." if verbose_mode
@@ -185,8 +183,8 @@ class BaseModel
185
183
  # @param wait_interval_in_secs sleeps this interval between retries; if nil or absent,
186
184
  # a default will be provided
187
185
  #
186
+ # Connected is defined as being able to connect to an external web site.
188
187
  def till(target_status, wait_interval_in_secs = nil)
189
-
190
188
  # One might ask, why not just put the 0.5 up there as the default argument.
191
189
  # We could do that, but we'd still need the line below in case nil
192
190
  # was explicitly specified. The default argument of nil above emphasizes that
@@ -217,7 +215,7 @@ class BaseModel
217
215
  # Tries an OS command until the stop condition is true.
218
216
  # @command the command to run in the OS
219
217
  # @stop_condition a lambda taking the command's stdout as its sole parameter
220
- # @return the stdout produced by the command
218
+ # @return the stdout produced by the command, or nil if max_tries was reached
221
219
  def try_os_command_until(command, stop_condition, max_tries = 100)
222
220
 
223
221
  report_attempt_count = ->(attempt_count) do
@@ -225,10 +223,10 @@ class BaseModel
225
223
  end
226
224
 
227
225
  max_tries.times do |n|
228
- stdout = run_os_command(command)
229
- if stop_condition.(stdout)
226
+ stdout_text = run_os_command(command)
227
+ if stop_condition.(stdout_text)
230
228
  report_attempt_count.(n + 1)
231
- return stdout
229
+ return stdout_text
232
230
  end
233
231
  end
234
232
 
@@ -16,7 +16,7 @@ class MacOsModel < BaseModel
16
16
 
17
17
  # Identifies the (first) wireless network hardware interface in the system, e.g. en0 or en1
18
18
  # This may not detect wifi ports with nonstandard names, such as USB wifi devices.
19
- def detect_wifi_interface
19
+ def detect_wifi_interface_using_networksetup
20
20
 
21
21
  lines = run_os_command("networksetup -listallhardwareports").split("\n")
22
22
  # Produces something like this:
@@ -39,10 +39,34 @@ class MacOsModel < BaseModel
39
39
  end
40
40
  end
41
41
 
42
+ # Identifies the (first) wireless network hardware interface in the system, e.g. en0 or en1
43
+ # This may not detect wifi ports with nonstandard names, such as USB wifi devices.
44
+ def detect_wifi_interface
45
+ json_text = run_os_command('system_profiler -json SPNetworkDataType')
46
+ net_data = JSON.parse(json_text)
47
+ nets = net_data['SPNetworkDataType']
48
+ wifi = nets.detect { |net| net['_name'] == 'Wi-Fi'}
49
+ wifi['interface']
50
+ end
51
+
52
+ # Returns the network names sorted in descending order of signal strength.
42
53
  def available_network_names
43
54
  return nil unless wifi_on? # no need to try
44
55
 
45
- run_swift_command('AvailableWifiNetworkLister').split("\n")
56
+ # run_swift_command('AvailableWifiNetworkLister').split("\n").uniq
57
+
58
+ json_text = run_os_command('system_profiler -json SPAirPortDataType')
59
+ data = JSON.parse(json_text)
60
+
61
+ inner_key = connected_network_name ? 'spairport_airport_other_local_wireless_networks' : 'spairport_airport_local_wireless_networks'
62
+
63
+ nets = data['SPAirPortDataType'] \
64
+ .detect { |h| h.key?('spairport_airport_interfaces') } \
65
+ ['spairport_airport_interfaces'] \
66
+ .detect { |h| h['_name'] == wifi_interface } \
67
+ [inner_key] \
68
+ .sort_by { |net| -net['spairport_signal_noise'].split('/').first.to_i }
69
+ nets.map { |h| h['_name']}.uniq
46
70
  end
47
71
 
48
72
 
@@ -1,3 +1,3 @@
1
1
  module WifiWand
2
- VERSION = '2.19.1' unless defined?(VERSION)
2
+ VERSION = '2.20.0' unless defined?(VERSION)
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wifi-wand
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.19.1
4
+ version: 2.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith Bennett