#!/bin/bash
#
# If the file [ /etc/powernap/action ] is executable, then the
# /usr/sbin/powernap binary will run it when called.
#
# Otherwise, /usr/sbin/powernap will run one of:
#   * pm-suspend
#   * pm-hibernate
#   * poweroff
# depending on your hardware's capabilities, as determined by
# pm-is-supported(1).
#
# You may do one of:
#   1) Write your own custom script below and make this file executable,
#      calling some specific action, such as:
#        /usr/sbin/pm-suspend
#        /usr/sbin/pm-hibernate
#        /sbin/poweroff
#        echo 'I am wasting electricity' | mail Al_Gore@example.com
#   2) Replace this file with an executable script or binary
#   3) Symlink this file to some other executable script or binary


################### Configuration ####################
TIME_TO_BOOT=3
TIME_TO_DOWN=3

# Debug output
# 1 == on, '' == off
#DEBUG=1

# Ping-Command with parameters
# here: send two requests
PING="ping -c 2"

# List of hosts to check
HOSTS=`grep -v ^# <<!
#192.168.1.5
#192.168.1.12
192.168.1.10
192.168.1.11
#192.168.1.15
#192.168.1.20
#192.168.1.21
!`

################## Functions ########################

get_next_wakeup_timer()
{
 CURRENTLY_RECORDING=0
 if [ `echo $(du -b /var/lib/vdr/timers.conf) | awk '{print $1}'` -gt "0" ];then
    i=1
    while [ $i -le 80 ];do 					#get the closest timer (max 80 is an improvement) sould be something like: for line in file do...
	STRING=`head -n $i /var/lib/vdr/timers.conf|tail -n 1` 	
	DATE=`echo $STRING | awk -v FS=":" '{print $3}'`
	if [ `echo $DATE | grep M` ] || [ `echo $DATE | grep D` ] || [ `echo $DATE | grep F` ] || [ `echo $DATE | grep S` ];then	#yet no week days in timers!
	    [ ${DEBUG} ] && echo "Do not use days of timers, yet!"
	    DATE=`date +%Y-%m-%d`
	    [ ${DEBUG} ] && echo "To prevent loosing a timer I will use fallback date: $DATE (today)"
	fi
	TIME=`echo $STRING | awk -v FS=":" '{print $4}'`
	ENDTIME=`echo $STRING | awk -v FS=":" '{print $5}'`
	HOUR=`echo $TIME | cut -b 1-2`
	MINUTES=`echo $TIME | cut -b 3-4`
	NEW_TIMER=`echo $DATE | tr -d '[=-=][:blank:]'`$TIME
	END_TIMER=`echo $DATE | tr -d '[=-=][:blank:]'`$ENDTIME
	if [ `expr $NEW_TIMER - $TIME_TO_DOWN - $TIME_TO_BOOT` -le `date +%Y%m%d%H%M` ] && [ $END_TIMER -ge `date +%Y%m%d%H%M` ]; then
	    [ ${DEBUG} ] && echo "There is currently a timer running"
	    CURRENTLY_RECORDING=1
	    break
	fi
	if ( [ -z $NEXT_TIMER ] || [ $NEXT_TIMER -gt $NEW_TIMER ] ) && [ `expr $NEW_TIMER - $TIME_TO_DOWN - $TIME_TO_BOOT` -gt `date +%Y%m%d%H%M` ];then  #keep the newest, but prevent setting past timers
	    [ ${DEBUG} ] && echo "TAKE_TIMER $i (JJJJMMDDHHhhmm): $NEW_TIMER"
	    NEXT_TIMER=$NEW_TIMER
	fi
	i=`expr $i + 1`
    done
    if [ $CURRENTLY_RECORDING -eq 0 ]; then
	[ ${DEBUG} ] && echo "Now it is (JJJJMMDDHHhhmm): `date +%Y%m%d%H%M`"
	[ ${DEBUG} ] && echo "NEXT_TIMER selected (JJJJMMDDHHhhmm): $NEXT_TIMER"
    else
	[ ${DEBUG} ] && echo "Not sleeping"
    fi
 fi
}
convert_timer_to_acpi_format()
{
    #convert NEXT_TIMER to acpi format
    YEAR=`echo $NEXT_TIMER | cut -b 1-4`
    MONTH=`echo $NEXT_TIMER | cut -b 5-6`
    DAY=`echo $NEXT_TIMER | cut -b 7-8`
    HOUR=`echo $NEXT_TIMER | cut -b 9-10`
    MINUTES=`echo $NEXT_TIMER | cut -b 11-12`
    BIOS_STRING="$YEAR-$MONTH-$DAY $HOUR:$MINUTES:00"
    BIOS_TIME="`date --date=\"$BIOS_STRING\" +%s`"
    BIOS_STRING=`expr $BIOS_TIME - 60 \* $TIME_TO_BOOT`

#    if [ $MINUTES -le $TIME_TO_BOOT ];then
#	HOUR=`expr $HOUR - 1`
#	MINUTES=`expr $MINUTES + 60 - $TIME_TO_BOOT`
#    else
#	MINUTES=`expr $MINUTES - $TIME_TO_BOOT`
#    fi
#    BIOS_STRING="`date --date=\"$BIOS_STRING\" +%s`"
}

