Proximity Detection on a Mac

I get really annoyed when I find myself having to do things over and over that a computer could easily do. I am also really bad at remembering to do small things that don’t seem that important.

The latest intersection of these 2 things is that I’ve been forgetting (or not bothering) to set my status as “Away” or “Back” on all the communications apps I have running when I leave the computer. This is something that a computer should be able to do itself, and something that I’m horribly bad at remembering to do.

After a little bit of Googling around, I came across this awesome little application called Proximity (for Macs) which pairs up with a bluetooth device (e.g. my iPhone) and performs one simple task. All it does is executes an AppleScript when that device is in range, and a different one when it returns to range. This is exactly what I was looking for; with some custom AppleScripting, I was able to put together a solution that does the following:

  • Detects that my iPhone is in range/nearby (which I always carry, so it proxies as “detecting me”)
    • Sets me as “available” on IRC (Colloquy), Adium (all chat networks) and Skype
    • Presses “play” on iTunes
  • If I walk away?
    • Set me as “Away” on IRC, Adium and Skype
    • Press “pause” on iTunes
    • Triggers the screensaver (which I also have configured to require my password to unlock)

I also have it logging to a text file when I am “away” and “back” just for interest, and I’ll see if there’s anything fun I can do with that later.

Now I’m looking for more things to tie into these two scripts (below) to make life a little bit easier. Suggestions?

My “Away” script — Download

-- Adium : set away message
if appIsRunning("Adium") then
        tell application "Adium"
                go away with message "Away"
        end tell
end if

-- Skype : set as away
if appIsRunning("Skype") then
        tell application "Skype"
                send command "SET USERSTATUS AWAY" script name "Proximity"
        end tell
end if

-- Colloquy: change nick to [current-nick]|away
if appIsRunning("Colloquy") then
	tell application "Colloquy"
      set aC to every connection
      repeat with conn in aC
         set aR to (every chat room of conn)
         repeat with room in aR
			set nickname of conn to "beau|away"
         end repeat
      end repeat
   end tell
end if

-- iTunes : pause music
if appIsRunning("iTunes") then
        tell application "iTunes"
                pause
        end tell
end if

-- Bump Screensaver
activate application "ScreenSaverEngine"

-- Log Movements
set logFile to "/Users/beau/util/proximity.log"
open for access logFile with write permission
write "AWAY: " & current date & "\n" to logFile starting at eof
close access logFile

-- Helper
on appIsRunning(appName)
        tell application "System Events" to (name of processes) contains appName
end appIsRunning

And when I come “Back” — Download

-- Adium : set as available
if appIsRunning("Adium") then
        tell application "Adium"
                go available
        end tell
end if

-- Skype : set as available
if appIsRunning("Skype") then
        tell application "Skype"
                send command "SET USERSTATUS ONLINE" script name "Proximity"
        end tell
end if

-- Colloquy: change nick back to normal
if appIsRunning("Colloquy") then
	tell application "Colloquy"
      set aC to every connection
      repeat with conn in aC
         set aR to (every chat room of conn)
         repeat with room in aR
			set nickname of conn to "beaulebens"
         end repeat
      end repeat
   end tell
end if

-- iTunes : play music
if appIsRunning("iTunes") then
        tell application "iTunes"
                play
        end tell
end if

-- Start Screensaver (which locks the screen)
tell application "ScreenSaverEngine" to quit

-- Log Movements
set logFile to "/Users/beau/util/proximity.log"
open for access logFile with write permission
write "BACK: " & current date & "\n" to logFile starting at eof
close access logFile

-- Helper
on appIsRunning(appName)
        tell application "System Events" to (name of processes) contains appName
end appIsRunning
  1. Donncha said:

    That's mad stuff that is! You should probably warn people that bluetooth has quite a range and can go through walls and floors. I was trying to get my PS3 controller hooked up to my Macbook in the kitchen and I was confused when the little "connected" light lit up but the Macbook was't seeing it.

    Only later when I returned upstairs did I find the PS3 on, and I had browsed to the users menu. Luckily no damage had been done!

    • Beau Lebens said:

      Good point 🙂 The range can be deceptively far, especially with a clear line of sight. While I was testing this I was just turning Bluetooth on and off to simulate being out of range which worked nicely, but in my apartment for example, it's not possible to get far enough away to trigger it!

      • Fabio said:

        Can't you fix some sort of ping to check response time and estimate your distance? Like response time less then 1ms, it means your far, set the away status?

        • Beau Lebens said:

          I'm not sure to be honest Fabio — I've never done any Cocoa programming. That part of the setup is handled by Proximity.app. I'm happy enough with what I've got — as long as I'm marked away when I leave my apartment/office it's fine.

    • Beau Lebens said:

      Let me know if you come up with any other cool things to trigger from it, I feel like there *have* to be some other cool things to do with it! (other than making my laptop say something like "welcome back, master" when I return 😉 )

  2. Lance said:

    This looks awesome—thanks for posting it! Can't wait to try it.

    A quick thought from looking at the code: doesn't setting your nickname in one Colloquy room do it in all of the open rooms? There shouldn't be the need for the loop through all the rooms.

    You could also add in the /AWAY command to mark your user as away and fades your nick to a grey color in Colloquy. For example: /AWAY Back later.

    • Beau Lebens said:

      You're totally right about the looping through rooms/connections Lance. That's what I get for copy-pasting blindly 🙂

      if appIsRunning("Colloquy") then
      tell application "Colloquy"
      set aC to every connection
      repeat with conn in aC
      set nickname of conn to "beau|away"
      end repeat
      end tell
      end if

      That loop will do it just fine. My original script had an /away command in there as well, but I ended up removing it. If you want to do that, the AppleScript command is just

      set away message of conn to "Away message"

    • mdawaffe said:

      Depending on Colloquy's AppleScript API, you might need to loop through all open servers. But maybe that's what Beau's loop above does.

      • Lance said:

        Yes, you do need to loop through open connections (servers), but don't need to loop through all the rooms within that connection.

    • Beau Lebens said:

      I read that very same post while I was looking for a way to do this 🙂 I was considering setting something like that up since it seems like a more immediate/accurate way of doing it, although I'm not sure how fond I am of the idea of my iSight being constantly on, snapping pictures of me.

  3. IM/IRC/Skype Statuses Applescript Helper « tekArtist

  4. Proximity Detection on OS X | Apple | Keefer Madness

  5. Tim Phillips said:

    can you make a script that stops iMessage giving new message notifications to BOTH the iPhone/iPad and Mac when they are in range of each other. I find it really annoying when im having a conversation through iMessage on my Macbook, and my iPhone is forever vibrating in my pocket!

Comments are closed.