Макрос для балансировки исходящих звонков на GSM в Asterisk

в 22:26, , рубрики: asterisk, gsm, linux, sip, балансировка, телефония, метки: , , ,
Привет!

В прошлом топике(уже в черновиках) я обещал предоставить хабрасообществу действующий макрос для балансировки исходящих звонков через N-ное количество сим-карт. Сабж, собственно, найден, усовершенствован и протестирован. Плюс — он гарантирует, что симка с превышенным лимитом использоваться не будет.

Дано: FreeBSD 9, Asterisk 11.4, 2х Addpac GS1002 (используются все 4 сим-карты). Настроено 4 транка на симки: 9001, 9002, 9003, 9004 соответственно. На них полосатый тариф с «безлимитом» 300 минут в месяц на каждой.
Задача: Если на какой-либо симке исчерпан лимит, не использовать ее при наборе. Если же исчерпаны все — слать звонок через провайдера (там чуть дешевле, чем через GSM с тарификацией)

1. Настраиваем сохранение cdr в mysql

Не вижу смысла копипастить сюда мануал. Добавлю лишь, проверьте наличие модуля cdr_mysql.so в своей сборке.

2. Добавляем контекст с макросом в extensions.conf(для работы необходим модуль app_mysql.so — Simple Mysql Interface!)

Сам макрос подробно прокомментирован.

[macro-gsm]

exten => s,1(start),Set(ARG2=$[${ARG2} + 1]) ;инкремент, подробности чуть ниже
same => n,GotoIf($[${ARG2}>=9005]?sip:repeat) ;У нас 4 транка, предлагает 9005 - пускаем через провайдера
same => n(repeat),MYSQL(Connect connid localhost asterisk password asterisk) ; Подключаемся к базе
same => n,MYSQL(Query resultid ${connid} SELECT SUM(`billsec`) FROM `cdr` WHERE `dstchannel` LIKE '%${ARG2}%' AND MONTH(`calldate`)=MONTH(NOW()) AND YEAR(`calldate`)=YEAR(NOW())) ; Собственно запрос. Результат - суммарное количество тарифицируемых секунд на текущем транке за текущий месяц
same => n,MYSQL(Fetch fetchid ${resultid} duration) ; Результат в переменную duration
same => n,MYSQL(Clear ${resultid}) ;Очистка и отключение от базы
same => n,MYSQL(Disconnect ${connid})
same => n,GotoIf($[${duration}<=18000]?call:start) ; Если через транк прошло менее 300 минут, посылаем звонок через него, нет - отправляемся в начало, в следующем круге используется транк с большим номером
same => n(call),Dial(SIP/${ARG2}/${ARG1},,tkr) ;Звоним
same => n,GotoIf($[${DIALSTATUS}=ANSWER]?end:start) ;Разговор состоялся - кладем трубку, транк занят - следующий круг
same => n(sip),Dial(SIP/ctm/${ARG1},,Ttr) ;Звонок через провайдера
same => n(end),Hangup ;Кладем трубку

exten => h,1,MYSQL(Clear ${resultid}) ; Еще команды на отключение от базы, для перестраховки. 
same => n,MYSQL(Disconnect ${connid})


Пример вызова в диалплане: exten => _79XXXXXXXXX,1,Macro(gsm,${EXTEN},9000)
9000: номер транка — 1

Макрос протестирован и работает. Очевидные минусы — неоптимизированный запрос, названия транков только цифровые. Есть желание помочь — предлагайте в комментариях свои варианты. Плюс — он эффективен)

Спасибо pfactum, PyroRed и Malamut за вдохновение.

Автор: Sl1mShady

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js