Automatic, Periodic Syncing with iSync
The first time I decided I wanted to start synchronizing my cell phone's calendar and address book with my Mac's, I noticed how iSync doesn't have a system of automatically invoking the synchronization procedure between regular intervals. I wanted to have the sync invoked automatically every 30 minutes, so I figured I had to do it myself somehow. I've had this script in place and running for, I don't know, a year and a half now, and I've used it with two different phones (the Nokia 3230 and the Nokia N82.) I'm not sure why I haven't blogged about it before, since this is exactly the kind of stuff I tend to write about here. Probably I've just forgotten is all. In any case, here it is.
Marc Liyanage at entropy.ch has already pretty much done the bulk of the work for this already. The differences between my solution and his are basically that mine tries to output lots of info to the user (via stdout or Growl,) mine doesn't care when the last sync took place, and that mine can be configured to start up iSync if it isn't already running.
An earlier version of my script figured out (via iSync's AppleScript interface) when the last sync procedure took place (regardless of whether it had been invoked from this script or from iSync itself) and then either cancelled or proceeded with the syncing based on that, but after a while I realized I had no need for that kind of a feature, so I removed it. I don't have the old version available anymore, but if anyone is interested in adding that feature, I still have the lastSync.scpt AppleScript I used to check if the difference between the current date and the last sync's date was long enough. It's included in the zip archive (a link to which is below.)
The (very general) directions to configuring the script and making it run are in the comments in the beginning of the file.
Download:
- The script and supporting files in a zip archive
- bluelist by Marc Liyanage and Will Harris (required for this to work -- save it in /usr/local/bin or somewhere)
- Lingon by Peter Borg (optional: for setting up a launchd configuration for this from a GUI)
- my workaround for a Leopard bug in growlnotify)
The script:
#!/bin/bash—————————————————————-
DESCRIPTION:
A script that is meant to be run periodically in order to
force iSync to synchronize.
It will not, however, invoke the sync if a specific
device (e.g. a mobile phone) is not connected via Bluetooth.
(c) Ali Rantakari, 2007-2008
http://hasseg.org
—————————————————————-
REQUIRES:
- OS X 10.4 (Tiger) or later
- The “bluelist” helper application by Marc Liyanage
and Will Harris
( link to the blog post where i found it:
http://tinyurl.com/2ahpme
direct link to the app itself:
http://will.harris.ch/bluelist.gz )
OPTIONAL:
- Growl + growlnotify (for notifications)
- Lingon (launchd/launchctl GUI for scheduling the running
of this script at regular intervals)
—————————————————————-
SETTING IT UP:
1) Change the settings in the “settings” area below to
correspond to your environment
2) Use Lingon/launchctl to schedule this script to be run
periodically
—————————————————————-
NOTE 1: You can run this script from the command line
with the parameter “-v” to check that it is working.
all notifications (and some additional info) will
be printed to the standard output then.
NOTE 2: I also noticed that iSync seems to not be setting the
sync status value for applescript properly -
a failed sync may have a status code of a successful
one - and thus this script may notify you that
the sync was successful when it in fact was not.
I have reported this issue to Apple on 12 Feb 2008,
and as of this writing (17 Apr 2008,) it still seems
to be open (the radar ID is 5738357).
NOTE 3: I found a lot of useful info for making this
script from these places:
http://hollington.ca/technocrat/?p=44
http://tinyurl.com/2ahpme [ -> entropy.ch]
—————————————————————-
get the location of this script.
do not change this (unless you know a better
implementation ;) )
DN=
dirname $0
THISDIR="cd $DN; pwd
"—————————————————————-
SETTINGS:
the bluetooth name of your mobile phone (or any similar device
you’re syncing with iSync via BT)
MOBILEBTNAME=“MyPhoneName”
the level of notifications you want to receive
0 = quiet (no notifications at all)
1 = inform only when starting to sync and
when sync has completed
2 = inform of everything
NOTIFICATIONLEVEL=1
whether to run iSync if it isn’t already running
“true” = if iSync is not running, run it
and then invoke the sync procedure
“false” = if iSync is not running, don’t sync
RUNISYNCIFNOTRUNNING=“false”
locations of CLI apps used
custom: (you need to get these yourself)
GROWLNOTIFY=/usr/local/bin/growlnotify BLUELIST=/usr/local/bin/bluelist
system: (these should be here)
OSASCRIPT=/usr/bin/osascript STAT=/usr/bin/stat TOUCH=/usr/bin/touch
the name of this application
(to send to growlnotify)
THISAPP=“Autosync script”
whether to use growl or stdout (or both) for notifications
“stdout” -> notifications will be printed to stdout
“growl” -> notifications will be sent to growl
“both” -> notifications will be sent to growl and
printed to stdout
NOTIFICATIONS=“growl”
the icon to show in growl notifications
GROWLICON="$THISDIR/forcesync.icon.png"
- - - - - - - - - - - - - - - - - - - - - -
settings end here.
—————————————————————-
Script IMPLEMENTATION begins here —————————
————————————————————-
— functions ——
parameters:
$1 = Title
$2 = Message
$3 = Minimum notification level
$4 = Location of icon to show
show_message() { if [ $NOTIFICATIONLEVEL -gt $(( $3 - 1 )) ] || [ $VERBOSEMODE == 1 ];then
if [ "$NOTIFICATIONS" != "stdout" ]; then if [ -e "$4" ];then THISGROWLICON="$4" else THISGROWLICON="$GROWLICON" fi $GROWLNOTIFY -n "$THISAPP" -t "$1" -m "$2" --image "$THISGROWLICON" fi if [ "$NOTIFICATIONS" != "growl" ];then echo "** $1" echo " $2" echo " " fi fi
}
no params
check_isync_running() { if [ “
ps xwww | grep -v grep | grep -c iSync.app/Contents/MacOS/iSync
” == “0” ];then echo “false” else echo “true” fi }no params
check_mobile_present() { if [ “
$BLUELIST | grep \"$MOBILEBTNAME\"
” == “$MOBILEBTNAME” ];then echo “true” else echo “false” fi }no params
activate_isync() { $OSASCRIPT -e “tell application "iSync" to activate” -s o }
no params
hide_isync() { $OSASCRIPT -e “tell application "System Events" to set visible of process "iSync" to false” -s o }
— /functions ——
script runs from here:
——————————————–
VERBOSEMODE=0 if [ “$1” == “-v” ];then VERBOSEMODE=1 NOTIFICATIONS=“both” echo " " fi
check if mobile phone is in Bluetooth range
if [ $VERBOSEMODE == 1 ];then echo " " echo -n “Scanning for bluetooth device "$MOBILEBTNAME"…” fi
if [ “
check_mobile_present
” == “false” ];then if [ $VERBOSEMODE == 1 ];then echo " …not found!" echo " " fi show_message “Will not sync” “"$MOBILEBTNAME" not found (either BT is off or device is out of range)” 2 exit 0 else if [ $VERBOSEMODE == 1 ];then echo " …found!" echo " " fi ficheck if iSync is running
ISYNCRUNNING="
check_isync_running
"if [ “$ISYNCRUNNING” == “false” ] && [ “$RUNISYNCIFNOTRUNNING” == “true” ];then
show_message "Starting up iSync" "Activating and hiding iSync" 2 activate_isync hide_isync
elif [ “$ISYNCRUNNING” == “false” ] && [ “$RUNISYNCIFNOTRUNNING” != “true” ];then
show_message "Will not sync" "iSync is not running" 2 exit 0
elif [ “$ISYNCRUNNING” == “true” ];then if [ $VERBOSEMODE == 1 ];then echo “iSync seems to be running. continuing…” echo " " fi else show_message “Error” “The iSyncRunning applescript returned invalid value: "$ISYNCRUNNING"” 1 exit 0 fi
sync
show_message “Sync starting” “Telling iSync to synchronize…” 1
SYNCSTATUS="
$OSASCRIPT -s o \"$THISDIR/forceSync.scpt\"
"if [ “$SYNCSTATUS” == “2” ];then show_message “Sync completed” “…Synchronization completed successfully.” 1 exit 0 elif [ “$SYNCSTATUS” == “3” ];then show_message “Sync warnings” “…Synchronization completed with warnings!” 1 exit 3 elif [ “$SYNCSTATUS” == “4” ];then show_message “Sync errors” “…Synchronization completed with errors!” 1 exit 4 elif [ “$SYNCSTATUS” == “5” ];then show_message “Sync cancelled” “…Synchronization was cancelled!” 1 exit 5 elif [ “$SYNCSTATUS” == “6” ];then show_message “Sync failed” “…Synchronization failed to complete!” 1 exit 6 elif [ “$SYNCSTATUS” == “7” ];then show_message “Sync failed” “…Synchronization did not succeed (status: (7) "never synced")!” 1 exit 7 else show_message “Sync error” “…Undefined error with sync: "$SYNCSTATUS"” 1 exit 127 fi
4 Comments
This sounds awesome! but im having REAL problems setting this up…
Im pretty new to macs, if you have the time could you please post a step-by-step?
thanks!
Hi Ollie,
Hope this helps:
Growl is a system-wide notification server, which receives notifications from applications and displays them to the user somehow. The idea is that applications would tell Growl what they want to tell the user and then Growl would tell it to the user. This way, the user can tell Growl how they’d like to receive all of their notifications instead of being constrained to however each individual application displays their stuff. When you’ve installed it, you’ll be able to find a “Growl” preference pane in the System Preferences application where you can configure the kinds of notifications you’d like to receive from Growl-enabled applications. growlnotify is a command-line application that can be easily used by scripts such as this to send notifications to Growl.
Lingon is an application that allows you to make OS X run scripts between regular intervals (among other things.) Its UI should be quite straightforward.
1) Download Growl (the link is in the post) and install it. From the Growl disk image (.dmg file) where the installer can be found, you’ll find a file called “growlnotify” (in a folder called “Extras”, if I remember correctly.) Copy this file over to /usr/local/bin (if this folder structure doesn’t exist, create it.) If you’re running Leopard, see my post about making growlnotify work properly in Leopard: ://hasseg.org/blog/post/111/growlnotify-leopard-incompatibility-workaround/
2) Download bluelist from the following location (this is a gzip archive so you’ll have to extract it first to get the bluelist application itself) and put it in /usr/local/bin as well: http://will.harris.ch/bluelist.gz
3) Download my script and its support files (the link is in the post.) Extract the contents of the archive somewhere (e.g. in /Users/your_user_name/scripts/forceSync)
4) Open my script in a text editor and configure it (in the “SETTINGS” section.) I Hope the comments I’ve put in the script will make it clear what each of the configuration values mean and what the allowed values for them are. Save the edited script when you’re done.
5) Test the script by running it in the terminal with the “verbose” parameter ("-v"):
cd /Users/your_user_name/scripts/forceSync/
./forceSync.bash -v
6) Download Lingon (the link is in the post) and run it. Create a new “agent”. You can put “org.hasseg.forceSync” into the Name field, “/Users/your_user_name/scripts/forceSync/forceSync.bash” (or wherever you put my script in) into the What field, and specify how often youd like to run it (e.g. “Run it every 30 minutes”.) Remember to check the “enabled” checkbox and click save.
If you’re still having problems, make sure that all of the command-line apps as well as my script are executable:
chmod a+x /Users/your_user_name/scripts/forceSync/forceSync.bash
chmod a+x /usr/local/bin/growlnotify
chmod a+x /usr/local/bin/bluelist
Thanks for this. I had to rebuild bluelist on Snow Leopard but otherwise it works fine.
Hi, thanks for all of this! It’s perfect! I’ve modified it a little bit because I don’t want my bluetooth always on. It’s simple, you have only to integrate it with ‘blueutil’ (http://www.frederikseiffert.de/blueutil/), just adding at the beginning and at the ending two commands. Bye!