Задача "Проснуться утром" для меня, честно говоря, довольно сложная. Неделю назад пришла в голову идея: написать простой будильник, который будет проигрывать музыку все громче и громче пока не решишь математический пример.
В гугле есть некоторые статьи и темы, но все не то, что нужно.
Сразу оговорюсь, что компьютер (в моём случае ноутбук) ночью находится в спящем режиме, поэтому ему потребуется немного зарядки на ночь (у меня за ночь уходит около 30% батареи).
Если у вас настольный компьютер, есть перебои с электричеством и нет ИБП, то лучше не рискуйте.
Далее вы должны убедиться, что ваш компьютер поддерживает некоторые режимы "сна". Можете почитать об этом здесь.
Что нам потребуется:
- Утилита rtcwake — для засыпания компьютера (встроена в ядро)
- Утилита amixer — для постепенного увеличения громкости звука
- Любой проигрыватель, позволяющий воспроизводить музыку в цикле (в моём случае mplayer)
Начнём
Зададим необходимые переменные:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# время по умолчанию
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-а и/или заново воспроизводить случайную музыку.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# включаем музыку
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
}
|
Также нужно перехватывать сигналы завершения процесса.
1
2
|
trap
"echo
-
e
`
Неа,
решите задачу!
`
&&
sleep
1
&&
alarm
_start"
SIGINT
SIGTERM
SIGHUP
SIGQUIT
SIGTSTP
SIGSTOP
|
Для того, чтобы можно было указать время просыпания будем использовать необязательный параметр $1. Сразу сделаем все проверки валидности даты.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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. Всё, что вы делаете — вы делаете на свой страх и риск.
1
2
3
4
5
6
7
8
|
# засыпаем
sudo
rtcwake
-
m
mem
-
t
$date
# устанавливаем громкость
amixer
-
q
set
Master
$volume
%
# включаем музыку
alarm_start
|
Про rtcwake, как уже говорил, вы можете прочитать здесь.
Осталось только сделать повышение громкости и пример для решения.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# повышаем уровень громкости
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 нужен для того, чтобы увеличение громкости было в фоне.
И генерируем пример:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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:
1
|
"alias alarm=`~/path_to_script/alarm.sh`"
|
Для того, чтобы будильник нельзя было выключить закрытием программы консоли, я выхожу из текущего сеанса и переключаюсь в другую консоль (Alt+Ctrl+F1 или другой F[1-7]).
При желании будильник можно отключить подав сигнал принудительного закрытия, но для этого нужно будет зайти в другую консоль, авторизоваться, найти этот процесс и убить. Быстрее, наверно, решить пример.
Для удобства код скопирован на pastebin, чтобы можно было скачать.
Надеюсь этот будильник заставит не проспать на учёбу или работу.
Задача "Проснуться утром" для меня, честно говоря, довольно сложная. Неделю назад пришла в голову идея: написать простой будильник, который будет проигрывать музыку все громче и громче пока не решишь математический пример.
В гугле есть некоторые статьи и темы, но все не то, что нужно.
Сразу оговорюсь, что компьютер (в моём случае ноутбук) ночью находится в спящем режиме, поэтому ему потребуется немного зарядки на ночь (у меня за ночь уходит около 30% батареи).
Если у вас настольный компьютер, есть перебои с электричеством и нет ИБП, то лучше не рискуйте.
Далее вы должны убедиться, что ваш компьютер поддерживает некоторые режимы "сна". Можете почитать об этом здесь.
Что нам потребуется:
- Утилита rtcwake — для засыпания компьютера (встроена в ядро)
- Утилита amixer — для постепенного увеличения громкости звука
- Любой проигрыватель, позволяющий воспроизводить музыку в цикле (в моём случае mplayer)
Начнём
Зададим необходимые переменные:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# время по умолчанию
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-а и/или заново воспроизводить случайную музыку.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# включаем музыку
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
}
|
Также нужно перехватывать сигналы завершения процесса.
1
2
|
trap
"echo
-
e
`
Неа,
решите задачу!
`
&&
sleep
1
&&
alarm
_start"
SIGINT
SIGTERM
SIGHUP
SIGQUIT
SIGTSTP
SIGSTOP
|
Для того, чтобы можно было указать время просыпания будем использовать необязательный параметр $1. Сразу сделаем все проверки валидности даты.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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. Всё, что вы делаете — вы делаете на свой страх и риск.
1
2
3
4
5
6
7
8
|
# засыпаем
sudo
rtcwake
-
m
mem
-
t
$date
# устанавливаем громкость
amixer
-
q
set
Master
$volume
%
# включаем музыку
alarm_start
|
Про rtcwake, как уже говорил, вы можете прочитать здесь.
Осталось только сделать повышение громкости и пример для решения.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# повышаем уровень громкости
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 нужен для того, чтобы увеличение громкости было в фоне.
И генерируем пример:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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:
1
|
"alias alarm=`~/path_to_script/alarm.sh`"
|
Для того, чтобы будильник нельзя было выключить закрытием программы консоли, я выхожу из текущего сеанса и переключаюсь в другую консоль (Alt+Ctrl+F1 или другой F[1-7]).
При желании будильник можно отключить подав сигнал принудительного закрытия, но для этого нужно будет зайти в другую консоль, авторизоваться, найти этот процесс и убить. Быстрее, наверно, решить пример.
Для удобства код скопирован на pastebin, чтобы можно было скачать.
Надеюсь этот будильник заставит не проспать на учёбу или работу.