#!/bin/bash # Dusk and Dawn X10 schedule preprocessor # Author Daniel B. Suthers # This utility takes an X10 schedule file and creates multiple lines # where-ever it sees the special string DAWN or DUSK It calls the dawndusk # utility to determine the actual sunrise and sunset times. # # An offset can be specified by adding a positive or negative number of minutes # to the end of the dawn or dusk tag. # Example: #timer smtwtfs 01/11-04/29 dusk dawn+20 livinroom_on livinroom_off #timer smtwtfs 01/11-04/29 07:00 dusk-20 lampoff lampon PATH=$PATH:. FINE_GRAIN=OK # NO= 1 entry per month, OK=twice per month if [ $# = 0 ] ; then SCHED=$HOME/.x10sched.conf else SCHED=$1 fi for FL in $X10CONFIG $HOME/.x10config /etc/x10.conf ; do egrep 'LATITUDE' $FL > /dev/null 2>&1 if [ $? = 0 ] ; then LATITUDE=`sed -n -e "s/^OPTION *LATITUDE//p" -e "s/^LATITUDE[ *]//p" $FL | tr -d 'NSEW' ` LONGITUDE=`sed -n -e "s/^OPTION *LONGITUDE//p" -e "s/^LONGITUDE[ *]//p" $FL | tr -d 'NSEW' ` export LATITUDE LONGITUDE break fi done # return number of days in the month maxdays() { mo=`echo $1 | sed "s/^0//"` case "$mo" in 1|3|5|7|8|10|12) DAYS=31;; 2) DAYS=28;; *) DAYS=30;; esac echo $DAYS } #Return the number of seconds since Jan 1, 1970. # This is not real acurate, but it puts us within 48 hours of the correct # time. seconds() { mo=$1 day=$2 SEC_IN_YEAR=31536000 SECS=0 if [ -f $HOME/.PRIORYEARS ] ; then read SECS < $HOME/.PRIORYEARS fi YEAR=`date +%Y` # add up seconds since Jan 1, 1970 for each year before this one if [ "$SECS" -eq 0 ] ; then while [ "$YEAR" -gt 1970 ] ; do SECS=`echo 31536000 + $SECS | bc` if [ `expr "$YEAR" % 4` = 0 ] ; then if [ `expr $YEAR % 100` != 0 ] ; then SECS=`echo 86400 + $SECS | bc` fi fi YEAR=`expr "$YEAR" - 1` done echo $SECS > $HOME/.PRIORYEARS fi #Add a month at a time for this year mo=`expr $mo - 1` while [ $mo -gt 0 ] ; do DAYS=`maxdays $mo` mo=`expr $mo - 1` SECS=`echo $DAYS \* 86400 + $SECS | bc` done SECS=`echo $day \* 86400 + $SECS | bc ` HR=`date +%H` # add the hours today SECS=`echo $HR \* 3600 + $SECS | bc` echo $SECS } cat $SCHED | while read label days month_range on off cmds ; do if [ "$label" != timer ] ; then # Just duplicate the line as is if it is not a timer echo $label $days $month_range $on $off $cmds else echo "$on $off" | egrep -i 'dawn|dusk' > /dev/null if [ $? != 0 ] ; then echo $label $days $month_range $on $off $cmds # This is a timer line without dawn or dusk. continue fi echo "# Some of the entries were generated by `basename $0` from the following line:" echo \#$label $days $month_range $on $off $cmds # Separate the days and months set `echo "$month_range" | sed "s/[\/-]/ /g"` ENDMO=$3 STARTMO=$1 NO_DEC=1; MID=NO while [ $STARTMO -le $ENDMO ] ; do # set the start day for second and later months if [ $STARTMO = $1 ] ; then SDAY=$2 # original start day else SDAY=01 # Start of month fi # EOM = end of month if [ $STARTMO -lt $ENDMO ] ; then # Month 1 through N end on the last day of the month EOM=`maxdays $STARTMO` else # The last month uses the real end day EOM=$4 fi # This logic is somewhat convoluted. It's meant to increment the # sday by two weeks on every other iteration so that the granularity # is a bit finer. if [ $FINE_GRAIN = OK ] ; then if [ `expr $EOM - $SDAY` -gt 14 -a $MID = OK ] ; then SDAY=`expr $SDAY + 14` NO_DEC=0 # this flag says not to decrement month else NO_DEC=1 if [ `expr $EOM - $SDAY` -gt 14 ] ; then EOM=`expr $SDAY + 13` else NO_DEC=0 fi fi fi STARTMO=`expr 0$STARTMO : '.*\(..\)'` # get the number of seconds since Jan 1, 1970 for input to the # dawndusk utility SECONDS=`seconds $STARTMO $SDAY` offset=`echo $on | sed -n "s/.*\([+-][0-9]*\).*/\1/p"` eval `dawndusk $SECONDS $offset` ONDUSK=$DUSK ONDAWN=$DAWN offset=`echo $off | sed -n "s/.*\([+-][0-9]*\).*/\1/p"` eval `dawndusk $SECONDS $offset` OFFDUSK=$DUSK OFFDAWN=$DAWN case "$on" in dusk*) ONVALUE=$ONDUSK;; dawn*) ONVALUE=$ONDAWN;; *) ONVALUE=$on;; esac case "$off" in dusk*) OFFVALUE=$OFFDUSK;; dawn*) OFFVALUE=$OFFDAWN;; *) OFFVALUE=$off;; esac echo "$label $days $STARTMO/$SDAY-$STARTMO/$EOM $ONVALUE $OFFVALUE $cmds" if [ $FINE_GRAIN = OK ] ; then if [ $NO_DEC = 0 -o $FINE_GRAIN = NO ] ; then STARTMO=`expr $STARTMO + 1` MID=NO else MID=OK fi else STARTMO=`expr $STARTMO + 1` fi done echo "# end of auto generated entries." fi done [ -f $HOME/.PRIORYEARS ] && rm $HOME/.PRIORYEARS