Class: WifiWand::MacOsModel
- Defined in:
- lib/wifi-wand/models/mac_os_model.rb
Instance Attribute Summary
Attributes inherited from BaseModel
#verbose_mode, #wifi_interface
Instance Method Summary collapse
- #available_network_names ⇒ Object
-
#connected_network_name ⇒ Object
Returns the network currently connected to, or nil if none.
-
#detect_wifi_interface ⇒ Object
Identifies the (first) wireless network hardware interface in the system, e.g.
-
#disconnect ⇒ Object
Disconnects from the currently connected network.
- #ensure_swift_and_corewlan_present ⇒ Object
-
#initialize(options = OpenStruct.new) ⇒ MacOsModel
constructor
Takes an OpenStruct containing options such as verbose mode and interface name.
-
#ip_address ⇒ Object
Returns the IP address assigned to the wifi interface, or nil if none.
-
#is_wifi_interface?(interface) ⇒ Boolean
Returns whether or not the specified interface is a WiFi interface.
-
#mac_address ⇒ Object
TODO: Add capability to change the MAC address using a command in the form of: sudo ifconfig en0 ether aa:bb:cc:dd:ee:ff However, the MAC address will be set to the real hardware address on restart.
- #nameservers_using_networksetup ⇒ Object
-
#nameservers_using_resolv_conf ⇒ Object
Though this is strictly not OS-agnostic, it will be used by most OS’s, and can be overridden by subclasses (e.g. Windows).
- #nameservers_using_scutil ⇒ Object
- #open_application(application_name) ⇒ Object
- #open_resource(resource_url) ⇒ Object
-
#os_level_connect(network_name, password = nil) ⇒ Object
This method is called by BaseModel#connect to do the OS-specific connection logic.
-
#os_level_preferred_network_password(preferred_network_name) ⇒ Object
@return: If the network is in the preferred networks list If a password is associated w/this network, return the password If not, return nil else raise an error.
-
#preferred_networks ⇒ Object
Returns data pertaining to “preferred” networks, many/most of which will probably not be available.
- #remove_preferred_network(network_name) ⇒ Object
- #run_swift_command(basename) ⇒ Object
- #set_nameservers(nameservers) ⇒ Object
- #swift_and_corewlan_present? ⇒ Boolean
-
#wifi_info ⇒ Object
Returns some useful wifi-related information.
-
#wifi_off ⇒ Object
Turns wifi off.
-
#wifi_on ⇒ Object
Turns wifi on.
-
#wifi_on? ⇒ Boolean
Returns true if wifi is on, else false.
Methods inherited from BaseModel
#connect, #connected_to?, #connected_to_internet?, #cycle_network, #preferred_network_password, #public_ip_address_info, #random_mac_address, #remove_preferred_networks, #run_os_command, #till, #try_os_command_until
Constructor Details
#initialize(options = OpenStruct.new) ⇒ MacOsModel
Takes an OpenStruct containing options such as verbose mode and interface name.
13 14 15 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 13 def initialize( = OpenStruct.new) super end |
Instance Method Details
#available_network_names ⇒ Object
42 43 44 45 46 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 42 def available_network_names return nil unless wifi_on? # no need to try run_swift_command('AvailableWifiNetworkLister').split("\n") end |
#connected_network_name ⇒ Object
Returns the network currently connected to, or nil if none.
151 152 153 154 155 156 157 158 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 151 def connected_network_name return nil unless wifi_on? # no need to try command_output = run_os_command("networksetup -getairportnetwork #{wifi_interface}") connected_prefix = 'Current Wi-Fi Network: ' connected = Regexp.new(connected_prefix).match?(command_output) connected ? command_output.split(connected_prefix).last.chomp : nil end |
#detect_wifi_interface ⇒ Object
Identifies the (first) wireless network hardware interface in the system, e.g. en0 or en1 This may not detect wifi ports with nonstandard names, such as USB wifi devices.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 19 def detect_wifi_interface lines = run_os_command("networksetup -listallhardwareports").split("\n") # Produces something like this: # Hardware Port: Wi-Fi # Device: en0 # Ethernet Address: ac:bc:32:b9:a9:9d # # Hardware Port: Bluetooth PAN # Device: en3 # Ethernet Address: ac:bc:32:b9:a9:9e wifi_interface_line_num = (0...lines.size).detect do |index| /: Wi-Fi$/.match(lines[index]) end if wifi_interface_line_num.nil? raise Error.new(%Q{Wifi interface (e.g. "en0") not found in output of: networksetup -listallhardwareports}) else lines[wifi_interface_line_num + 1].split(': ').last end end |
#disconnect ⇒ Object
Disconnects from the currently connected network. Does not turn off wifi.
162 163 164 165 166 167 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 162 def disconnect return nil unless wifi_on? # no need to try run_swift_command('WifiNetworkDisconecter') nil end |
#ensure_swift_and_corewlan_present ⇒ Object
296 297 298 299 300 301 302 303 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 296 def ensure_swift_and_corewlan_present unless swift_and_corewlan_present? raise RuntimeError, <<~MESSAGE Swift and/or CoreWLAN are not present and are needed by this task. This can be fixed by installing XCode. MESSAGE end end |
#ip_address ⇒ Object
Returns the IP address assigned to the wifi interface, or nil if none.
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 129 def ip_address return nil unless wifi_on? # no need to try begin run_os_command("ipconfig getifaddr #{wifi_interface}").chomp rescue OsCommandError => error if error.exitstatus == 1 nil else raise end end end |
#is_wifi_interface?(interface) ⇒ Boolean
Returns whether or not the specified interface is a WiFi interface.
65 66 67 68 69 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 65 def is_wifi_interface?(interface) run_os_command("networksetup -listpreferredwirelessnetworks #{interface} 2>/dev/null") exit_status = $?.exitstatus exit_status != 10 end |
#mac_address ⇒ Object
TODO: Add capability to change the MAC address using a command in the form of:
sudo ifconfig en0 ether aa:bb:cc:dd:ee:ff
However, the MAC address will be set to the real hardware address on restart. One way to implement this is to have an optional address argument, then this method returns the current address if none is provided, but sets to the specified address if it is.
176 177 178 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 176 def mac_address run_os_command("ifconfig #{wifi_interface} | awk '/ether/{print $2}'").chomp end |
#nameservers_using_networksetup ⇒ Object
288 289 290 291 292 293 294 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 288 def nameservers_using_networksetup output = run_os_command("networksetup -getdnsservers Wi-Fi") if output == "There aren't any DNS Servers set on Wi-Fi.\n" output = '' end output.split("\n") end |
#nameservers_using_resolv_conf ⇒ Object
Though this is strictly not OS-agnostic, it will be used by most OS’s, and can be overridden by subclasses (e.g. Windows).
270 271 272 273 274 275 276 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 270 def nameservers_using_resolv_conf begin File.readlines('/etc/resolv.conf').grep(/^nameserver /).map { |line| line.split.last } rescue Errno::ENOENT nil end end |
#nameservers_using_scutil ⇒ Object
279 280 281 282 283 284 285 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 279 def nameservers_using_scutil output = run_os_command('scutil --dns') nameserver_lines_scoped_and_unscoped = output.split("\n").grep(/^\s*nameserver\[/) unique_nameserver_lines = nameserver_lines_scoped_and_unscoped.uniq # take the union nameservers = unique_nameserver_lines.map { |line| line.split(' : ').last.strip } nameservers end |
#open_application(application_name) ⇒ Object
241 242 243 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 241 def open_application(application_name) run_os_command('open -a ' + application_name) end |
#open_resource(resource_url) ⇒ Object
246 247 248 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 246 def open_resource(resource_url) run_os_command('open ' + resource_url) end |
#os_level_connect(network_name, password = nil) ⇒ Object
This method is called by BaseModel#connect to do the OS-specific connection logic.
99 100 101 102 103 104 105 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 99 def os_level_connect(network_name, password = nil) command = "networksetup -setairportnetwork #{wifi_interface} #{Shellwords.shellescape(network_name)}" if password command << ' ' << Shellwords.shellescape(password) end run_os_command(command) end |
#os_level_preferred_network_password(preferred_network_name) ⇒ Object
@return:
If the network is in the preferred networks list
If a password is associated w/this network, return the password
If not, return nil
else
raise an error
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 114 def os_level_preferred_network_password(preferred_network_name) command = %Q{security find-generic-password -D "AirPort network password" -a "#{preferred_network_name}" -w 2>&1} begin return run_os_command(command).chomp rescue OsCommandError => error if error.exitstatus == 44 # network has no password stored nil else raise end end end |
#preferred_networks ⇒ Object
Returns data pertaining to “preferred” networks, many/most of which will probably not be available.
50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 50 def preferred_networks lines = run_os_command("networksetup -listpreferredwirelessnetworks #{wifi_interface}").split("\n") # Produces something like this, unsorted, and with leading tabs: # Preferred networks on en0: # LibraryWiFi # @thePAD/Magma lines.delete_at(0) # remove title line lines.map! { |line| line.gsub("\t", '') } # remove leading tabs lines.sort! { |s1, s2| s1.casecmp(s2) } # sort alphabetically, case insensitively lines end |
#remove_preferred_network(network_name) ⇒ Object
143 144 145 146 147 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 143 def remove_preferred_network(network_name) network_name = network_name.to_s run_os_command("sudo networksetup -removepreferredwirelessnetwork " + "#{wifi_interface} #{Shellwords.shellescape(network_name)}") end |
#run_swift_command(basename) ⇒ Object
309 310 311 312 313 314 315 316 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 309 def run_swift_command(basename) ensure_swift_and_corewlan_present swift_filespec = File.join( File.dirname(__FILE__), "../../../swift/#{basename}.swift" ) command = "swift #{swift_filespec}" run_os_command(command) end |
#set_nameservers(nameservers) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 216 def set_nameservers(nameservers) arg = if nameservers == :clear 'empty' else bad_addresses = nameservers.reject do |ns| begin IPAddr.new(ns).ipv4? true rescue => e puts e false end end unless bad_addresses.empty? raise Error.new("Bad IP addresses provided: #{bad_addresses.join(', ')}") end nameservers.join(' ') end # end assignment to arg variable run_os_command("networksetup -setdnsservers Wi-Fi #{arg}") nameservers end |
#swift_and_corewlan_present? ⇒ Boolean
305 306 307 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 305 def swift_and_corewlan_present? system("swift -e 'import CoreWLAN' >/dev/null 2>&1") end |
#wifi_info ⇒ Object
Returns some useful wifi-related information.
182 183 184 185 186 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 213 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 182 def wifi_info connected = begin connected_to_internet? rescue false end info = { 'wifi_on' => wifi_on?, 'internet_on' => connected, 'interface' => wifi_interface, 'network' => connected_network_name, 'ip_address' => ip_address, 'mac_address' => mac_address, 'nameservers' => nameservers_using_scutil, 'timestamp' => Time.now, } if info['internet_on'] begin info['public_ip'] = public_ip_address_info rescue => e puts <<~MESSAGE #{e.class} obtaining public IP address info, proceeding with everything else. Error message: #{e} MESSAGE end end info end |
#wifi_off ⇒ Object
Turns wifi off.
89 90 91 92 93 94 95 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 89 def wifi_off return unless wifi_on? run_os_command("networksetup -setairportpower #{wifi_interface} off") wifi_on? ? Error.new(raise("Wifi could not be disabled.")) : nil end |
#wifi_on ⇒ Object
Turns wifi on.
80 81 82 83 84 85 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 80 def wifi_on return if wifi_on? run_os_command("networksetup -setairportpower #{wifi_interface} on") wifi_on? ? nil : Error.new(raise("Wifi could not be enabled.")) end |
#wifi_on? ⇒ Boolean
Returns true if wifi is on, else false.
73 74 75 76 |
# File 'lib/wifi-wand/models/mac_os_model.rb', line 73 def wifi_on? output = run_os_command("networksetup -getairportpower #{wifi_interface}") output.chomp.match?(/\): On$/) end |