Прокачиваем VoIP GSM шлюз Yeastar TG100 до мини-АТС

Подавляющее большинство готовых IP-АТС рассчитаны на компании численностью сотрудников от десяти и более человек. На деле же, в России полно фирм с двумя-пятью сотрудниками и им тоже как-то необходимо организовывать телефонную связь. Функционал готовых IP-АТС для них избыточен, а стоимость — слишком высока. Можно собрать свою собственную телефонную станцию при помощи обычного компьютера и Asterisk. Можно подключиться к VoIP-оператору связи и воспользоваться услугой «облачная АТС». А можно пойти по другому пути — взять недорогое устройство с уже предустановленным Asterisk, такое, как Yeastar TG100, и немного прокачать его функционал. Тем, кто не ищет легких путей — добро пожаловать под кат.

aedb8a87057b45d9830ed77b91cfce41.jpg
Yeastar TG100 — это VoIP GSM шлюз на одну SIM-карту и используется он, как правило, для подключения линии сотовой связи к IP-АТС по протоколу SIP. Мы же попытаемся использовать Yeastar TG100 не вместе с IP-АТС, а вместо неё. Почему в качестве подопытного мы выбрали именно GSM-шлюз? Не секрет, что многие компании в начале своей деятельности используют для связи с миром обычный мобильный номер. В процессе роста, потребности в связи увеличиваются, но и старый номер хочется сохранить — в этом смысле вариант с использованием VoIP GSM шлюза выглядит выигрышнее, чем Asterisk на компьютере или виртуальная IP-АТС.

Почему именно Yeastar? Во-первых, это наиболее качественные, на наш взгляд, VoIP GSM шлюзы, представленные на нашем рынке. Во-вторых, в данных шлюзах предусмотрена возможность получения доступа к установленному на него Asterisk и модификации конфигурационных файлов (за что инженерам стоит сказать отдельное спасибо). В-третьих, сам производитель утверждает, что VoIP GSM шлюзы Yeastar поддерживают «SIP-сервер для регистрации IP-телефонов», что зачастую вводит в заблуждение конечных пользователей, которые думают, что смогут использовать шлюз, как полноценную IP-АТС. Данная статья может быть интересна именно таким пользователям.

Наконец, почему мы выбрали самую младшую модель Yeastar TG100? Тут все просто — раз речь идет об АТС для самых маленьких, то и шлюз мы выбрали самый недорогой. При желании вместо TG100, можно взять TG200 (на две сим-карты), TG400 (на четыре) и даже TG800 (на восемь) — принципиальных изменений в их настройке не будет.

Что мы хотим получить?


Вначале определимся, какой минимальный набор функций должна иметь наша будущая IP-АТС.

  1. Внутренняя связь. IP-телефоны или софтфоны пользователей, зарегистрированных на шлюзе должны уметь звонить между собой и переводить вызовы
  2. Входящие вызовы. Входящий звонок должен попадать на интерактивное голосовое меню, которое предложит звонящему несколько вариантов соединения с сотрудниками компании
  3. SIP-провайдер. Наличие GSM-линии — это хорошо, но для полноценной телефонизации офиса не обойтись без городского номера, который проще всего получить, зарегистрировав шлюз на сервере VoIP-оператора связи
  4. Исходящие вызовы. Так как у нас будет два канала связи с миром — SIP и GSM, то шлюз должен автоматически определять, через какой именно канал ему следует совершать исходящий вызов. Мы будем использовать простой принцип — звонки на мобильные номера шлюз должен совершать через GSM-линию, на городские — через SIP


Что мы можем сделать штатными средствами?


Постараемся свести настройку шлюза через конфигурационные файлы к минимуму, используя по максимуму штатные средства настройки, то есть — Web-интерфейс. К примеру, с его помощью мы можем создать необходимое нам количество SIP-аккаунтов для подключения к шлюзу IP-телефонов пользователей. Переходим в раздел Шлюз — Линии VoIP и нажимаем Добавить линию VoIP.

72e37bb6774243699862301ba5506049.jpg

