Как сделать будильник при помощи Asterisk, FreeBSD и наличии небольшого количества свободного времени

от автора

Сижу я на работе утром. Коллега опаздывает, делать особо нечего. Скучно. Наконец приходит опоздавший и жалуется, что не проснулся по своему будильнику. То ли не завел, то ли не услышал, этого я уже не помню. Почему бы не устроить ему звонок с работы, с утра пораньше?

Сказано — сделано. Решил я написать будильник.

Как будем реализовывать?

Диалплан решил не трогать, ибо он и так уже не самый маленький, и усложнять его не хочется. Поэтому было решено написать shell скрипт, который запускается по крону и создает call-файлы с нужными данными.

Записывать кому и когда звонить в сам скрипт мне показалось неудобным, поэтому был создан текстовый файл alarmnumbers.txt вида:

89993332211 1000 1100 1200 1300 1400 1500 1600 /recs/macroform-robot_dity 89993332211 1005 1105 1205 1305 1405 XXXX XXXX /recs/macroform-robot_dity 

Где первое это номер телефона, на который будет совершен звонок, дальше идут 7 блоков, разделенных пробелами, с указанием времени звонка: первый блок для понедельника, второй для вторника, и так далее. В самом конце путь к файлу, который будет воспроизведен, если поднимут трубку. Это должен быть любой звуковой файл, который астериск сможет скушать. Имя файла пишется без разрешения, астер сам выберет, какое ему нужно. Можно звуковой файл и вовсе не указывать, в таком случае при поднятии трубки звонок будет сразу же сброшен. Ну а XXXX вместо времени указывает не совершать побудку. К примеру, в выходные.

В файлике может быть сколько угодно строк, повторения номеров тоже допустимы. Решение, конечно, не самое оптимальное, но поскольку использование будильника предполагается только внутри IT отдела, то вполне подходящее. Разместил я его на шаре win сервера, подцепив её к FreeBSD при помощи mount_smbfs.

Сам скрипт запускается по крону раз в сутки. Т.е. обновление данных кому и куда звонить происходит каждый день в 00.02.

Разберем, что делает скрипт:

#!/bin/sh  echo 'START!'  filename=/recs/alarmnumbers.txt CallFileName=AlarmFile NewCallFilesPath=/var/spool/asterisk/outgoing_new/ AsteriskCallFilePath=/var/spool/asterisk/outgoing/  

Указываем, где что лежит и как называть call-файлы для asterisk (ему, кстати, имя файла не важно, можете указать любое)
filename — наш файл со списком кому и когда
CallFileName — имя call-файла, только для нашего удобства
NewCallFilesPath — каталог для создаваемых call-файлов. Создавать их там, откуда их берет астер, нельзя — читает он их быстро и часто, может прочитать неполный. Этот каталог должен быть на том же разделе с каталогом, где астер ищет call-файлы для выполнения.
AsteriskCallFilePath – каталог, из которого астер читает call-файлы. Т.к. у меня FreeBSD, у вас они могут располагаться в другом месте.

 currentdate=$(date +%Y%m%d) weekday=$(date +%u) var0=0  

Запоминаем текущее время и день недели.

 case "$weekday" in         1)wd="13-16";;         2)wd="18-21";;         3)wd="23-26";;         4)wd="28-31";;         5)wd="33-36";;         6)wd="38-41";;         7)wd="43-46";; esac  

В зависимости от дня недели будем выбирать соответствующий блок в alarmnumbers.txt. Это параметры для cut.

 cat $filename | while read line do  DialTime=$(echo $line | cut -c$wd)  var0=`expr $var0 + 1`  number=$(echo $line | cut -c1-11)  dialwavfile=$(echo $line | cut -c48-200)  

