My HTPC should be available when I need it, but not waste power when I'm not at home or sleeping.
See previous parts: Part 1, Part 2
My setup consists of 3 scripts:
kodi-shutdown-inhibit-check.sh
: Main script that is run from cron, talks to Kodi to allow/inhibit shutdownshutdown-check.sh
: Checks if anything should inhibit shutdownset-next-wakeup.sh
: Sets when the computer should start next time
Kodi idle shutdown timer
Kodi is set to shutdown after 5 mins of inactivity (See "Timer til lukning af funktion"):
Every 4 minutes cron runs the kodi-shutdown-inhibit-check.sh
script. Note: it requires that kodi-send
from the kodi-eventclients package is installed.
#!/bin/bash
# based on http://forum.xbmc.org/showthread.php?tid=172801&pid=1500080#pid1500080
LASTSTATEFILE="/tmp/xbmc-shutdown-inibit-laststate"
XBMCPIDFILE="/tmp/xbmc-shutdown-inibit-pid"
# Handle restart of xbmc
CURRENTPID=$(pgrep kodi.bin)
KODI_NOT_RUNNING=0
if [[ $? -gt 0 ]]; then
KODI_NOT_RUNNING=1
fi
if [[ -f $XBMCPIDFILE ]]; then
PID=`cat $XBMCPIDFILE`
else
PID=$CURRENTPID
echo $PID > $XBMCPIDFILE
fi
# if the old pid is not equal to the current, make sure that inhibit is send again
# by forcing it to be 0
if [[ $PID != $CURRENTPID ]]; then
/usr/bin/logger "$0: XBMC changed PID: $PID != $CURRENTPID"
if [[ -f $LASTSTATEFILE ]]; then
rm $LASTSTATEFILE
fi
echo $CURRENTPID > $XBMCPIDFILE
fi
/usr/local/bin/set-next-wakeup.sh &>/dev/null
if [[ -f $LASTSTATEFILE ]]; then
LASTSTATE=`cat $LASTSTATEFILE`
else
LASTSTATE=0
fi
/usr/local/bin/shutdown-check.sh &>/dev/null
CHECK=$?
# Enable to debug
# /usr/bin/logger "$0: [DEBUG] CHECK: ${CHECK}"
# /usr/bin/logger "$0: [DEBUG] KODI_NOT_RUNNING: ${KODI_NOT_RUNNING}"
# /usr/bin/logger "$0: [DEBUG] PID: ${PID}"
# /usr/bin/logger "$0: [DEBUG] CURRENTPID: ${CURRENTPID}"
# 0: Shutdown allowed
if [[ $CHECK -eq 0 ]]; then
if [[ $KODI_NOT_RUNNING -gt 0 ]]; then
/usr/bin/logger "$0: Kodi not running, shutting down"
/usr/bin/shutdown -h now
fi
if [[ $LASTSTATE -ne 0 ]]; then
kodi-send --action="XBMC.InhibitIdleShutdown(false)" >/dev/null
/usr/bin/logger "$0: Allow shutdown"
echo "0" > $LASTSTATEFILE
# else
# /usr/bin/logger "$0: Shutdown allready allowed"
fi
else
if [[ $LASTSTATE -eq 0 ]]; then
kodi-send --action="XBMC.InhibitIdleShutdown(true)" >/dev/null
/usr/bin/logger "$0: Inhibit shutdown"
echo "1" > $LASTSTATEFILE
# else
# /usr/bin/logger "$0: Shutdown allready inhibited"
fi
fi
The above script calls shutdown-check.sh
to see if it is OK to shutdown. The script checks for:
- Time of day, weekdays the computer should be on between 9 and 10:59, and again from 19 to 23:59. If the computer is running after midnight it will be shutdown between 2 and 6
- A couple of checks to see if anything is running that should be allowed to continue running
- Is there any users logged in other than the user that runs Kodi (in this case the "mythtv" user)
#!/bin/bash
# Check time
HOUR=`date '+%-k'`
MIN=`date +%M`
DAY=`date '+%u'`
case ${DAY} in
1|2|3|4|5) # Work days
ONHOURS="9 10 19 20 21 22 23"
;;
6|7) # Weekends
ONHOURS="0 1 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23"
;;
esac
# Hours where shutdown is forced
KILLHOURS="2 3 4 5 6"
for KILLHOUR in ${KILLHOURS}; do
if [[ ${HOUR} == ${KILLHOUR} ]]; then
/usr/bin/logger "$0: in killhour: ${HOUR} (day:${DAY})"
exit 0
fi
done
for ONHOUR in ${ONHOURS}; do
if [[ ${HOUR} == ${ONHOUR} ]]; then
#/usr/bin/logger "$0: in onhour: ${HOUR} (day:${DAY})"
exit 1
else
# Considered true if clock 18:16
if [[ $(( ${HOUR} + 1 )) == ${ONHOUR} && ${MIN} -gt 15 ]]; then
/usr/bin/logger "$0: less than 45min to onhour: ${HOUR} ${MIN} ${ONHOUR} (day:${DAY})"
exit 1
fi
fi
done
if [[ `transmission-remote -l | wc -l` > 2 ]]; then
/usr/bin/logger "$0: transmission downloading"
exit 1
fi
if [[ `grep -c "check" /proc/mdstat` = 1 ]]; then
/usr/bin/logger "$0: raid resync is running"
exit 1
fi
if [ -e /tmp/noshutdown-*.lock ]; then
/usr/bin/logger "$0: a job is running"
exit 1
fi
declare -a CHECK_PROGRAMS
CHECK_PROGRAMS=('chrome' 'chromium' 'fs-uae' 'popcorntime' 'dolphin')
for PROGRAM in "${CHECK_PROGRAMS[@]}"; do
if pgrep "$PROGRAM" &>/dev/null; then
/usr/bin/logger "$0: $PROGRAM is running"
exit 1
fi
done
# if last | head | grep -q ".*still logged in"; then
USERS=`w -h | grep -v mythtv | wc -l`
if [[ $USERS > 0 ]]; then
# A user is logged in
/usr/bin/logger "$0: user logged in"
exit 1
fi
/usr/bin/logger "$0: shutdown ok"
exit 0
Wakeup
The last 2 pieces is to set up the computer so that it will automatically start the next day, and enable Wake-On-LAN.
Wakeup via ACPI / RTC
I have made a simple script that ensures that the computer is turned on at 9:00 and again at 19:00 on weekdays, and at 7:00 in the weekend. The script is called set-next-shutdown.sh
.
Note: this requires that the BIOS/UEFI is configured correctly, in the case of the Gigabyte GA-Z87-D3HP the "Wake from Alarm" should be disabled.
#!/bin/bash
# Defaults to tomorrow @ 09:00:00 in weekdays, and 07:00:00 in the weekend
LASTWAKETIMEFILE="/tmp/set_next_wakeup_laststate"
HOUR=`date '+%-k'`
DAY=`date '+%u'`
ONTIME=`date '+%s' -d 'tomorrow 09:00:00'`
case ${DAY} in
1|2|3|4) # Work days
case ${HOUR} in
0|1|2|3|4|5|6|7)
ONTIME=`date '+%s' -d '09:00:00'`
;;
8|9|10|11|12|13|14|15)
ONTIME=`date '+%s' -d '19:00:00'`
;;
esac
;;
5) # Friday
case ${HOUR} in
0|1|2|3|4|5|6|7)
ONTIME=`date '+%s' -d '9:00:00'`
;;
8|9|10|11|12|13|14|15)
ONTIME=`date '+%s' -d '19:00:00'`
;;
16|17|18|19|20|21|22|23)
ONTIME=`date '+%s' -d 'tomorrow 07:00:00'`
;;
esac
;;
6) # Saturday
case ${HOUR} in
0|1|2|3|4|5|6)
ONTIME=`date '+%s' -d '7:00:00'`
;;
*)
ONTIME=`date '+%s' -d 'tomorrow 07:00:00'`
;;
esac
;;
7) # Sunday
case ${HOUR} in
0|1|2|3|4|5|6)
ONTIME=`date '+%s' -d '7:00:00'`
;;
esac
;;
esac
if [[ -f $LASTWAKETIMEFILE ]]; then
LASTWAKETIME=`cat $LASTWAKETIMEFILE`
if [[ $LASTWAKETIME != $ONTIME ]]; then
/usr/bin/logger "$0: Setting wakeup to $ONTIME (`date -d @${ONTIME}`)"
echo 0 > /sys/class/rtc/rtc0/wakealarm
echo $ONTIME > /sys/class/rtc/rtc0/wakealarm
echo $ONTIME > $LASTWAKETIMEFILE
# else
# /usr/bin/logger "$0: Wakeup allready set to $LASTWAKETIME (`date -d @${LASTWAKETIME}`)"
fi
else
/usr/bin/logger "$0: Setting wakeup to $ONTIME (`date -d @${ONTIME}`)"
echo 0 > /sys/class/rtc/rtc0/wakealarm
echo $ONTIME > /sys/class/rtc/rtc0/wakealarm
echo $ONTIME > $LASTWAKETIMEFILE
fi
Wake On LAN (WOL)
In case I need the computer at a time where it is not runnin, I can wake it from my desktop computer or from my phone using the Wake On LAN app.
Activate WOL support using ethtool with a systemd unit (based on Arch Linux Wiki:Wake-on-LAN):
[Unit]
Description=Wake-on-LAN for %i
After=network.target
[Service]
ExecStart=/usr/bin/ethtool -s %i wol g
Type=oneshot
[Install]
WantedBy=multi-user.target
Now I can use the wol tool to wake the HTPC: wol -v ${MAC}
where ${MAC} is the MAC address of NIC