Тип линии: Аккаунт VoIP
Тип: SIP
Имя: Произвольное имя
Аккаунт: внутренний номер телефона
Пароль: сложный пароль

Повторяем эту операцию столько раз, сколько телефонов нам нужно завести. К сожалению, даже после создания всех SIP-аккаунтов внутренняя связь работать не будет, для её включения нам потребуется поработать с конфигурационными файлами.

Подключим наш Yeastar TG100 к VoIP-оператору связи, благо Web-интерфейс предоставляет для этого все возможности. В этом же разделе Шлюз — Линии VoIP вновь нажимаем Добавить линию VoIP и в поле Тип линии выберем «Линия VoIP». У каждого оператора связи свои требования к регистрации, однако, имеющихся полей вполне достаточно для успешного подключения к большинству из них.

f0470c0a036e4b3a8fbcdc38118cb89f.jpg

Тип линии: Линия VoIP
Тип: SIP
Имя: Произвольное имя
Хост/IP: IP-адрес или доменное имя SIP-сервера, а также его порт.
Домен: IP-адрес или доменное имя SIP-сервера
Пользователь: SIP ID, выданный оператором
Идентификационное имя: SIP ID, выданный оператором
Пароль: пароль, выданный оператором
From (вкладка Дополнительно): SIP ID, выданный оператором

Создать интерактивное голосовое меню через Web-интерфейс у нас, конечно, не получится. Но для него в любом случае потребуется голосовое приветствие, для загрузки которого воспользоваться Web-интерфейсом мы можем. В разделе Система — Аудиофайлы нажимаем Загрузить файл. Файл должен быть, а wav-формате и его размер не должен превышать 1.8 Мб. Допускается следующее кодирование:

gsm 6.10 8kHz, Mono,1Kb/s
alaw/ulaw 8kHz, Mono,1Kb/s
pcm 8kHz, Mono, 16Kb/s

На этом возможности Web-интерфейса заканчиваются. Настраивать внутреннюю, исходящую и входящую маршрутизацию будем уже сами.

Подключаемся к Yeastar TG100


Для подключения мы будем использовать протокол SSH, который вначале необходимо активировать на шлюзе. В разделе Система — Сетевые настройки — Настройки LAN активируем опцию Включить SSH, сохраняем и применяем изменения.

5eb13a27a8aa4e758bc0b9e78e645199.jpg

С помощью вашего любимого SSH-клиента подключитесь к шлюзу. По умолчанию порт для подключения — 8022, логин — root, пароль — ys123456. Подключившись, вы попадёте в окружение ОС Linux.

Конфигурационные файлы Астериска находятся в привычном месте — /etc/asterisk, однако напрямую в них ничего изменять нельзя, иначе после любого применения настроек в Web-интерфейсе, все ваши настройки в конфигурационных файлах будут утеряны. Для добавления или изменения настроек конфигурационных файлов Астериска предусмотрен специальный каталог — /persistent/custom-cfg. В нем находится файл gncustom.conf, содержащий названия всех конфигурационных файлов астериска, которые можно изменять или добавлять в них что-то новое.

cat /persistent/custom-cfg/gncustom.conf :
[modifyfile]
/etc/asterisk/extensions.conf
/etc/asterisk/sip.conf
/etc/asterisk/users.conf
/etc/asterisk/iax.conf
/etc/asterisk/queues.conf
/etc/asterisk/features.conf
/etc/asterisk/voicemail.conf
/etc/asterisk/meetme.conf
/etc/asterisk/rc_org.conf
/etc/asterisk/rtp.conf
/etc/asterisk/http.conf
/etc/asterisk/musiconhold.conf
/etc/asterisk/followme.conf
/etc/asterisk/logger.conf
/etc/asterisk/manager.conf
/etc/asterisk/chan_dahdi.conf
/etc/asterisk/digital-channel.conf
[replacefile]
/etc/asterisk/dahdi-channels.conf


