Class: WifiWand::BaseModel
- Inherits:
-
Object
- Object
- WifiWand::BaseModel
- Defined in:
- lib/wifi-wand/models/base_model.rb
Direct Known Subclasses
Defined Under Namespace
Classes: OsCommandError
Instance Attribute Summary collapse
-
#verbose_mode ⇒ Object
Returns the value of attribute verbose_mode.
-
#wifi_interface ⇒ Object
Returns the value of attribute wifi_interface.
Instance Method Summary collapse
-
#connect(network_name, password = nil) ⇒ Object
Connects to the passed network name, optionally with password.
- #connected_to?(network_name) ⇒ Boolean
-
#connected_to_internet? ⇒ Boolean
This method returns whether or not there is a working Internet connection, which is defined as success for both name resolution and an HTTP get.
-
#cycle_network ⇒ Object
Turns wifi off and then on, reconnecting to the originally connecting network.
-
#initialize(options) ⇒ BaseModel
constructor
A new instance of BaseModel.
- #preferred_network_password(preferred_network_name) ⇒ Object
-
#public_ip_address_info ⇒ Object
Reaches out to ipinfo.io to get public IP address information in the form of a hash.
- #random_mac_address ⇒ Object
-
#remove_preferred_networks(*network_names) ⇒ Object
Removes the specified network(s) from the preferred network list.
- #run_os_command(command, raise_on_error = true) ⇒ Object
-
#till(target_status, wait_interval_in_secs = nil) ⇒ Object
Waits for the Internet connection to be in the desired state.
-
#try_os_command_until(command, stop_condition, max_tries = 100) ⇒ Object
Tries an OS command until the stop condition is true.
Constructor Details
#initialize(options) ⇒ BaseModel
Returns a new instance of BaseModel.
14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/wifi-wand/models/base_model.rb', line 14 def initialize() @verbose_mode = .verbose if .wifi_interface if is_wifi_interface?(.wifi_interface) @wifi_interface = .wifi_interface else raise Error.new("#{.wifi_interface} is not a Wi-Fi interface.") end end end |
Instance Attribute Details
#verbose_mode ⇒ Object
Returns the value of attribute verbose_mode.
12 13 14 |
# File 'lib/wifi-wand/models/base_model.rb', line 12 def verbose_mode @verbose_mode end |
#wifi_interface ⇒ Object
Returns the value of attribute wifi_interface.
12 13 14 |
# File 'lib/wifi-wand/models/base_model.rb', line 12 def wifi_interface @wifi_interface end |
Instance Method Details
#connect(network_name, password = nil) ⇒ Object
Connects to the passed network name, optionally with password. Turns wifi on first, in case it was turned off. Relies on subclass implementation of os_level_connect().
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 |
# File 'lib/wifi-wand/models/base_model.rb', line 132 def connect(network_name, password = nil) # Allow symbols and anything responding to to_s for user convenience network_name = network_name.to_s if network_name password = password.to_s if password if network_name.nil? || network_name.empty? raise Error.new("A network name is required but was not provided.") end wifi_on os_level_connect(network_name, password) # Verify that the network is now connected: actual_network_name = connected_network_name unless actual_network_name == network_name = %Q{Expected to connect to "#{network_name}" but } if actual_network_name.nil? || actual_network_name.empty? << "unable to connect to any network." else << %Q{connected to "#{connected_network_name}" instead.} end << ' Did you ' << (password ? "provide the correct password?" : "need to provide a password?") raise Error.new() end nil end |
#connected_to?(network_name) ⇒ Boolean
124 125 126 |
# File 'lib/wifi-wand/models/base_model.rb', line 124 def connected_to?(network_name) network_name == connected_network_name end |
#connected_to_internet? ⇒ Boolean
This method returns whether or not there is a working Internet connection, which is defined as success for both name resolution and an HTTP get. Domains attempted are google.com and baidu.com. Success is defined as either being successful. Commands for the multiple sites are run in parallel, in threads, to save time.
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 |
# File 'lib/wifi-wand/models/base_model.rb', line 52 def connected_to_internet? return false unless wifi_on? # no need to try # We cannot use run_os_command for the running of external processes here, # because they are multithreaded, and the output will get mixed up. test_using_dig = -> do domains = %w(google.com baidu.com) puts "Calling dig on domains #{domains}..." if verbose_mode threads = domains.map do |domain| Thread.new do output = `dig +short #{domain}` output.length > 0 end end threads.each(&:join) values = threads.map(&:value) success = values.include?(true) puts "Results of dig: success == #{success}, values were #{values}." if verbose_mode success end test_using_http_get = -> do test_sites = %w{https://www.google.com http://baidu.com} puts "Calling HTTP.get on sites #{test_sites}..." if verbose_mode threads = test_sites.map do |site| Thread.new do url = URI.parse(site) success = true start = Time.now begin Net::HTTP.start(url.host) do |http| http.read_timeout = 3 # seconds http.get('.') puts "Finished HTTP get #{url.host} in #{Time.now - start} seconds" if verbose_mode end rescue => e puts "Got error for host #{url.host} in #{Time.now - start} seconds:\n#{e.inspect}" if verbose_mode success = false end success end end threads.each(&:join) values = threads.map(&:value) success = values.include?(true) puts "Results of HTTP.get: success == #{success}, values were #{values}." if verbose_mode success end test_using_dig.() && test_using_http_get.() end |
#cycle_network ⇒ Object
Turns wifi off and then on, reconnecting to the originally connecting network.
113 114 115 116 117 118 119 120 121 |
# File 'lib/wifi-wand/models/base_model.rb', line 113 def cycle_network # TODO: Make this network name saving and restoring conditional on it not having a password. # If the disabled code below is enabled, an error will be raised if a password is required, # even though it is stored. # network_name = connected_network_name wifi_off wifi_on # connect(network_name) if network_name end |
#preferred_network_password(preferred_network_name) ⇒ Object
171 172 173 174 175 176 177 178 |
# File 'lib/wifi-wand/models/base_model.rb', line 171 def preferred_network_password(preferred_network_name) preferred_network_name = preferred_network_name.to_s if preferred_networks.include?(preferred_network_name) os_level_preferred_network_password(preferred_network_name) else raise Error.new("Network #{preferred_network_name} not in preferred networks list.") end end |
#public_ip_address_info ⇒ Object
Reaches out to ipinfo.io to get public IP address information in the form of a hash. You may need to enclose this call in a begin/rescue.
241 242 243 |
# File 'lib/wifi-wand/models/base_model.rb', line 241 def public_ip_address_info JSON.parse(`curl -s ipinfo.io`) end |
#random_mac_address ⇒ Object
246 247 248 249 250 |
# File 'lib/wifi-wand/models/base_model.rb', line 246 def random_mac_address bytes = Array.new(6) { rand(256) } chars = bytes.map { |b| "%02x" % b } chars.join(':') end |
#remove_preferred_networks(*network_names) ⇒ Object
Removes the specified network(s) from the preferred network list.
164 165 166 167 168 |
# File 'lib/wifi-wand/models/base_model.rb', line 164 def remove_preferred_networks(*network_names) network_names = network_names.first if network_names.first.is_a?(Array) && network_names.size == 1 networks_to_remove = network_names & preferred_networks # exclude any nonexistent networks networks_to_remove.each { |name| remove_preferred_network(name) } end |
#run_os_command(command, raise_on_error = true) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/wifi-wand/models/base_model.rb', line 26 def run_os_command(command, raise_on_error = true) if verbose_mode puts CommandOutputFormatter.command_attempt_as_string(command) end start_time = Time.now output = `#{command} 2>&1` # join stderr with stdout if verbose_mode puts "Duration: #{'%.4f' % [Time.now - start_time]} seconds" puts CommandOutputFormatter.command_result_as_string(output) end if $?.exitstatus != 0 && raise_on_error raise OsCommandError.new($?.exitstatus, command, output) end output end |
#till(target_status, wait_interval_in_secs = nil) ⇒ Object
Waits for the Internet connection to be in the desired state. Connected is defined as being able to connect to an external web site.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/wifi-wand/models/base_model.rb', line 187 def till(target_status, wait_interval_in_secs = nil) # One might ask, why not just put the 0.5 up there as the default argument. # We could do that, but we'd still need the line below in case nil # was explicitly specified. The default argument of nil above emphasizes that # the absence of an argument and a specification of nil will behave identically. wait_interval_in_secs ||= 0.5 finished_predicates = { conn: -> { connected_to_internet? }, disc: -> { ! connected_to_internet? }, on: -> { wifi_on? }, off: -> { ! wifi_on? } } finished_predicate = finished_predicates[target_status] if finished_predicate.nil? raise ArgumentError.new( "Option must be one of #{finished_predicates.keys.inspect}. Was: #{target_status.inspect}") end loop do return if finished_predicate.() sleep(wait_interval_in_secs) end end |
#try_os_command_until(command, stop_condition, max_tries = 100) ⇒ Object
Tries an OS command until the stop condition is true.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/wifi-wand/models/base_model.rb', line 219 def try_os_command_until(command, stop_condition, max_tries = 100) report_attempt_count = ->(attempt_count) do puts "Command was executed #{attempt_count} time(s)." if verbose_mode end max_tries.times do |n| stdout_text = run_os_command(command) if stop_condition.(stdout_text) report_attempt_count.(n + 1) return stdout_text end end report_attempt_count.(max_tries) nil end |