The other day, Federico asked about why people use web services such as IFTTT. I have a few of these that I use frequently, but the geekiest one is this: controlling my Mac with my car.
More specifically, when I turn my car’s ignition on or off in the parking lot at my office, Automatic triggers an IFTTT recipe, creating a text file in a special Dropbox folder which is monitored by launchd[1] and runs a shell script depending on which file is created.
It sounds more complicated than it is. No, really.
What can these shell scripts do?
There are many possibilities for what these scripts can do, but here are some examples of what I do.
When my ignition turns on
When my ignition turns on, that means that I am leaving my office, which could mean for lunch (I’ll be back in an hour), an off-site meeting (I’ll be back in an hour or two), or it’s the end of the day (I’ll be back tomorrow or the next business day).
- Make sure my Mac is locked
- Load CrashPlan
- Make sure my TimeMachine backup drive is mounted
- Make sure BitTorrent Sync is running
- Run SuperDuper[2]
When my ignition turns off
When my ignition turns off , that means that I am arriving at work.
- Unload CrashPlan[3]
- Unmount my SuperDuper drive [4]
- Launch apps that I want to use to start the day: BusyCal, OmniFocus, MailMate, etc.
If you use network drives, this would be a good time to (re)connect to them. You could also launch iTunes or Spotify if you listen to music at work. Basically anything that you normally wait for your computer to do when you first arrive at the office, you can get started before you even walk in the door.[5]
“Ok… how?”
Now that you hopefully understand the big picture overview, I’ll get into the specifics of how to put this together.
- You need a car with an Automatic device.[6]
- You need accounts with IFTTT and Dropbox.
- Create a folder in Dropbox. This can be any folder, but I will be using /Users/jsmyth/Dropbox/IFTTT/Automatic/IgnitionAtWork/ in my examples.
- A
launchd
plist in ~/Library/LaunchAgents/ which monitors the folder from step #3. - A shell script to run from the
launchd
plist. This can be called anything you want, but I will be using/usr/local/bin/IgnitionAtWork.sh
in my examples. - Two geofenced triggers in the iOS IFTTT app: one which creates an “IgnitionOn.txt” file and one which creates an “IgnitionOff.txt” file.
Example launchd
plist
Here is an example launchd
plist.
- Change the
Program
key to be the name of the shell script - Change the
QueueDirectories
key to point to the directory that you created.
Note that you cannot use ~
or $HOME
to refer to your home directory in a launchd
plist, you must provide the full, exact path.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.tjluoma.IgnitionAtWork</string>
<key>Program</key>
<string>/usr/local/bin/IgnitionAtWork.sh</string>
<key>QueueDirectories</key>
<array>
<string>/Users/jsmyth/Dropbox/IFTTT/Automatic/IgnitionAtWork/</string>
</array>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>
(Note: this is available as a GitHub gist).
Save it to ~/Library/LaunchAgents/com.tjluoma.IgnitionAtWork.plist
Example shell script
The contents of IgnitionAtWork.sh
are really up to you. This is just an example to show how you might put it together.
#!/bin/zsh -f
# Important! DIR _must_ be the same as whatever directory you used
# for `QueueDirectories` in the `com.tjluoma.IgnitionAtWork.plist`
DIR="/Users/jsmyth/Dropbox/IFTTT/Automatic/IgnitionAtWork/"
# if the directory does not exist, exit
cd "$DIR" || exit 0
# get rid of this file, which will cause `launchd` to keep triggering
rm -f .DS_Store
command ls -1 \
| egrep 'IgnitionOn|IgnitionOff' \
| while read line
do
case "$line" in
IgnitionOn*)
###########################################################################
## BEGIN OPTIONAL SECTION for when Ignition is turned on
## Change this in this section to suit your needs
# run BitTorrent Sync application
open -a 'BitTorrent Sync'
# mount TimeMachine drive, if not mounted
[[ ! -d '/Volumes/TimeMachine' ]] && diskutil mount TimeMachine
if (( $+commands[lock.sh] ))
then
# if the 'lock.sh' script is found, run it
lock.sh
else
# otherwise, just lock screen by switching to login window
'/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession' -suspend
fi
## END OPTIONAL SECTION for when Ignition is turned on
###########################################################################
# This deletes the file so that launchd doesn't just keep triggering the script
rm -f "$line"
;;
IgnitionOff*)
###########################################################################
## BEGIN OPTIONAL SECTION for when Ignition is turned off
## Change this in this section to suit your needs
# launch apps that you want to have run when you get to the office
# these are just some examples
open -g -a 'OmniFocus'
open -g -a 'BusyCal'
open -g -a 'MailMate'
## END OPTIONAL SECTION for when Ignition is turned off
###########################################################################
# This deletes the file so that launchd doesn't just keep triggering the script
rm -f "$line"
;;
esac
done
exit 0
# End of shell script
(This shell script is also available as a GitHub gist.)
Example IFTTT recipes on iOS
Step 1) Create IFTTT recipe for when the ignition turns ON in a specific area
When you launch the IFTTT iOS app, choose “Automatic” and then “Ignition turned on in an area” as the “Trigger”:
Note: If you are not in the area that you want to use as the trigger, you can manually select the area that you want to use, but it is easier to do this when you are already at the area that you want to use as the IFTTT trigger. For example, since I wanted the geofence to be the parking lot at my office, I waited until I was there before creating the IFTTT recipes.
Next, choose “Dropbox” and “Create a text file” as the “Select Action”:
This part can be a little confusing. When you first create the IFTTT recipe, it automatically chooses the folder (IFTTT/Automatic) and the filename for you. You have to select the recipe and tap “Edit”
then scroll down to change the filename and folder:
Step 2) Create IFTTT recipe for when the ignition turns OFF in a specific area
Once you have completed Step 1, repeat the process except when you launch the IFTTT iOS app, choose “Automatic” and then “Ignition turned off in an area” as the “Trigger” instead of “Ignition turned on in an area.”
There are a few provisos, a couple of quid pro quos…
This system is not foolproof.
Occasionally I realize that the IFTTT action failed to run for some reason. Launching the IFTTT app on my iPhone usually fixes this. The IFTTT iOS app can send you a push notification when recipes run, which is a good idea so that you know it is working. If Dropbox is not running, or if it is busy doing something else (like reindexing itself for the millionth time, not that I’m bitter), it might not sync the IFTTT file right away.
There have been times when I have been at the office for an hour and then suddenly Dropbox says “Oh, wait, here’s that file” and then launchd
runs the “Oh, you have just arrived at the office!” script.
A few times I have been sitting at my desk after being at my office for a long time when suddenly I received an IFTTT notification that the ignition in my car had just started. It was a little disconcerting the first time it happened, but now whenever I notice that something isn’t working properly I just launch the Automatic and IFTTT apps on my iPhone, and that seems to solve the problem. (I assume these issues are caused when the iPhone runs out of RAM and kills off background processes, but that’s just a guess.)
-
Whenever I am just monitoring a folder to run a shell script if/when a change happens, I use
launchd
instead of Hazel. In my experience,launchd
is triggered faster than Hazel. I use Hazel when I want to do some sort of file manipulation. Also, it’s possible to sync my launchd plists using BitTorrent Sync, but Hazel does not sync. ↩︎ -
It takes about 30 minutes for SuperDuper to update my bootable clone, and when I leave in my car, I am almost always gone for longer than that, so I might as well run it! ↩︎
-
Generally, I would recommend leaving your online backup software on all the time, but the Internet connection at my office is AT&T U-Verse, and the upload bandwidth is terrible, so I avoid running online backups during work hours. Also, CrashPlan is still a Java app, despite the developers promising for several years that a native Mac app is coming. Even when CrashPlan is configured not to use a lot of CPU, sometimes it still does, so unloading it avoids that problem too. ↩︎
-
Normally Keyboard Maestro will unmount my SuperDuper drive when SuperDuper quits. This is for three reasons: a) if the drive is mounted but has gone to sleep, OS X will have to wait for it to “spin up” when I use Open/Save in an app, and b) when I use Spotlight, sometimes it shows me files or applications on my SuperDuper drive, which I never want it to do. Best to avoid any risk and just leave it unmounted when not in use. c) If my Mac mini loses power or has a kernel panic, a mounted drive could be corrupted. If it isn’t mounted, it’s safe. That does not happen very often, but since there’s no compelling reason to leave it mounted, it seems like another good reason to unmount it when not in use. ↩︎
-
Even if you don’t have an Automatic, you could still create a
launchd
plist to do this at a certain time of day, assuming you have a relatively set schedule of when you arrive at the office. ↩︎ -
Unfortunately, Automatic only works in the USA. (Sorry, Federico!) Hopefully that will change in the future. The Automatic device normally costs $100 USD, but they often sponsor podcasts and offer a $20 discount if you use the podcast’s referral code or referral link. (Just to be clear: Automatic did not “sponsor” this article.) ↩︎