пятница, 17 марта 2017 г.

Ограничение вызовов в транке по количеству и времени.

Я пользуюсь услугами оператора sipnet, а именно бесплатными звонками по городским номерам Москвы и Питера. Бесплатность как бы условная  - на счету надо иметь не менее 10 у.е., и тогда появляется возможность совершать 5 разговоров в сутки,  общей продолжительностью 30 мин. Для следования этим ограничениям был написан следующий диалплан.
Скорее всего это не самая изящная, а наверное даже громоздкая  в части обработки переменнных конструкция, но тем не менее рабочая, и позволяющая сэкономить мои, и если захотите, ваши средства.

В /etc/asterisk/extensions.conf:

[sipnet]

exten => _7XXXXXXXXXX, 1, NoOp(=calling_sipnet=)

exten => _7XXXXXXXXXX, n, Set(TOTALCOUNT=5);общее количество возможных звонков
exten => _7XXXXXXXXXX, n, Set(CUR_COUNT=${SHELL(/home/asterisk/sipnet/count.sh)}) ;проверяем сколько звонков уже совершили
exten => _7XXXXXXXXXX, n, Set(ALLOW_COUNT=$[${TOTALCOUNT} - ${CUR_COUNT}]) ;отнимаем из значения одной переменной значение другой и выводим в третью переменную
exten => _7XXXXXXXXXX, n, ExecIf($[${ALLOW_COUNT} = 0]?Playback(tt-weasels)) ;в случае если значение полученной выше переменной равно 0 проигрываем звуковой файл
exten => _7XXXXXXXXXX, n, ExecIf($[${ALLOW_COUNT} = 0]?Hangup()) ;и кладем трубку

exten => _7XXXXXXXXXX, n, Set(TOTALTIME=1740) ;количество разрешенных секунд (я сознательно уменьшил на 60 секунд)
exten => _7XXXXXXXXXX, n, Set(CUR_TIME=${SHELL(/home/asterisk/sipnet/time.sh)}) ;получаем в переменную значение сколько секунд уже наговорили
exten => _7XXXXXXXXXX, n, Set(ALLOW_TIME=$[${TOTALTIME} - ${CUR_TIME}]) ;получаем в переменную сколько секунд осталось на разговоры
exten => _7XXXXXXXXXX, n, ExecIf($[${ALLOW_TIME} < 41]?Playback(tt-somethingwrong)) ; если менее 41 секунды - проигрываем файл
exten => _7XXXXXXXXXX, n, ExecIf($[${ALLOW_TIME} < 41]?Hangup()) ;и кладем трубку
exten => _7XXXXXXXXXX, n, Set(ALLOW_TIME_MILL=$[${ALLOW_TIME} * 1000]) ;для дальнейшего использования получаем из разрешенных секунд милисекунды

exten => _7XXXXXXXXXX, n, Set(LIMIT_WARNING_FILE=beep) ;проиграем beep в начале (типа время пошло)
exten => _7XXXXXXXXXX, n, Dial(SIP/${EXTEN}@sipnet,50,L(${ALLOW_TIME_MILL}:31000)) ;звоним 50 сек. задав длительность разговора значением ранее полученной переменной, за 31 сек. до конца разговора сообщим, что скоро время закончится (вспомним тут про 41 секунду фигурировавшую ранее)
exten => _7XXXXXXXXXX, n, Playback(vm-nobodyavail) ;в случае если никто не ответил или занято проиграем файл 
exten => _7XXXXXXXXXX, n, Hangup() ;и положим трубку

В диалплане используются два bash скрипта, получающиеие значения из базы:

cat count.sh
#!/bin/bash
echo "SELECT COUNT('id') FROM cdr WHERE calldate >= CURDATE() and dstchannel like '%sipnet%' and disposition like 'ANSWERED';" | mysql -uasterisk_read -ppassw0rd asterisk | tail -n1

cat time.sh
#!/bin/bash
echo "SELECT SUM(billsec) FROM cdr WHERE calldate >= CURDATE() and dstchannel like '%sipnet%';" | mysql -uasterisk_read -ppassw0rd asterisk | tail -n1

 Соответственно, чтобы все это работало mysql база содержащая таблицу CDR должна быть подключена к Asterisk.

Еще раз поясню:
Если уже было 5-ть попыток - проигрываем звуковой файл и сбрасываем звонок.

Определяем сколько секунд осталось говорить, (я сократил на минуту общую продолжительность на всякий случай на 60 секунд), если это значение менее 41 секунды проигрываем звуковой файл, и обрываем соединение, затем умножаем значение секунд которые можно говорить на 1000 для получения единицы в милисекундах и подставляем это значение в аргумент продолжительности разговора, когда до конца будет оставаться 31 секунда проигрывается сообщение сообщающее время оставшегося разговора, затем произойдет разрыв. Отсюда и значение 41 секунда - типа все равно за 41 секунду не поговорить, все равно через 10 сек проиграет сообщение о скором принудительном разрыве.