When someone gets a new MacBook, stuff like dropping the WiFi signal can kill the vibe. It actually killed me for over 6 or 7 months when my new internet was connected in. The providers changed my router, checked the network and did everything they could but couldn’t fix the machine. I am pretty sure that it interferes with something on the same frequency but because of the amount of electrical devices at home, I never had so much time to ‘debug’ why it happens.
Thank you, MacBook
I bought myself a new work machine - which was actually my first Apple device ever - some days before Christmas. It was a shiny, thin MacBook Air. But out of all features this is not even close to being the best features. The killer feature in any MacBook is their Hardware API that Apple publishes, edits and expands online daily.
So after 2 days of playing around with my Mac, configuring my developer environment, learning keyboard shortcuts I discovered this documentation and immediately searched for WiFi. For all the joy people can have, it was there, shining bright and well-documented. With CWInterface Class Reference you have complete control over most parts of your connection.
The building
After I found this, I knew I must solve my WiFi issue and do what I usually do, reconnect or turn my signal on and then off. So I started thinking about how to approach this and came up with this script that I will detail later on:
#!/usr/bin/python
from AppKit import CWInterface
import socket
import time
from urllib2 import urlopen, URLError, HTTPError
starttime=time.time()
def reConnect():
iface = CWInterface.interface()
iface.setPower_error_(False, None)
iface.setPower_error_(True, None)
print "your wifi should work now!"
def wifiCorrect():
socket.setdefaulttimeout( 0.2 )
url = 'http://google.com/'
try :
response = urlopen( url )
except HTTPError, e:
print 'The server couldn\'t fulfill the request. Reason:', str(e.code)
except URLError, e:
print 'We failed to reach a server. Reason:', str(e.reason)
reConnect()
except socket.timeout as e:
reConnect()
else :
print 'got response!'
while True:
wifiCorrect()
time.sleep(10.0 - ((time.time() - starttime) % 10.0))
After this, you can just get into the directory with your Terminal, and run python yourfilename.py
where yourfilename.py is the name of the saved file that holds your script.
What does this thing do?
If you just want the solution, there you have it, but for people who are a bit more curious and want to learn in-depth about the program, I will detail it in this section.
The first very important thing is from AppKit import CWInterface
.
Here we import the CWInterface module from the native C-compatible API library, and I actually had to go through some pains to hack around with its syntax, but we will see that later.
We import a bunch of other things, including ping
, which helps us ping a server ( I am not using it in this version, but I left it in because it might be there in an updated version ) , socket
for creating socket connections between your device and the server, time
to be able to run this script every ‘n’ seconds and some urllib2
modules which if you don’t have pre-installed, you can install it with sudo pip install urllib2
I also start a timer to keep track of the elapsed 10 seconds when I need to run the timer again.
I also define 2 functions─let’s go on with the bottom one first: wifiCorrect
is not the most appropriate name, probably because it does not directly correct WiFi, it tries to ping google.com and if it fails because of my net, it calls an other function called reConnect
which is doing the magic over here.
In wifiCorrect
, I call socket.setdefaulttimeout( 0.2 )
which is basically the timeout of the connection in seconds (avarage response time should be around 10-40 ms so 200ms is a lot for this, but I left it like that so it won’t qualify super slow internet as frozen internet.)
Some of the error explanations:
- HTTPError is basically not the wifi’s fault, there are some problems with Google
- URLError is the most common error that I get when it can’t resolve the host. My wifi is not fully disconnected, but does not send any signals at all
- socket.timeout is the 200ms socket timeout we set before (0.2 seconds) and it also happens a lot.
reConnect()
I told you that reConnect
function holds the magic and yes. This is the section that can be 100 lines on a Linux depending on the hardware, and as for Windows… I don’t even know why people code Python in Windows because it is most likely a bad practice every time.
So in this section, I define the interface as the Apple Developer Reference writes, I put the network interface data into a variable called iface
and I just turn off then turn on the WiFi. I don’t care about networks, priority and others here because I only need this for one network at a time but if you have multiple wifis in the same area and you are selecting it by hand every time, take a look at Network Preferences in the dropdown of the WiFi icon and you can change the priority of your networks there for automatic connections.
You can read about the setPower function I use HERE.