Соответственно, файлы в разделе [modifyfile] — файлы в которых допускается изменение или дополнение существующих настроек; файлы в разделе [replacefile] — файлы которые полностью заменяются вашими настройками.
Для того, что бы произвести изменение каких-либо настроек в конфигурационном файле астериска нужно знать три параметра:

  1. Название конфигурационного файла Астериска, находящегося в папке /etc/asterisk
  2. Название раздела, указанное в квадратных скобках [раздел] в котором будет изменена соответствующая опция
  3. Название самой опции


Далее, в каталоге /persistent/custom-cfg создаётся файл с именем формата _custom.conf. Где — название конфигурационного файла в каталоге /etc/asterisk без окончания ».conf». Например, если требуется произвести изменения в файле /etc/asterisk/users.conf, то файл с изменениями будет назваться users_custom.conf. В файле с изменениями указывается раздел в квадратных скобках, так же как и в оригинальном файле, в котором требуется произвести изменение и строчкой ниже изменяемая опция с новым значением после знака равно. Пример:

[new-context]
parameter1=value1
parameter2=value2


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

Внутренние вызовы


Чуть ранее с помощью Web-интерфейса мы создали SIP-аккаунты, пусть это будет 401, 402 и 403. Конфигурация этих SIP устройств находится в файле /etc/asterisk/users.conf. Для каждого устройства используется свой собственный контекст плана набора — параметр context. Для 401 — это Voip-Account-401, для 402 — Voip-Account-402, для 403 — Voip-Account-403.
В файле плана набора /etc/asterisk/extensions.conf мы можем видеть следующую запись:

[Voip-Account-401] 
[Voip-Account-402] 
[Voip-Account-403] 


По сути это означает, что каждое созданное нами устройство находится в своем собственном и абсолютно пустом контексте плана набора. Этим и объясняется то, что внутренние вызовы по умолчанию в шлюзе не работают, а это надо исправить.

  1. Создадим специальный контекст плана набора, где будем обрабатывать исходящие вызовы с наших SIP телефонов. Оригинальный файл плана набора называется extensions.conf — соответственно создаём в каталоге /persistent/custom-cfg файл с названием extensions_custom.conf со следующим содержанием:
    [from-internal]
    ;internal routes
    exten => _4XX,1,NoOp(Internal Call)
    exten => _4XX,n,Dial(${trunk-${EXTEN}},30,Ttr)
    exten => _4XX,n,Hangup()
    
    

    Суть данной записи в том, что любой вызов на трехзначный номер, начинающийся с цифры 4, будет вызывать устройство с соответствующим номером созданным ранее в веб интерфейсе шлюза.
  2. Так же нужно разрешить нашим телефонам использовать этот контекст плана набора при совершении вызовов. Для этого в этом же файле extensions_custom.conf ниже добавим строчки:
    [Voip-Account-401]      
    include => from-internal
    
    [Voip-Account-402]
    include => from-internal
    
    [Voip-Account-403]
    include => from-internal
    
    

  3. Применяем сделанные изменения с помощью Web-интерфейса
  4. Смотрим файл /etc/asterisk/extensions.conf и убеждаемся, что сделанные нами изменения в нём появились
  5. Проверяем на деле — пробуем совершить вызов с одного внутреннего телефона на другой


Входящие вызовы


Все входящие вызовы, пришедшие, как через GSM-линию, так и через SIP-транк, мы будем отправлять в интерактивное голосовое меню со следующей структурой:

  1. Проигрывается ранее загруженный звуковой файл с голосовым приветствием. Загруженный нами файл располагается в папке /var/lib/asterisk/sounds/record
  2. Ждем от абонента донабора номера. При вводе цифры »1» вызывается абонент с номером 401. При вводе цифры »2» звонок отправляется в группу обзвона, в которой телефоны 401, 402, 403 звонят по очереди
  3. Если абонент ничего не набирает, вызов также уходит в ту же группу обзвона, но телефоны в ней звонят уже не по очереди, а одновременно


Для реализации этого функционала добавляем в файл extensions_custom.conf следующее:

