Как стать автором
Обновить

Переадресация на мобильный и СМС-уведомление при отсутствии ответа. Одна из возможных реализаций «обратного» звонка

Время на прочтение8 мин
Количество просмотров17K
Всем доброго времени суток!

В данной статье хочу описать свой вариант реализации некоторого функционала, реализованного на моем Asterisk-сервере.

Описано:
— вариант реализации переадресации на мобильные, используя двухканальный SIP-GSM шлюз и многоканальный Мультифон;
— SMS-уведомление абонента посредством бесплатной услуги email2sms;
— реализация «прямого» входа в общий внутренний план нумерации для мобильного абонента программным (для Android) и аппаратным (SIM-Dialer для обычных мобильников) способами.

Подробности под катом.

Не претендую на идеальность представляемого сообществу кода, выкладываю «как есть». Буду рад, если кому-либо пригодятся мои наработки.

В нашей организации ведомственная телефонная сеть преимущественно построена на Si2000 и только у нас используется DX-500.

КАРТИНКА по теме для тех кому интересно:
Все картинки сделаны для конкурса молодежных проектов на нашем предприятии и из соображений безопасности на них полностью отсутствует стык с интернет (ну и мультифон как следствие).


...


Для стыка «моего» IP-сервера с «моей» АТС (DX-500) используется Quasar-M (PCI-шина) на один поток PRI E1. Внутренняя нумерация в пределах предприятия преимущественно пятизначная: 2хххх — 5хххх. В «моем» филиале (на моей DX-500) выделены и используются номера 54ххх. Весь сегмент 55ххх у меня уходит на Asterisk.

КАРТИНКА - Визуализация маршрута - ОСТОРОЖНО ЮМОР - для тех кому интересно:

...


Переадресацию абоненты устанавливают и снимают сами -112 55ххх (сервисный код DX-500). Нумерация прозрачная — номеру 54705 на DX соответствует 55705 на Asterisk.

На Asterisk использую AstDB:
xxx*CLI> database show transfer
/transfer/55705: 7922xxxXXxx
...


Asterisk, получая из потока Е1 входящий на «виртуальный» номер вида 55xxx, проверяет его базе transfer и в случае наличия осуществляет исходящий вызов на соответствующий мобильный.

кусок pri_inc.conf:

exten => _5XXXX,1,Set(Dest4Call=0); Сбрасываем значение переменной
; 0 — прямой звонок, 1 — переадресация. Используем
; значение этой переменной в макросе звонков на мобильные
; для автодозвона в случае не ответа адресата
exten => _5XXXX,n,Set(MobNumber=${DB(transfer/${EXTEN})}); берем из базы соответствующий мобильный если есть
exten => _5XXXX,n,GotoIf($[${ISNULL(${MobNumber})}]?internal:transfer); проверяем есть или нет и переходим по меткам
; если MobNumber пустой — internal, иначе — redirect
exten => _5XXXX,n(internal),Dial(SIP/${EXTEN},60,tm); входящий с Е1 DX — звоним на SIP-аккаунт с соответствующим номером
exten => _5XXXX,n,Dial(DAHDI/g0/${EXTEN},60,tm); входящий с Е1 DX — звоним на SIP-аккаунт с соответствующим номером
exten => _5XXXX,n,Hangup()
exten => _5XXXX,n(transfer),Background(/my_sounds/call-forward); проигрываем «переадресация вызова»
exten => _5XXXX,n,Set(Dest4Call=${CALLERID(number)}); Сохраняем номер звонившего в переменной
exten => _5XXXX,n,Macro(dial-mobile,${MobNumber},${Dest4Call}); используем макрос звонков на мобильные через GSM-шлюзы и мультифон
; ARG1 — MobNumber, ARG2 — Dest4Call


У меня в системе используется «железный» GSM-шлюз — каналы 1 и 2, аккаунт мультифона прикручен каналом номер 3.

Исходящие идут по свободному каналу. Приоритеты заданы условиями в диалплане 1->2->3. Создана отдельная база GSM-Channels — в ней я иногда выключаю какой-либо канал по мере необходимости.
кусок extensions.conf относительно исходящих на GSM:

; — [macro-dial-mobile]; Макрос для исходящих на МЕГАФОН звонков
; — exten => s,1,Set(Call_Dial_status=Blank); Сохраняем статус звонка для последующей отправки смс
exten => s,n,Set(Dest_number=${ARG2}); Используем переменную для номера адресата
exten => s,n,ExecIF( $[ "${Dest_number}" == «unknown» ]?Set(Dest_number=${CALLERID(num)}))
exten => s,n,NoOP(«USLOVIE CHANNEL 1»)
exten => s,n(dial_ch1),GotoIf($["${DB(GSM-Channels/GSM-Channel-1_status)}" = «off»]?dial_ch2); проверяем включен ли канал
; в базе данных GSM-Channels
exten => s,n,Dial(${GSM-Channel-1}/00${ARG1},30,gmt); Звоним через 1-й GSM-канал — 0116
exten => s,n,Set(Call_Dial_status=${DIALSTATUS}); передаем результат вызова для анализа
exten => s,n,Noop(«Dialstatus is — ${Call_Dial_status}»)
exten => s,n,GotoIf($["${Call_Dial_status}" = «BUSY»]?sms); если абонент занят или отбил звонок
exten => s,n,GotoIf($["${Call_Dial_status}" = «CANCEL»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «CONGESTION»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «NOANSWER»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «ANSWER»]?complete_call); если нет — продолжаем

exten => s,n,NoOP(«USLOVIE CHANNEL 2»)
exten => s,n(dial_ch2),GotoIf($["${DB(GSM-Channels/GSM-Channel-2_status)}" = «off»]?dial_ch3); проверяем включен ли канал
; в базе данных GSM-Channels
exten => s,n,Dial(${GSM-Channel-2}/01${ARG1},30,gmt); Звоним через 2-й GSM-канал — 0117
exten => s,n,Set(Call_Dial_status=${DIALSTATUS}); передаем результат вызова для анализа
exten => s,n,Noop(«Dialstatus is — ${Call_Dial_status}»)
exten => s,n,GotoIf($["${Call_Dial_status}" = «BUSY»]?sms); если абонент занят или отбил звонок
exten => s,n,GotoIf($["${Call_Dial_status}" = «CANCEL»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «CONGESTION»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «NOANSWER»]?sms); если нет — продолжаем
exten => s,n,GotoIf($["${Call_Dial_status}" = «ANSWER»]?complete_call); если нет — продолжаем

3-й канал — «многоканальный» мультифон, ограничен лишь опцией call-limit в sip.conf.

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

Наш Asterisk отправляет сформированное специальным образом e-mail письмо на почтовый ящик мобильного абонента. В итоге мобильный абонент получает текст письма в виде SMS. Реализованная функция совершенно бесплатна и работает без ощутимых задержек.

Лично для меня весьма накладно отсылать обычные SMS-ки с GSM-модема, но может быть с подключенным пакетом SMS кто-то решит поступить именно так с целью изолированности Asteriska от «внешних воздействий».

Настройка сервиса email2sms:
Мобильному абоненту нужно отправить бесплатное сообщение на 000908 с буквой С (полагаю, что от английского слова create-создать).


кусок extensions.conf относительно отправки SMS-уведомления:
; продолжение макроса [macro-dial-mobile]…

exten => s,n(complete_call),Background(/my_sounds/goodbue)
exten => s,n,NoOp(«Call to ${ARG1} from ${Dest_number} is complete!»)
exten => s,n,Hangup()