set_bios_wakeup_time()
{
    echo 0 > /sys/class/rtc/rtc0/wakealarm
    echo $BIOS_STRING > /sys/class/rtc/rtc0/wakealarm
#    echo $BIOS_STRING > /sys/class/rtc/rtc0/wakealarm
    echo $BIOS_STRING
    echo -n "BIOS ACPI TIME WAS SET TO: "
    cat /sys/class/rtc/rtc0/wakealarm
}
get_default_timer(){ 		#default timer to keep epg up to date
    TODAY=`date +%d`
    TOMORRO=`expr $TODAY + 1` 	#should changed because of the last day of the month!
    YEAR=`date +%Y%m`
    TIME="1900"
    NEXT_TIMER="$YEAR$TOMORRO$TIME"
    echo "Default Timer is (JJJJMMDDHHhhmm): $NEXT_TIMER"
}

##
# check host-list
checkHosts()
{
    ACTIVE=false

    for ADDR in ${HOSTS}
    do
        ${PING} ${ADDR} > /dev/null
        if [ $? -eq 0 ]; then
            [ ${DEBUG} ] && echo $0": "${ADDR}" ist aktiv!"
            ACTIVE=true
            break
        else
            [ ${DEBUG} ] && echo $0": "${ADDR}" nicht aktiv!"
        fi
    done

##
# if ACTIVE is still 0 then all hosts are off
    if [ "${ACTIVE}" = "false" ];then
        # schaltet Rechner ab, falls keine lokalen/SSH-Nutzer da sind
        [ ${DEBUG} ] && echo $0": keine LAN-Rechner aktiv, schaltet Server aus"
        logger -t $0 "keine LAN-Rechner aktiv"
        return 1
    else
        [ ${DEBUG} ] && echo $0": Tue nichts, LAN-Rechner aktiv!"
        return 0
    fi


} 

## 
# check for users which are logged in locally or remotely (via ssh)
# also accounts for screen sessions
localUsers()
{
    COUNT=`w -h | sed '/^\s*$/d' | wc -l`
    [ $DEBUG ] && echo "$0: Lokale Benutzer: $COUNT "
    return ${COUNT}
}

nap()
{
    echo "Will suspend now"
    sendemail -f xxx@yyy.zz -t xxx@yyy.zz -s smtp.yyy.zz -m 'Server will suspend now' -u 'powernap'
    /usr/sbin/pm-suspend
}

checkVDR()
{
    ### check for vdr-sxfe connections
    CONNECTIONS=`netstat -A inet  | grep 37890`
    if [ -n "$CONNECTIONS" ]; then
        return 0;
    fi
    ### check for active streamdev connections
    CONNECTIONS=`netstat -A inet | grep 2004`
    if [ -n "$CONNECTIONS" ]; then
        return 0;
    fi
    return 1;
}


#################### Main #############################

### check for running ssh sessions / local logins
localUsers
if [ $? -ne 0 ]; then
    [ $DEBUG ] && echo "There are still active users, so not going to sleep."
    exit 0
fi

### check for active hosts in the LAN
checkHosts
if [ $? -eq 0 ]; then
    [ $DEBUG ] && echo "There are still active computers in the LAN."
    exit 0
fi

### check for active VDR connections
checkVDR
if [ $? -eq 0 ]; then
    [ $DEBUG ] && echo  "Will not nap because of active vdr connections."
    exit 0
fi

### check for active timers
#get_default_timer
get_next_wakeup_timer
if [ $CURRENTLY_RECORDING -eq 1 ]; then
    echo "Will not go to sleep because there is a timer recording right now."
    exit 0
fi

### set acpi wakeup time
if [ -n "$NEXT_TIMER" ]; then
    convert_timer_to_acpi_format
    set_bios_wakeup_time
else
    [ $DEBUG ] && echo "Will not set wakeup time because there is no future timer."
fi

### execute the nap commands
nap

