Saturday, May 25, 2013

Bash Script: Timing a Hard Refresh

Problem

The Cal Poly Robotics Club has a slideshow that runs 24/7 on a computer (we call it halftop) in the club window. The half-of-a-laptop is hooked up to a screen so we can bombard any (and all) lucky Bonderson visitors with information about CPRC. Eventually they will join us or at least think we are awesome.

The slideshow is actually available on Google Drive, which is really convenient for editing purposes. However, the fullscreen slideshow has to be restarted manually if any edits are made. Sure, that's not that difficult if there is someone in the room all the time, but the more autonomous the better!

Solution

So, I seized the opportunity to struggle with bash a bit more. At first, I was going to write a bash script that took care of all the timing in-house (see that attempt here). However, I quickly realized that really smart people have already written programs that can make this task pretty simple. Still, from that first bit, I garnished the knowledge I needed on wmctrl and cron/crontabs.

wmctrl

Wmctrl is a command-line program for finding and changing the properties of windows managed by whatever window manager is active. You should read the manual for it, though, to get a better description.

cron/crontabs

Cron is a daemaen that runs in the background in order to accomplish tasks on a timed schedule. I use it to make sure the window slideshow gets updated every 24 hours (or 3 hours, depending on one's preference).

Code

Implementing this solution is a two-part process: writing the script, and installing the crontab command.

Script Setup

The most updated script can be downloaded from here. Below is the code as of 5/24/2013.
#! /bin/bash
# this script is run by cron whenever indicated.
# it takes one argument: the command for starting the window.

# check that wmctrl is installed
if [[ -z `which wmctrl` ]]
then
   echo "`basename $0`: wmctrl is not installed."
   exit
fi

# if no argument is given, then it exits without doing anything.
if [[ -z $1 ]]
then
   echo "`basename $0`: no argument given. exiting..."
   exit
fi

# make a variable for path
STORE_PATH=~/.cron_info
F_WNUM=$STORE_PATH/window_num
F_TMP0=$STORE_PATH/temp0
F_TMP1=$STORE_PATH/temp1

# if .cron_info doesn't exist, create it
if [[ ! -d $STORE_PATH ]]
then
   echo "`basename $0`: ~/.cron_info does not exist. creating directory"
   mkdir $STORE_PATH
fi

# if the file containing the window number exists
if [[ -a $F_WNUM ]]
then
   # use it
   WIN_NUM=`cat $F_WNUM`
   # close it
   echo "`basename $0`: closing window number '$WIN_NUM'"
   wmctrl -i -c $WIN_NUM
   sleep 1
fi

# start the window
echo "`basename $0`: starting window with '$1'"
wmctrl -l > $F_TMP0
$1 &
sleep 1
wmctrl -l > $F_TMP1
DIFF=`diff ${F_TMP0} ${F_TMP1}`
echo "`basename $0`: waiting for new window to load"

# this while loop needs to wait for there to only be one line difference
while [[ -z $DIFF || `wc -l <<<$DIFF` != 1 ]]
do
   sleep 1
   wmctrl -l > $F_TMP1
   DIFF=`diff ${F_TMP0} ${F_TMP1}`
done

rm $F_TMP0 $F_TMP1

# store the window number for next run
DIFF=( $DIFF )
WIN_NUM=${DIFF[2]}
echo $WIN_NUM > $F_WNUM

# make window fullscreen now
echo "`basename $0`: making window fullscreen"
wmctrl -i -r $WIN_NUM -b "add,fullscreen"

echo "`basename $0`: done."
Make sure the script is an executable with
$ chmod +x /path/to/cron_refresh_script.sh
and you should be good to go.

Crontab Setup

To set up the crontab line, you have to open up the crontab editor with
$ crontab -e
The format for a line in crontab is
min hour dom mon dow command
where you give integers for the minute, hour, day-of-month, month, and day-of-week. If you want it to run on all of them, you use a *. For example, if you want it to run every 3 hours
0 */3 * * * command
and to get it to run every 24 hours, you would put the line
0 0 * * * command
Of course, you should read man crontab for a fuller description. The final line for making the slideshow update every 3 hours with my script is
0 */3 * * * /path/to/cron_refresh_script.sh "google-chrome --app=https://docs.google.com/presentation/d/12QC74xBCKrXP60eyH0DcjMpEpQB8vd9aOabrP09gRfY/pub?start=true&loop=true&delayms=7000#slide=id.gb3f24a1f_2_38"
I hope this helps someone out there (including any future CPRC officers who want to do something similar)!

No comments:

Post a Comment

Please keep your comments respectful and in the spirit of constructive criticism.