exten => s,n(sms),Background(busy_now); «Аппарат абонента занят.»
exten => s,n, System(rm /my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(touch /my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(chmod 777 -R /my_scripts/sms/sendfile_mail${ARG1})

exten => s,n, System(echo «Subject: 'HOMEP — ${ARG2}'» >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo «Mime-Version: 1.0» >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo «Content-Type: text/plain; charset=»UTF-8"" >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo «Content-Transfer-Encoding: 8bit» >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo "" >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo "${STRFTIME(${EPOCH},,%d.%m.-%H:%M:)}" >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo "" >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo "." >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(echo "" >>/my_scripts/sms/sendfile_mail${ARG1})
exten => s,n, System(cat /my_scripts/sms/sendfile_mail${ARG1} |sendmail -f XXxxXX@mail.ru -t ${ARG1}@sms.ugsm.ru)
exten => s,n, NoOp(«SMS to ${ARG1} from number ${Dest_number} sent now.»)
exten => s,n,Background(sms_sended)
; «Ему отправлено смс с вашим номером.»
exten => s,n, Hangup()


Идем дальше.

Для полного отказа от развернутого решения Информтехники — DECT-трубок (и расставленных по территории промплощадки базовых станций), как от отжившего себя атавизма, сделано еще кое-что.

КАРТИНКА - Визуализация маршрута - ОСТОРОЖНО ЮМОР - для тех кому интересно:

...


«Мои» мобильные абоненты делятся по оснащенности на две условные категории: Android-пользователи и пользователи обычных древних мобильников (обычно руководство в возрасте). Все они используют корпоративный тариф, где все внутрикорпоративные звонки бесплатны/безлимитны.
Мультифоновский аккаунт, благодаря своей многоканальности, прекрасно работает на входящую связь.

КАРТИНКА по теме для тех кому интересно:

...


У Android-пользователей используется приложение Prefixer(найдете в маркете — не реклама). Для исходящих во внутренную ведомственную сеть по привычным номерам достаточно одного правила:

When number matches — [2-5].* — правилом обрабатываются все номера начинающиеся с 2,3,4,5.
Add prefix: 8922xxxXXxx,,, — мультифоновский аккаунт сервера Asterisk, три запятые — это пауза в три секунды после соединения (в это время DISA сервера Asterisk радостно приветствует позвонившего).

Таким образом, когда мобильный абонент набирает на своем мобильном привычный ему номер 54705, приложение перехватывает управление вызовом, набирает определенный в правиле префикс (номер мультифоновского аккаунта), выжидает паузу в три секунды для пропуска голосового приветствия и набирает в канал цифры 5 4 7 0 5 с помощью DTMF.

В ближайшее время поправлю диалплан касаемо DISA на проверку CallerID входящего звонка в базе transfer — не зачем каждый раз слушать голосовое приветствие и просьбу набрать добавочный номер абонентам у которых настроен Prefixer — пусть сразу номер донабирается.

Вторая категория абонентов в силу некоторых причин до сих пор использует обычные мобильники. Для них заказаны с Китая интересные девайсы — SIM-Dialer. Они представляют собой этакую «подкладку» под SIM-карту, настраиваются абсолютно просто и обеспечивают функционал аналогичный Prefixer-у. Цена вопроса на момент заказа 4,5-5 USD за шт.
Подробное описание SIM-Dialer:
toster.ru/answer?answer_id=418483 — тема, где выложены ссылки на описание в PDF.
Мои действующие настройки(устройство подменяет SIM-меню оператора) такие:
Пароль 8888
Set ACC N; установка номера дозвона = префикса
ACC 1 N: ##8922xxxXXxx; аккаунт мультифона сервера Asterisk
Acc delay: 01; задержка 3 сек, вычисляется как 01х3
Set Dialplan; правило набора
catch prx for Acc1: 2*3*4*5; фильтр правила на цифры 2,3,4,5
Other
Ending code: #; по-умолчанию
Mode: 4;
Стоит упомянуть, что сей девайс умеет делать CallBack — смотрите инструкцию по ссылке выше.
Я эту функцию не тестировал за ненадобностью.

Таким образом, мои мобильные абоненты имеют удобные (для себя) и бесплатные (для бюджета предприятия) звонки во внутреннюю учрежденческую сеть.

Продолжение статьи…
Появилась потребность при звонке на номер DISA (мобильный) для «своих» убрать голосовые инструкции. В принципе, для тех кому нужно можно отсеять входящие звонки с «чужих» номеров. Подробности под спойлером. Welcome!

Фильтрация по CallerID входящих звонков:
[Voice_Disa]; Входящая DISA
exten => s,1, Answer(); Берем трубку
exten => s,n, Wait(0.2); выжидаем паузу

exten => s,n, NoOp(«Incomming DISA-Call from number ${CALLERID(num)}»); показываем CALLERID входящего вызова

exten => s,n, Set(result=${SHELL(asterisk -rx «database show transfer» |grep ${CALLERID(num)} | wc -l)}); проверяем его наличие
exten => s,n, NoOp(${result}); в базе tranfer, сохраняем
; и показываем эту переменную
exten => s,n, GotoIf($[${result}>0]?no_voice); проверяем значение переменной в базе и маршрутизируем
exten => s,n, Wait(0.2); по условию на «неголосовой» — короткий вариант
exten => s,n(voice), PlayBack(/my_sounds/GO/hi); «Здравствуйте»
exten => s,n, Wait(0.5)

exten => s,n, PlayBack(/my_sounds/dial_2_transfer); «Введите номер для перевода вызова»
exten => s,n, Wait(0.5)
exten => s,n, DISA(no-password,from_sip); Отправляем в основной контекст
exten => s,n, System(echo "${DATETIME} — ${CALLERID} — ${CHANNEL}" >> /var/log/asterisk/DISA_mobile_calls); ведем лог звонков
exten => s,n, Hangup(); кладём трубку

exten => s,n(no_voice), DISA(no-password,from_sip); Отправляем в основной констекст
exten => s,n, System(echo "${DATETIME} — ${CALLERID} — ${CHANNEL}" >> /var/log/asterisk/DISA_mobile_calls); ведем лог звонков
exten => s,n, Hangup()


Не считаю, что тут хитрый или оригинальный код, но вероятно он может кому-то пригодится… Тем более что это логическое продолжение описанного выше функционала.
Теги:
Хабы:
+8
Комментарии12

Публикации

Изменить настройки темы

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн