В гугле есть некоторые статьи и темы, но все не то, что нужно.
Сразу оговорюсь, что компьютер (в моём случае ноутбук) ночью находится в спящем режиме, поэтому ему потребуется немного зарядки на ночь (у меня за ночь уходит около 30% батареи).
Если у вас настольный компьютер, есть перебои с электричеством и нет ИБП, то лучше не рискуйте.
Далее вы должны убедиться, что ваш компьютер поддерживает некоторые режимы «сна». Можете почитать об этом здесь.
Что нам потребуется?
— Утилита rtcwake — для засыпания компьютера (встроена в ядро).
— Утилита amixer — для постепенного увеличения громкости звука.
— Любой проигрыватель, позволяющий воспроизводить музыку в цикле (в моём случае mplayer).
Начнём
Зададим необходимые переменные:
# время по умолчанию tm='07:05' # начальная громкость volume=10 # максимальная громкость volume_max=90 # время для смены задачи sec=2 # папка с музыкой folder=~username/Music/alarm/* # временный файл для статуса temp=`mktemp -t alarm_status_XXX.txt`
Здесь всё понятно.
«время для смены задачи» — время простоя перед генерацией новой задачи.
«папка с музыкой» — папка, из которой нужно брать список музыки. Я просто создал папку alarm и создал жёсткие ссылки на необходимые мне музыкальные композиции.
«временный файл для статуса» — нужен для завершения увеличения громкости. Если существует непустой файл, то завершаем фоновой процесс (кстати, можно просто через «jobs -l» найти наш процесс).
Теперь нужно написать функцию, которая будет убивать процессы mplayer-а и/или заново воспроизводить случайную музыку.
# включаем музыку alarm_start() { # убиваем все процессы mplayer-а jbs=(`ps al | grep [m]player | gawk -F ' ' '{print $3}'`) for job in ${jbs[*]} ; do kill -15 $jbs done # включаем случайную мелодию с бесконечным повтором if [ -z "$1" ] ; then mplayer -loop 0 -shuffle $folder &> /dev/null & fi }
Также нужно перехватывать сигналы завершения процесса.
trap "echo -e '\nНеа, решите задачу!' && sleep 1 && alarm_start" SIGINT SIGTERM SIGHUP SIGQUIT SIGTSTP SIGSTOP
Для того, чтобы можно было указать время просыпания будем использовать необязательный параметр $1. Сразу сделаем все проверки валидности даты.
if [[ $# > 0 ]] ; then if [[ "$1" == [0-9]:[0-9][0-9] ]] || [[ "$1" == [0-9][0-9]:[0-9][0-9] ]] ; then tm=$1 else echo 'Установите правильное время. Пример: "07:00".' >&2 exit 10 fi fi date1=$(date -d "`date +%m/%d/%y` $tm" +%s) date2=$(date -d "`date +%m/%d/%y` $tm tomorrow" +%s) # последняя ошибка (если неверная дата) err=$? if [[ $err > 0 ]] ; then echo 'Установите правильное время. Пример: "07:00".' >&2 exit $err fi # если настоящее время больше времени для пробуждения, то ставим завтрашний день if [[ $date1 < `date -u +%s` ]] ; then date=$date2 else date=$date1 fi
Переменные date1 и date2 нужны на случай, если пользователь укажет прошедшую дату, тогда время для просыпания будет установлено завтрашним днём. Если же время будет указано, например «07:99», то в переменную err будет занесён код ошибки.
Теперь можно «заставить» компьютер спать. rtcwake требует прав суперпользователя. Можно воспользоваться sudo. Всё, что вы делаете — вы делаете на свой страх и риск.
# засыпаем sudo rtcwake -m mem -t $date # устанавливаем громкость amixer -q set Master $volume% # включаем музыку alarm_start
Про rtcwake, как уже говорил, вы можете прочитать здесь.
Осталось только сделать повышение громкости и пример для решения.
# повышаем уровень громкости while true ; do amixer sset Master 1%+ &> /dev/null volume=$(( $volume+1 )) if [ $volume -eq $volume_max ] ; then break elif [ -s "$temp" ] ; then rm "$temp" # возвращаем нормальную громкость amixer -q set Master 50% break fi sleep 2 done &
Строчкой «amixer sset Master 1%+ &> /dev/null» мы указываем, что нужно повышать громкость на 1 процент и не нужно ничего выводить на экран.
Знак амперсанда & после оператора done нужен для того, чтобы увеличение громкости было в фоне.
И генерируем пример:
clear echo 'Чтобы выключить музыку решите пример:' while true ; do # ждём echo "Ждите $sec сек." sleep $sec # пример который надо решить var1=$(( $RANDOM % 10000 - 5000 )) var2=$(( ($RANDOM % 100000 - 50000)/($RANDOM % 800 + 1) )) # операторы case $(( $RANDOM % 3 )) in 0) opt='+' result=$(( $var1 + $var2 )) ;; 1) opt='-' result=$(( $var1 - $var2 )) ;; 2) opt='*' var2=$(( ($RANDOM % 5 + 5) )) result=$(( $var1 * $var2 )) ;; esac # для красоты if [[ $var2 < 0 ]] ; then if [[ "$opt" == '-' ]] ; then opt='+' var2=$(( $var2 * -1 )) elif [[ "$opt" == '+' ]] ; then opt='-' var2=$(( $var2 * -1 )) fi fi # ответ read -p "$var1 $opt $var2 = " answer # завершаем цикл если ответ был правильный if [[ $answer == $result ]] ; then echo "Правильно! Ответ: $result." break else clear echo -n "Неверно! Правильный ответ был: $var1 $opt $var2 = $result." if [ -n "$answer" ] ; then echo " Вы ответили: $answer." else echo "" fi fi done # параметром мы указываем, что не нужно воспроизводить музыку alarm_start false # для выключения увеличения громкости echo "done" > "$temp"
Вот и всё. Будильник был написан неделю назад. Телефонные будильники были выключены. За эту неделю я вполне мог проснуться пока решаю пример (задачка может быть очень простой (1020 — 120) или сложной (394 * 5). В одно утро мне попадался 13 раз подряд пример с умножением).
Можно создать alias в файле ~/.bashrc: «alias alarm=’~/path_to_script/alarm.sh’»
Для того, чтобы будильник нельзя было выключить закрытием программы консоли, я выхожу из текущего сеанса и переключаюсь в другую консоль (Alt+Ctrl+F1 или другой F[1-7]).
При желании будильник можно отключить подав сигнал принудительного закрытия, но для этого нужно будет зайти в другую консоль, авторизоваться, найти этот процесс и убить. Быстрее наверно решить пример 🙂
#!/bin/bash # Будильник # включаем музыку alarm_start() { # убиваем все процессы mplayer-а jbs=(`ps al | grep [m]player | gawk -F ' ' '{print $3}'`) for job in ${jbs[*]} ; do kill -15 $jbs done # включаем случайную мелодию с бесконечным повтором if [ -z "$1" ] ; then mplayer -loop 0 -shuffle $folder &> /dev/null & fi } # время по умолчанию tm='07:05' # начальная громкость volume=10 # максимальная громкость volume_max=90 # время для смены задачи sec=2 # папка с музыкой folder=~username/Music/alarm/* # временный файл для статуса temp=`mktemp -t alarm_status_XXX.txt` # от намеренного закрытия сонного человека trap "echo -e '\nНеа, решите задачу!' && sleep 1 && alarm_start" SIGINT SIGTERM SIGHUP SIGQUIT SIGTSTP SIGSTOP if [[ $# > 0 ]] ; then if [[ "$1" == [0-9]:[0-9][0-9] ]] || [[ "$1" == [0-9][0-9]:[0-9][0-9] ]] ; then tm=$1 else echo 'Установите правильное время. Пример: "07:00".' >&2 exit 10 fi fi date1=$(date -d "`date +%m/%d/%y` $tm" +%s) date2=$(date -d "`date +%m/%d/%y` $tm tomorrow" +%s) # последняя ошибка (если неверная дата) err=$? if [[ $err > 0 ]] ; then echo 'Установите правильное время. Пример: "07:00".' >&2 exit $err fi # если настоящее время больше времени для пробуждения, то ставим завтрашний день if [[ $date1 < `date -u +%s` ]] ; then date=$date2 else date=$date1 fi # засыпаем sudo rtcwake -m mem -t $date # sudo echo "$date" > /sys/class/rtc/rtc0/wakealarm # устанавливаем громкость amixer -q set Master $volume% # день недели # day=$(( `date +%u` - 1 )) # включаем музыку alarm_start # повышаем уровень громкости while true ; do amixer sset Master 1%+ &> /dev/null volume=$(( $volume+1 )) if [ $volume -eq $volume_max ] ; then break elif [ -s "$temp" ] ; then rm "$temp" # возвращаем нормальную громкость amixer -q set Master 50% break fi sleep 2 done & clear echo 'Чтобы выключить музыку решите пример:' while true ; do # ждём echo "Ждите $sec сек." sleep $sec # пример который надо решить var1=$(( $RANDOM % 10000 - 5000 )) var2=$(( ($RANDOM % 100000 - 50000)/($RANDOM % 800 + 1) )) # операторы case $(( $RANDOM % 3 )) in 0) opt='+' result=$(( $var1 + $var2 )) ;; 1) opt='-' result=$(( $var1 - $var2 )) ;; 2) opt='*' var2=$(( ($RANDOM % 5 + 5) )) result=$(( $var1 * $var2 )) ;; esac # для красоты if [[ $var2 < 0 ]] ; then if [[ "$opt" == '-' ]] ; then opt='+' var2=$(( $var2 * -1 )) elif [[ "$opt" == '+' ]] ; then opt='-' var2=$(( $var2 * -1 )) fi fi # ответ read -p "$var1 $opt $var2 = " answer # завершаем цикл если ответ был правильный if [[ $answer == $result ]] ; then echo "Правильно! Ответ: $result." break else clear echo -n "Неверно! Правильный ответ был: $var1 $opt $var2 = $result." if [ -n "$answer" ] ; then echo " Вы ответили: $answer." else echo "" fi fi done alarm_start false # для выключения увеличения громкости echo "done" > "$temp"
Для удобства код скопирован на pastebin, чтобы можно было скачать.
Надеюсь этот будильник заставит не проспать на учёбу или работу 🙂
ссылка на оригинал статьи http://habrahabr.ru/post/159987/
Добавить комментарий