[arttel-ivr]                                                             
exten => _.,1,NoOp(Custom IVR by ArtTel)                                 
exten => _.,n,Set(CDR(userfield)=SIP_TRUNK->IP)                          
exten => _.,n,Answer()                                                   
exten => _.,n,Set(TIMEOUT(digit)=2)                                                 
exten => _.,n,Background(record/arttel_ivr_alaw) ;проигрываем звуковой файл                                 
exten => _.,n,WaitExten(3) ;ждем 3 секунды для донабора номера                                                         
                                                                                    
exten => t,1,NoOp(Goto by Timeout) ;если ничего не набрано, переходим сюда                                                 
exten => t,n,Macro(arttel-ringgroup,ringall,402-403-401,15,2) ;и звоним тремя телефонами одновременно                          
exten => t,n,Hangup()                                                               
                                                                                    
exten => 1,1,NoOp(Goto by pressed 1)                                                
exten => 1,n,Dial(${trunk-401},30,T) ;если набрано «1», вызываем номер 401                                                
exten => 1,n,Hangup()                                                               
                                                                                    
exten => 2,1,NoOp(Goto by pressed 2)                                                
exten => 2,n,Macro(arttel-ringgroup,linear,402-403-401,15,2) ;если набрано «2», телефоны 402, 403 и 404 звонят по очереди                            
exten => 2,n,Hangup()

[macro-arttel-ringgroup]                                                            
;ARG1 - Type: linear, ringall                                                                                
;ARG2 - Numbers separated dash: 401-402-403                                         
;ARG3 - Time Dial for Dial app                                                      
;ARG4 - Repeat Count for linear                                                     
                                                                                    
exten => s,1,Set(RG_Type=${ARG1})                                                            
exten => s,n,Set(RG_Nums=${ARG2})                                                   
exten => s,n,NoOp(Macro RingGroup type: ${RG_Type} for numbers: $RG_Nums)           
exten => s,n,GotoIf($[ "${RG_Type}" = "linear" ]?linear,1:ringall,1)               
exten => s,n,Hangup()                                                               
                                                                                    
exten => ringall,1,Set(COUNT=1)                                                     
exten => ringall,n,Set(REPEAT_COUNT=1)                                               
exten => ringall,n,Set(Repeat=${ARG4})                                               
exten => ringall,n,Set(TimeDial=${ARG3})                                             
exten => ringall,n(loop),Set(RG_Dial=${RG_Dial}&${trunk-${CUT(RG_Nums,-,${COUNT})}})
exten => ringall,n,NoOp(RG_Dial=${RG_Dial})                                         
exten => ringall,n,Set(COUNT=$[${COUNT} + 1])                                       
exten => ringall,n,GotoIf(${CUT(RG_Nums,-,${COUNT})}?loop)                          
exten => ringall,n(repeat),Dial(${RG_Dial:1},${TimeDial},T)                                
exten => ringall,n,Set(REPEAT_COUNT=$[${REPEAT_COUNT} + 1])                          
exten => ringall,n,GotoIf($[ ${REPEAT_COUNT} <= ${Repeat} ]?repeat)                    
exten => ringall,n,Hangup()                                                         
                                                                                    
exten => linear,1,Set(COUNT=1)                                                      
exten => linear,n,Set(REPEAT_COUNT=1)                                               
exten => linear,n,Set(Repeat=${ARG4})                                               
exten => linear,n,Set(TimeDial=${ARG3})                                             
exten => linear,n(loop),Dial(${trunk-${CUT(RG_Nums,-,${COUNT})}},${TimeDial},T)    
exten => linear,n,Set(COUNT=$[${COUNT} + 1])                                        
exten => linear,n,GotoIf(${CUT(RG_Nums,-,${COUNT})}?loop)                           
exten => linear,n,Set(COUNT=1)                                                      
exten => linear,n,Set(REPEAT_COUNT=$[${REPEAT_COUNT} + 1])                          
exten => linear,n,GotoIf($[ ${REPEAT_COUNT} <= ${Repeat} ]?loop)                    
exten => linear,n,Hangup()


