Tuesday, July 8, 2008

Proximity

When I've got my MacBook sometime last December, I was astounded by the hacking possibilities that were then available to me, as it was the first computer I had with Bluetooth, WiFi and such.

Within the first few hours - after I set my phone to synchronize with iCal and iCal with Google Calendar, I figured that I had to find a way to make it happen automatically.

Thanks to Google, I quickly found this great post that helped me make it happen, using a really good program called Proximity.

I later found another wonderful program called MarcoPolo, and used it to switch the scripts for Proximity when I get in or out of my home wireless network range. MarcoPolo can actually handle Bluetooth proximity detection itself, but I remember I had some problems having it run different scripts for Bluetooth discovery/non-discovery depending on whether I was home or not.

Anyway, since I'm kind of impatient, and since I also used the cool idea from the aforementioned post to have Proximity start or stop the screensaver when I go away or come back - I made it check for the presence of my phone every 10 seconds. A successful check takes about 3 seconds, and an unsuccessful check takes about 7 or 8, so you can't get much lower than that.

After a long time of usage, though, I started to get annoyed by the fact that the UI of Proximity became unresponsive during the proximity checks. If I wanted to close it for some reason, it would become a pain in the ass because 8 out of 10 seconds it would give me the wheel of death, and I'd have to wait about half a minute until I got to the quit button and it responded (or resort to killing it from the terminal, which usually happened first).

Also - out of the blue it started making my phone light up and show messages that the computer was connecting and disconnecting every half a minute, which was kind of distracting and annoying.

Thankfully, Denver Timothy - the Proximity guy - is a great internet citizen, and decided to release the source code for Proximity along with the application itself.

Fixing the phone lighting up was pretty straightforward: previously, Proximity would try and connect to the phone and then disconnect, in order to check if it's around. It turns out, though, that there's a much more silent way to do this (somewhat like TCP SYN port scanning compared to the connect() method, only you don't have to be root).

The Cocoa Bluetooth Framework (I have to say I was very impressed with the extensiveness of the Cocoa libraries, as I had no previous experience with Cocoa or Obj-C) has a method called remoteNameRequest which - simply enough - asks for the name of the requested device, which cannot answer if it isn't there. Turns out that was enough to make my phone stop flashing at night.

Now to the UI unresponsiveness - after some research about how threads, memory management, run loops and thread synchronization go around in Cocoa, I gave the job of doing the blocking-proximity-check to a different thread. There was some message-passing to be done between the threads, in order to support different timer intervals for error-checking and normal-checking, but it worked out eventually.

Denver kindly agreed that I post this new version of Proximity for others to use, and even apply these code changes to the trunk.

So here is the application and here is the code.

Have fun,
Tomer

Edit: after a few weeks of usage, I noticed Proximity was crashing once in a while. Turns out the Bluetooth stack implementation in OS X was not thread safe :)
Anyway, I hope the code will help anyone with anything.

1 comment:

Roee Aharoni said...

so that's how you study for computer architecture.