beengone: a script-friendly way to check computer idle time

[Tweet : ADN : nvALT]

I spent too long figuring this out, but I’m quite certain there are at least 3 people who can put the result to good use. I don’t know who they are yet, but they’ll show up. Eventually.

I wanted a way to detect whether I was at my computer or not when a script finished, and — if I’d been gone a certain amount of time — send me a text message or push notification instead of displaying a Growl popup. I had everything worked out except for the actual detection. I was just going to use AppleScript and check for the ScreenSaverEngine process, but that proved not to be failsafe. I did some digging, only to find that OS X doesn’t seem to expose that information directly anywhere.

Now, if you’re using Growl, you can easily add push notifications only on idle using Pushover, Boxcar or Prowl. Pushover even has an API that you can integrate in non-Growl scripts. When using the API, though, you can’t detect idle the way the Growl plugin does. For applications where I want a configurable time limit and need to trigger something like another task or anything other than push notifications, I needed a means to detect idle time on my own.

Enter I/O Kit. I learned this technique for detecting the idle status from a post by Jean-David Gadina. I hacked together my solution from his examples, and most of the credit for the final product really goes to him.

The result is a little CLI called beengone. You simply run it from a script with a number that represents the amount of time (in minutes) that you want to test for. If there hasn’t been any keyboard or mouse input within the number of minutes you specify, it prints out “true” and a 0 exit code. If there has, then you haven’t “been gone” and it outputs “false” and exits with a non-zero status. It’s designed to be used in scripts, where you can just call it with:

beengone 5

and it will tell you if there has been activity in the last 5 minutes. Capture the output on STDOUT or use the exit code to handle logic in your script. If you want to check and make sure it’s working, run:

sleep 5 && beengone .1

Then, don’t touch anything for five seconds. If it’s working, it will output “true” on STDOUT. If not, you’ll see “false” and there may be something providing input to your computer in the background which is preventing idle. I haven’t seen WOL or anything else affect it yet, though.

Here’s a quick example in Ruby of how I would call it and determine an action to take based on the results:

def notify(msg)
  $stderr.puts msg
    away = %x{/usr/local/bin/beengone 5}.strip
    if away == "false"
      # user is present, display a Notification Center banner
      TerminalNotifier.notify(msg, :title => "Your script name") if growl
      # Machine is idle, send an SMS using <>
      $stderr.puts "Sending... " + %x{~/scripts/voicesms.rb -m "#{msg}"}

### perform tasks and notify on completion
notify("The script is complete")

(Of course, you could get more elegant with how the CLI is called, and I’ll probably eventually write a wrapper using the Process module.)

beengone is a simple tool and a simple solution which seems to be fairly foolproof for my needs. Feel free to download the binary below, and if you’re curious how it works, please refer to Jean-David’s original post. Hope this helps some other folks, too.

beengone v1.0

A command-line tool to check if the user has been AFK for a given number of minutes

Updated Sat Feb 09 2013.

More info…