Наш контекст с голосовым приветствием создан, теперь в него необходимо отправить все входящие вызовы, как с GSM-канала, так и с SIP-транка. Для этого создадим файл users_custom.conf в папке /persistent/custom-cfg со следующим содержанием:

[gsm_1]
context=arttel-ivr

[trunk-arttel_telecom]
context=arttel-ivr


Сохраняем и принимаем сделанные изменения через Web-интерфейс.

Исходящие вызовы


Последнее, что нам осталось сделать — настроить логику исходящих вызовов. Она будет следующей:

  1. Звонки на все мобильные номера, начинающиеся на 89… будем выпускать через GSM канал
  2. Звонки по России, номера которых состоят из 10 знаков, и начинаются с 83…, 84… или 88… будем выпускать через SIP провайдера
  3. Звонки на международные номера, начинающиеся на 810… будем так же выпускать через канал GSM


Для этого в уже созданный нами файл extensions_custom.conf в раздел [from-internal] добавим следующее:

;outbound routes
;STRATEGY: 0 - default(first free), 1 - linear(linear with memories), 2- balance
exten => _89XX.,1,NoOp(Outbound dial to Mobile)
exten => _89XX.,n,Set(CDR(userfield)=IP->MOBILE)
exten => _89XX.,n,Set(STRATEGY=0)                                                                                                  
exten => _89XX.,n,Macro(trunkdial-failover-0.4,1,,${EXTEN:0},trunk-GSM1,)
exten => _89XX.,n,Hangup()
                                                                                             
exten => _8[348]XXXXXXXXX,1,NoOp(Outbound dial to Russia)
exten => _8[348]XXXXXXXXX,n,Set(CDR(userfield)=IP->SIP_TRUNK)
exten => _8[348]XXXXXXXXX,n,Set(STRATEGY=0)
exten => _8[348]XXXXXXXXX,n,Macro(trunkdial-failover-0.4,1,,${EXTEN:0},trunk-arttel_telecom,)
exten => _8[348]XXXXXXXXX,n,Hangup()
                                                                                    
exten => _810XX.,1,NoOp(Outbound dial to International)
exten => _810XX.,n,Set(CDR(userfield)=IP->MOBILE)
exten => _810XX.,n,Set(STRATEGY=0)
exten => _810XX.,n,Macro(trunkdial-failover-0.4,1,,${EXTEN:0},trunk-GSM1,) ; 1 trunk
exten => _810XX.,n,Hangup()


Какие правила за какое направления отвечают не сложно понять по шаблону номера расширения: _89XX. — мобильные номера, _8[348]XXXXXXXXX — вызовы по России, _810XX. — вызовы на международные направления. За отправку вызовов через определенный транк отвечает макрос trunkdial-failover-0.4. В первом аргументе указывается количество используемых для исходящего вызова линий. В последнем аргументе перечисляются транки, через которые исходящий вызов может быть совершен. К примеру, если бы мы работали с четырехпортовым шлюзом Yeastar TG400 вместо однопортового Yeastar TG100, то строчку:

exten => _89XX.,n,Macro(trunkdial-failover-0.4,1,,${EXTEN:0},trunk-GSM1,)  


следовало бы заменить на:

exten => _89XX.,n,Macro(trunkdial-failover-0.4,4,,${EXTEN:0},trunk-GSM1,trunk-GSM2,trunk-GSM3,trunk-GSM4,)


Сохраняем и применяем внесенные нами изменения.

Заключение


В результате произведенных изменений, мы получили вполне работоспособное решение, готовое совершенно спокойно обслуживать офис из 2–10 человек. Да, оно не поддерживает такие дополнительные функции, как запись и прослушивание разговоров, парковка вызова, конференц-связь, голосовая почта и другие. Но, по правде говоря, для самых маленьких компаний, все эти функции являются мало востребованными. Зато данное решение отличается компактностью, низким энергопотреблением и поддержкой GSM-линии. А при наличии времени, желания и фантазии, VoIP GSM шлюз Yeastar TG100 можно дополнить еще многими интересными функциями.

© Geektimes