Ограничение максимального количества вызовов через транки
В статье рассматривается установка ограничений по максимальному количеству занятых каналов в общем (для всех имеющихся транков) и в частности (для каждого отдельного транка). Установка ограничений по количеству звонков для отдельного транка. В веб-админке Freepbx ограничение для определенного транка можно установить, перейдя Connectivity —> Trunks (Маршрутизация —> Городские линии) и, открыв необходимый транк для редактирования, изменить […]
В статье рассматривается установка ограничений по максимальному количеству занятых каналов в общем (для всех имеющихся транков) и в частности (для каждого отдельного транка).
Установка ограничений по количеству звонков для отдельного транка.
В веб-админке Freepbx ограничение для определенного транка можно установить, перейдя Connectivity —> Trunks (Маршрутизация —> Городские линии) и, открыв необходимый транк для редактирования, изменить параметр Maximum Channels (Количество каналов).
Также, можно установить ограничение в конфигурационных файлах с помощью параметра call-limit. Например, установить ограничение для какого-либо определенного sip транка в Asterisk Vanilla можно добавив параметр call-limit в файле sip.conf, во Freepbx — в веб-интерфейсе, для кастомных транков, не присутствующих в веб-интерфейсе — в файле sip_custom.conf. В примере для транка sip_trunk1 установлено ограничение в два канала, для транка sip_trunk2 ограничений нет.
При превышении ограничений для отдельного транка в консоли появляется сообщение
Call to peer ‘sip_trunk1’ rejected due to usage limit of 2
Установка ограничений по общему количеству звонков через все транки.
Предположим, что имеются несколько офисов, имеющими транки от провайдеров и межофисные транки. Необходимо, чтобы одновременно было не более (в примере — 2-х) внешних вызовов (входящих или исходящих), при этом внутренние вызовы – без ограничений. На всех офисных серверах добавочные нумеруются по правилам. На первом имеют вид 1XX (для custom extension, напр. мобильных — нумерация вида 01XXX), на втором – 2XX (02XXX)… Таким образом, определить локальный вызов, например, во втором офисе, можно, если переменная CALLERID(num) будеть иметь длину в 3 цифры и начинаться с ‘2’ и
- либо набран номер длиной в 3 цифры и первая ‘2’ – на попадающий под шаблон нумерации локальный номер;
- либо набран номер в 4 цифры и первые ’02’ — на локальный кастомный номер (напр. мобильный).
Для внесения ограничений по вызовам через транки необходимо немного изменить диалплан.
Копируем из extensions_additional.conf extensions_override_freepbx.conf и вносим изменения. В macro-dialout-trunk – ограничения для исходящих вызовов через транки. В macro-dial-one – ограничения для входящих вызовов. Пример — диалплан для офиса с нумерацией 2XX(02XX).
[macro-dialout-trunk]
include => macro-dialout-trunk-custom
exten => s,1,Set(DIAL_TRUNK=${ARG1})
;вносим изменения – задание группы и подсчет звонков
exten => s,n(checkcalls),Set(GROUP()=callers)
exten => s,n,NoOp(--- занято каналов - ${GROUP_COUNT(callers)} ---)
;устанавливаем ограничение в 2 занятых канала, если ограничение превышено – переход на ;именованный приоритет over и отбой
exten => s,n,GotoIf($[${GROUP_COUNT(callers)} > 2]?over)
;для тестирования внесенных изменений можно использовать DumpChan – выведет список ;всех имеющихся на данный момент переменных и их значение
;exten => s,n,DumpChan()
;конец изменений, продолжение диалплана контекста macro-dialout-trunk из
;extensions_additional.conf
exten => s,n,GosubIf($[$["${ARG3}" != ""] & $["${DB(AMPUSER/${AMPUSER}/pinless)}" != "NOPASSWD"]]?sub-pincheck,s,1())
exten => s,n,GotoIf($["x${OUTDISABLE_${DIAL_TRUNK}}" = "xon"]?disabletrunk,1)
exten => s,n,Set(DIAL_NUMBER=${ARG2})
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${DIAL_OPTIONS})
exten => s,n,Set(OUTBOUND_GROUP=OUT_${DIAL_TRUNK})
exten => s,n,GotoIf($["${OUTMAXCHANS_${DIAL_TRUNK}}foo" = "foo"]?nomax)
exten => s,n,GotoIf($[ ${GROUP_COUNT(OUT_${DIAL_TRUNK})} >= ${OUTMAXCHANS_${DIAL_TRUNK}} ]?chanfull)
exten => s,n(nomax),GotoIf($["${INTRACOMPANYROUTE}" = "YES"]?skipoutcid)
exten => s,n,Set(DIAL_TRUNK_OPTIONS=${IF($["${DB_EXISTS(TRUNK/${DIAL_TRUNK}/dialopts)}" = "1"]?${DB_RESULT}:${TRUNK_OPTIONS})})
exten => s,n,Macro(outbound-callerid,${DIAL_TRUNK})
exten => s,n(skipoutcid),GosubIf($["${PREFIX_TRUNK_${DIAL_TRUNK}}" != ""]?sub-flp-${DIAL_TRUNK},s,1())
exten => s,n,Set(OUTNUM=${OUTPREFIX_${DIAL_TRUNK}}${DIAL_NUMBER})
exten => s,n,Set(custom=${CUT(OUT_${DIAL_TRUNK},:,1)})
exten => s,n,ExecIf($["${MOHCLASS}"!="default" & "${MOHCLASS}"!="" & "${FORCE_CONFIRM}"="" ]?Set(DIAL_TRUNK_OPTIONS=M(setmusic^${MOHCLASS})${DIAL_TRUNK_OPTIONS}))
exten => s,n,ExecIf($["${FORCE_CONFIRM}"!="" ]?Set(DIAL_TRUNK_OPTIONS=${DIAL_TRUNK_OPTIONS}M(confirm)))
exten => s,n(gocall),Macro(dialout-trunk-predial-hook,)
exten => s,n,GotoIf($["${PREDIAL_HOOK_RET}" = "BYPASS"]?bypass,1)
exten => s,n,GotoIf($["${custom}" = "AMP"]?customtrunk)
exten => s,n,Dial(${OUT_${DIAL_TRUNK}}/${OUTNUM}${OUT_${DIAL_TRUNK}_SUFFIX},${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS})
exten => s,n,Noop(Dial failed for some reason with DIALSTATUS = ${DIALSTATUS} and HANGUPCAUSE = ${HANGUPCAUSE})
exten => s,n,GotoIf($["${ARG4}" = "on"]?continue,1:s-${DIALSTATUS},1)
exten => s,n(customtrunk),Set(pre_num=${CUT(OUT_${DIAL_TRUNK},$,1)})
exten => s,n,Set(the_num=${CUT(OUT_${DIAL_TRUNK},$,2)})
exten => s,n,Set(post_num=${CUT(OUT_${DIAL_TRUNK},$,3)})
exten => s,n,GotoIf($["${the_num}" = "OUTNUM"]?outnum:skipoutnum)
exten => s,n(outnum),Set(the_num=${OUTNUM})
exten => s,n(skipoutnum),Dial(${pre_num:4}${the_num}${post_num},${TRUNK_RING_TIMER},${DIAL_TRUNK_OPTIONS})
exten => s,n,Noop(Dial failed for some reason with DIALSTATUS = ${DIALSTATUS} and HANGUPCAUSE = ${HANGUPCAUSE})
exten => s,n,GotoIf($["${ARG4}" = "on"]?continue,1:s-${DIALSTATUS},1)
exten => s,n(chanfull),Noop(max channels used up)
; вносим изменения
;если лимит по вызовам превышен – переход в over, выводим сообщение и устанавливаем статус вызова CONGESTION – канал перегружен
exten => s,n(over),NoOp(--- каналы заняты, установленное ограничение превышено на ${MATH(${GROUP_COUNT(callers)}-2)} вызова ---)
exten => s,n,Set(DIALSTATUS=CONGESTION)
;конец изменений
[macro-dial-one]
include => macro-dial-one-custom
exten => s,1,Set(DEXTEN=${ARG3})
;вносим изменения – задание группы и подсчет звонков
;Если вызов - не на внешние или в др. офис – вызов проходит, иначе - подсчет ограничений
;Вызов локальный, если
; CALLERID(num) 3 цифры и первая '2' - с локального и
;если набран номер (3 цифры) и первая '2' - локальный номер
exten => s,n,GotoIf($[${LEN(${EXTTOCALL})}=3 & ${EXTTOCALL:0:1}=2 & ${LEN(${CALLERID(num)})}=3 & ${CALLERID(num):0:1}=2]?setexttocall)
;Также вызов локальный, если
;CALLERID(num) 3 цифры и первая '2' - с локального и
;если набран номер (4 цифры) и первые '02' - на локальный номер (custom - напр. мобильный)
exten => s,n,GotoIf($[${LEN(${EXTTOCALL})}=4 & "${EXTTOCALL:0:2}"="02" & ${LEN(${CALLERID(num)})}=3 & ${CALLERID(num):0:1}=2]?setexttocall)
;установка группы и подсчет ограничений
exten => s,n(checkcalls),Set(GROUP()=callers)
exten => s,n,NoOp(--- занято каналов - ${GROUP_COUNT(callers)} ---)
;если ограничение по каналам превышено – переход на именованный приоритет over и отбой
exten => s,n,GotoIf($[${GROUP_COUNT(callers)} > 2]?over)
;конец внесенных изменений
exten => s,n(setexttocall),ExecIf($[${LEN(${EXTTOCALL})}=0 & ${LEN(${DEXTEN})}>0]?Set(EXTTOCALL=${DEXTEN}))
exten => s,n,Set(DIALSTATUS_CW=)
exten => s,n,GosubIf($["${FROM_DID}"!="" & "${SCREEN}"="" & "${DB(AMPUSER/${DEXTEN}/screen)}"!=""]?screen,1())
exten => s,n,GosubIf($["${DB(CF/${DEXTEN})}"!=""]?cf,1())
exten => s,n,GotoIf($["${DEXTEN:-1}"="#" | "${DB(DND/${DEXTEN})}"=""]?skip1)
exten => s,n,Set(DEXTEN=)
exten => s,n,Set(DIALSTATUS=BUSY)
exten => s,n,Goto(nodial)
exten => s,n(cwinusebusy),GotoIf($["${EXTHASCW}"!="" & "${CWINUSEBUSY}"="true"]?next3:continue)
exten => s,n(next3),ExecIf($["${EXTENSION_STATE(${DEXTEN})}"!="UNAVAILABLE" & "${EXTENSION_STATE(${DEXTEN})}"!="NOT_INUSE" & "${EXTENSION_STATE(${DEXTEN})}"!="UNKNOWN"]?Set(DIALSTATUS_CW=BUSY))
exten => s,n(continue),GotoIf($["${DEXTEN}"=""]?nodial)
exten => s,n,GosubIf($["${DEXTEN:-1}"!="#"]?dstring,1():dlocal,1())
exten => s,n,GotoIf($[${LEN(${DSTRING})}=0]?nodial)
exten => s,n,GotoIf($["${DEXTEN:-1}"="#"]?skiptrace)
exten => s,n,GosubIf($[${REGEX("^[\+]?[0-9]+$" ${CALLERID(number)})} = 1]?ctset,1():ctclear,1())
exten => s,n(skiptrace),Set(D_OPTIONS=${IF($["${NODEST}"!="" & ${REGEX("(M[(]auto-blkvm[)])" ${ARG2})} != 1]?${ARG2}M(auto-blkvm):${ARG2})})
exten => s,n,Noop(Blind Transfer: ${BLINDTRANSFER}, Attended Transfer: ${ATTENDEDTRANSFER}, User: ${AMPUSER}, Alert Info: ${ALERT_INFO})
exten => s,n,ExecIf($["${ALERT_INFO}"="" & ${LEN(${AMPUSER})}!=0 & ${LEN(${BLINDTRANSFER})}=0 & ${LEN(${ATTENDEDTRANSFER})}=0]?Set(ALERT_INFO=))
exten => s,n,ExecIf($[${LEN(${BLINDTRANSFER})}!=0]?Set(ALERT_INFO=))
exten => s,n,ExecIf($[${LEN(${ATTENDEDTRANSFER})}!=0]?Set(ALERT_INFO=))
exten => s,n,ExecIf($["${RVOL}"!=""]?Set(ALERT_INFO=${IF($["${ALERT_INFO}"!=""]?${ALERT_INFO}:Normal)}\;volume=${RVOL}))
exten => s,n,ExecIf($["${RVOL}"="" & "${DB(AMPUSER/${EXTTOCALL}/rvolume)}" != ""]?Set(ALERT_INFO=${IF($["${ALERT_INFO}"!=""]?${ALERT_INFO}:Normal)}\;volume=${DB(AMPUSER/${EXTTOCALL}/rvolume)}))
exten => s,n,GosubIf($["${ALERT_INFO}"!="" & "${ALERT_INFO}"!=" "]?func-set-sipheader,s,1(Alert-Info,${ALERT_INFO}))
exten => s,n,ExecIf($[("${MOHCLASS}"!="default") & ("${MOHCLASS}"!="")]?Set(CHANNEL(musicclass)=${MOHCLASS}))
exten => s,n,GosubIf($["${QUEUEWAIT}"!=""]?qwait,1())
exten => s,n,Set(__CWIGNORE=${CWIGNORE})
exten => s,n,Set(__KEEPCID=TRUE)
exten => s,n,GotoIf($["${USEGOTO}"="1"]?usegoto,1)
exten => s,n,Set(CALLEE_USERAGENT=${SIPPEER(${DEXTEN},useragent)})
exten => s,n,ExecIf(${REGEX("^Fanvil" ${CALLEE_USERAGENT})}?AGI(cut_callerid.pl,CALLERID(name),29,bytes))
exten => s,n,GotoIf($["${DB(AMPUSER/${EXTTOCALL}/cidname)}" = "" || "${DB(AMPUSER/${AMPUSER}/cidname)}" = ""]?godial)
exten => s,n,Set(CONNECTEDLINE(name,i)=${DB(AMPUSER/${EXTTOCALL}/cidname)})
exten => s,n,Set(CALLER_USERAGENT=${SIPPEER(${AMPUSER},useragent)})
exten => s,n,GotoIf($[${REGEX("^Fanvil" ${CALLER_USERAGENT})} = 0]?skip_cut_clname)
exten => s,n,Set(CUR_CONNECTEDLINE_NAME=${CONNECTEDLINE(name)})
exten => s,n,AGI(cut_callerid.pl,CUR_CONNECTEDLINE_NAME,39,bytes)
exten => s,n,Set(CONNECTEDLINE(name,i)=${CUR_CONNECTEDLINE_NAME})
exten => s,n(skip_cut_clname),Set(CONNECTEDLINE(num)=${EXTTOCALL})
exten => s,n,Set(D_OPTIONS=${D_OPTIONS}I)
exten => s,n(godial),Macro(dialout-one-predial-hook,)
exten => s,n,ExecIf($["${DIRECTION}" = "INBOUND"]?Set(D_OPTIONS=${STRREPLACE(D_OPTIONS,T)}I))
exten => s,n(dialapp),Noop()
exten => s,n,Dial(${DSTRING},${ARG1},${D_OPTIONS}b(func-apply-sipheaders^s^1))
exten => s,n,ExecIf($["${DIALSTATUS}"="ANSWER" & "${CALLER_DEST}"!=""]?MacroExit())
exten => s,n,ExecIf($["${DIALSTATUS_CW}"!=""]?Set(DIALSTATUS=${DIALSTATUS_CW}))
exten => s,n,GosubIf($[("${SCREEN}"!=""&("${DIALSTATUS}"="TORTURE"|"${DIALSTATUS}"="DONTCALL"))|"${DIALSTATUS}"="ANSWER"]?s-${DIALSTATUS},1())
exten => s,n,MacroExit()
exten => s,n(nodial),Noop()
exten => s,n,ExecIf($["${DIALSTATUS}" = ""]?Set(DIALSTATUS=NOANSWER))
exten => s,n,Noop(Returned from dial-one with nothing to call and DIALSTATUS: ${DIALSTATUS})
exten => s,n,MacroExit()
;внесение изменений
;если лимит по вызовам превышен – переход в over, выводим сообщение и устанавливаем статус вызова CONGESTION – канал перегружен
exten => s,n(over),NoOp(--- каналы заняты, установленное ограничение превышено на ${MATH(${GROUP_COUNT(callers)}-2)} вызова ---)
exten => s,n,Set(DIALSTATUS=CONGESTION)
;конец внесения изменений
После внесения изменений в маршрутизации, необходимо выполнить dialplan reload для их применения.
В Asterisk CLI dialplan reload
или
В консоли Linux asterisk –rx ‘dialplan reload’
В случае превышения установленного лимита на внешние вызовы вызов будет сброшен и в консоли появится сообщение.
При этом локальные вызовы между сотрудниками одного офиса не ограничиваются
Остались вопросы?
Я - Першин Артём, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.
категории
- DECT
- Linux
- Вспомогательный софт при работе с Asterisk
- Интеграция с CRM и другими системами
- Интеграция с другими АТС
- Использование Elastix
- Использование FreePBX
- Книга
- Мониторинг и траблшутинг
- Настройка Asterisk
- Настройка IP-телефонов
- Настройка VoIP-оборудования
- Новости и Статьи
- Подключение операторов связи
- Разработка под Asterisk
- Установка Asterisk
VoIP оборудование
ближайшие курсы
Новые статьи
10 доводов в пользу Asterisk
Распространяется бесплатно.
Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.
Безопасен в использовании.
Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.
Надежен в эксплуатации.
Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.
Гибкий в настройке.
Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.
Имеет огромный функционал.
Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.
Интегрируется с любыми системами.
То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.
Позволяет телефонизировать офис за считанные часы.
В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.
Отличная масштабируемость.
Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.
Повышает управляемость бизнеса.
Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.
Снижает расходы на связь.
Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.