Читаем alarmnumbers.txt. построчно, выбирая нужные параметры из каждой строки.
DialTime — время звонка, тут используется параметр wd, который мы задали раньше.
number — номер, на который будет совершен звонок
dialwavfile — звуковой файл

  echo "Channel: SIP/providername/$number" > "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "CallerID: CompanyNumber" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "MaxRetries: 2" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "RetryTime: 450" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "WaitTime: 20" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "Application: Playback" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "Data: $dialwavfile" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  echo "Archive: yes" >> "$NewCallFilesPath$CallFileName$DialTime$var0.call"  

Создаем call-файл. Структура у него получится вот такая:

 Channel: SIP/providername/89217884033 CallerID: CompanyNumber MaxRetries: 2 RetryTime: 450 WaitTime: 20 Application: Playback Data: /recs/macroform-robot_dity Archive: yes  

Channel — Через что звонить, указывается любой канал. У меня указан пир для внешних звонков. Если вы собираетесь звонить и на внутренние номера, то придется дописать условие, по которому будут подставляться различные каналы.
CallerID – Думаю, понятно. Не актуально, если это звонок на внешнюю линию и провайдер не позволяет менять CallerID
MaxRetries — Не поднял трубку? Не беда! Позвоним еще, вдруг не проснулся? Параметр сообщает сколько раз пытаться вызвать абонента
RetryTime — Через столько перезвонить, в секундах
WaitTime — Дозваниваться до абонента столько секунд.
Application — Это то приложение астериска которое будет использовано если абонент поднял трубку.
Data — Данные для приложения с предыдущей строки
Archive — Сохранять выполненные call-файлы, для анализа к примеру

  chmod 755 $NewCallFilesPath$CallFileName$DialTime$var0.call  chown asterisk $NewCallFilesPath$CallFileName$DialTime$var0.call  chgrp asterisk $NewCallFilesPath$CallFileName$DialTime$var0.call  

Выдаем права на чтение, изменение и удаление пользователю, от которого запущен астериск.

  time=$(echo $line | cut -c$wd)  case $time in   XXXX) rm $NewCallFilesPath$CallFileName$DialTime$var0.call ;;   "") rm $NewCallFilesPath$CallFileName$DialTime$var0.call ;;   *) touch -t "$currentdate$time" "$NewCallFilesPath$CallFileName$DialTime$var0.call" ;;  esac  

Тут мы правим время изменения или удаляем call-файл в том случае если вместо времени указано XXXX.
Один из важных моментов в работе с call-файлами. Астериск будет читать только файлы с датой и временем изменения меньше или равной текущей. Таким образом, если мы укажем время модификации в будущем, астер будет ждать, пока не наступит нужное время.

  mv $NewCallFilesPath$CallFileName$varr$var0.call $AsteriskCallFilePath  

Перемещаем наш созданный файл к астеру на съедение.

done  echo "HAPPY END!!!"  exit 0  

Завершаем скрипт. С ним все.

Осталось только запихать его выполнение в крон. Не забудьте дать ему права на исполнение.

 2       0          *       *       *       /usr/bin/my/alarm.sh  

Ну, в общем-то, будильник готов. Заполняем alarmnumbers.txt и ждем звонка. У нас исправно работает уже 3 недели. Глюков пока не обнаружено.

Что в итоге?

Мы получили будильник с расписанием. Есть возможность исключать любые дни недели из расписания. Система будет создавать call-файлы, а астериск выполнять, когда наступит подходящее время. Ничего сложного.

Что плохо:

  • Запуск раз в сутки. Если захочется проснуться сегодня через 4 часа, астер ничего не сделает, звонок будет только через неделю.
  • Критично содержание alarmnumbers.txt. Если в нем будет косяк по неаккуратному заполнению, звонка не будет. Самому астеру ничего, конечно, не будет, но все равно неприятно.
  • Требуется заранее конвертировать звуковой файл в нужный формат. Автоконвертацию прикрутить поленился.
  • Коллега все равно не реагирует и на этот будильник.

Приветствуется критика, замечания, пожелания по улучшению.

ссылка на оригинал статьи http://habrahabr.ru/post/158327/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *