Using ACPI & MythTV to run other applications

From MythTV Official Wiki
Jump to: navigation, search

Introduction

This is a quick & dirty solution. It is hard coded to run one task at the same time once per day. The scripts must be modified to change the name of the task, or the time of execution.

ACPI setup for a desktop system

mythtv-setup settings for your script

Block shutdown: (checked, if you run frontend and backend on 1 machine. Do not check if you do not automatically start the front end, and want the system to shut down after an automatic recording.)

Idle shutdown timeout (secs): 180 (if you set this to 0, it will disable auto shutdown)

Max. wait for recording (min): 60

Startup before rec. (secs): 1200 (If you have not disabled the occasional disk check on boot, make this time long enough to complete the boot & disk check before the recording should start. On my system the disk check can take as long as 15 minutes)

Wakeup time format: time_t

Command to set Wakeup Time: sudo sh -c "/usr/bin/setwakeup.sh $time"

Server halt command: sudo shutdown -h now

Pre Shutdown check-command: checklogin.sh

Write the startup script
Script.png /usr/bin/setwakeup.sh
#!/bin/bash
#$1 is the first argument to the script. It is the time in seconds since 1970
#this is defined in mythtv-setup with the time_t argument

#I don't know how to ask MythTV for this value, so it is duplicated here. This is ugly.
#number of seconds before scheduled recording that computer should start booting.
startbeforerecord=1200

#Calculate time_t format time for next non MythTV event. Note that the user event time is hard coded!
# This hard coded time must match the time of the event you schedule in cron.
userevent=$(( $(date -d 3:00AM +%s) - startbeforerecord ))
(( userevent += ( userevent < $(date +%s) ) ? 24*60*60 : 0 )) # If event time has already passed, add 1 day

# Set wake time to the earliest of MythTVs wake time and userevent
(( waketime = ( userevent < $1 ) ? userevent : $1 ))

echo 0 > /sys/class/rtc/rtc0/wakealarm      #this clears your alarm.
echo $waketime > /sys/class/rtc/rtc0/wakealarm     #this writes your alarm

Edit the script to change the event time to the time you wish to execute your custom script/program. The default is 3:00 AM

Change the permissions of the file so that it can execute

sudo chmod +x /usr/bin/setwakeup.sh

Add the following line to your /etc/sudoers by running "sudo visudo" and pasting the line at the end of the file.

%mythtv ALL = NOPASSWD: /sbin/shutdown, /bin/sh, /usr/bin/setwakeup.sh
Write the pre-shutdown script

Create the following script to prevent myth from shutting down when someone is logged in.


Script.png /usr/bin/checklogin.sh
#!/bin/bash
# Check to see if there are reasons MythTV does not know about to prevent shutdown. Return zero if not and 1 if so.
# Echoed text appears in log file. It can be removed and --quiet added to the 
# grep command once you are satisfied that mythTV is working properly

    # The leading space is important!
  if w | grep " 0 users" ; then
    echo No one is logged in.

         # If the user event is currently executing, do not shut down
         # IMPORTANT! you must change the text in the quotes to match the name of the program/script your are running with cron!
      if ps -A | grep "testscript" ; then
        echo User script is still running, don\'t shut down.
        exit 1
      fi

      #I don't know how to ask MythTV for these values, so I must duplicate them here. This is ugly
    maxwait=3600

      #Calculate time_t format time for next non MythTV event. Note that this time is hard coded
      # This time must match the time of the scheduled event in cron.
    userevent=$(date -d 3:00AM +%s)
    currenttime=$(date +%s)
    (( userevent += ( ( userevent + 5 ) < currenttime ) ? 24*60*60 : 0 )) # if userevent time has already passed, add 1 day.

        #if there is plenty of time before event, allow shutdown
      if (( currenttime < ( userevent - maxwait ) )); then
        echo User script is not running and there is lots of time before it needs to start, shut down.
        exit 0
      else
        echo User script is not running, but it will start shortly, don\'t shut down.
        exit 1
      fi
    
  else
    echo Someone is still logged in, don\'t shut down! 
    exit 1
  fi

Edit the script to set the time and name of the script/program you wish to be executing.

Change its attributes to executable

sudo chmod +x /usr/bin/checklogin.sh

Add a cron event with crontab. The name of the task and the time must match the values in the script.

You must remember to log out rather than shut down when you are done with your session, allowing the mythTV backend to shut off the computer when it is idle. This is because the mythTV shutdown sequence writes the wakealarm time to the BIOS just before shutting down the system. If, instead, you shut the system down, the mythTV backend is not able to update the BIOS with the correct wakealarm time. Failure to follow this procedure could interrupt a recording, or prevent the system from powering on for a later recording.

Note that the Idle Timeout time is the time you have to type your username and password when logging in. It would be a good idea to make it long enough to log in before the system can shut itself off.

In the BIOS, set your system to power on when power is restored. This will allow the system to recover after a power outage. Some systems will disable the wakealarm after a power outage, but even if it doesn't, if the power is off at the programmed wake time, the wakealarm could be missed. Powering up after a power outage allows mythTV to reset the wakealarm so that future recordings are not missed.

Things that still need to be resolved

I am assuming that I will use cron to initiate the external event, and the MythTV ACPI stuff to ensure that the computer is on at the time the external event needs to start. I'd like to make this setup generalized so that one can just add something to cron and have the computer power up at the correct time to execute the event. This means there must be some means of asking cron what the next events are, and somehow flagging the ones that need to have the computer turned on. Also once an external event is initiated, I must be able to tell when external event is completed so that the system knows when it is safe to shut itself down.

To distinguish between cron tasks that the computer should power on for, I'm thinking of defining a user. Cron has a crontab file for each user. Within that file there would be no way to distinguish tasks that need to have the computer powered on from those that don't, so by defining a user whose sole purpose is owning these tasks, I can use that username to identify which tasks I need to pay attention to.

I can see that implementing this is going to be messy since I will have to duplicate the parsing that cron does so I can identify the next task and when it needs to be executed. Also I'm not sure how to know when a task completes. The simple idea is to see if any tasks owned by this single purpose user are running, but some tasks, like a system backup must run as root.

I took a peek at the source code to cron. Seems rather inefficient to poll once a minute when the default ubuntu setup (and probably most other distributions) use cron only for once weekly or monthly events.

I'm beginning to believe I need to do a from scratch scheduler. There are three types of events it must handle:

1: normal scheduled events like cron does now.

2: scheduled events that need to guarantee the computer is running. The scheduler needs to keep track of these tasks once started to make sure it does not shut down the system until they are complete.

3: daemons that run all the time, but need to guarantee the computer is on at a particular time. Not yet sure how to handle these to know when it is safe to shut the system down.

Editorial content

It is my belief that the ACPI power control should be separated from MythTV, and incorporated into cron. This would allow people who don't use mythTV schedule stuff like automated backups & running sprinkler systems without having to leave their computers on all the time. Implementing this change would be non-trivial, so it does not appear that this is likely to happen, and I don't yet have the skill to do this myself. I might have enough skill to make the above scripting stuff work, so I'm going to attempt it.