Уведомление при перехвате вызова в Asterisk

Не большая предыстория


На работе периодически приходится перехватывать вызовы, что в принципе не беда. Но бывает, что необходимо потом перезвонить тому, кто звонил.
Номер соответственно у меня не высветился и обычно приходится лезть в cdr'ки в mysql или подойти к телефону напарника и искать номер телефона.
Можно в принципе попросить напарника включать переадресацию на телефонном аппарате, но уходит он на пару минут, да и мы не ищем легких путей.

Итак, что мы имеем: офисная АТС на Asterisk (версия = 1.8.15.1), реализована функция перехвата вызова и уведомлений о звонке через jabber.

Информации по поводу настройки перехвата вызова, отправки уведомлений c помощью jabber достаточно в просторах интернета, так что сразу опишу о реализации получения уведомления при перехвате вызова.

Начнем с Mysql (версия = Server version: 5.5.31-0+wheezy1 (Debian)):


В базе asteriskcdrdb создадим 2 таблицы pickup_message и pickup_group.
В таблице pickup_message, у нас будет всего 2 столбца pg_id и message:
pg_id — id pickup группы в Asterisk;
message — поле куда будут записываться уведомления;

mysql> CREATE TABLE pickup_message
    -> (pg_id smallint unsigned,

Параметры SMALLINT и UNSIGNED для столбца pg_id, выбрал т.к. планируются только короткие, целые числа. Хотя можно использовать и имена для групп перехвата.
  -> message varchar(128),
  -> CONSTRAINT pk_pg_id PRIMARY KEY (pg_id)


В столбце pg_id у нас будут только уникальные записи, и столбец будет служить для связки 2-х таблиц.

 -> );
Query OK, 0 rows affected (0.09 sec)

Таблица pickup_group содержит информацию о принадлежности внутреннего номера (peer) к определенной группе перехвата (pg_id).
Так же для связки 2 таблиц добавим FOREIGN KEY () и REFERENCES.
mysql> CREATE TABLE pickup_group
    -> (pg_id SMALLINT UNSIGNED,
    -> peer SMALLINT UNSIGNED,
    -> CONSTRAINT fk_pg_id FOREIGN KEY (pg_id)
    -> REFERENCES pickup_message (pg_id)
    -> );
Query OK, 0 rows affected (0.08 sec)

Заполним для теста обе таблицы следующей информацией группа перехвата 1, внутренние номера 309 и 373:
mysql> insert into pickup_message values (1, NULL);
Query OK, 1 row affected (0.05 sec)

mysql> insert into pickup_group values (1, 309);
Query OK, 1 row affected (0.06 sec)

mysql> insert into pickup_group values (1, 373);
Query OK, 1 row affected (0.04 sec)

mysql> select * from pickup_message;
+-------+---------+
| pg_id | message |
+-------+---------+
|     1 | NULL    |
|    33 | NULL    |
+-------+---------+
2 rows in set (0.00 sec)

mysql> select * from pickup_group;
+-------+------+
| pg_id | peer |
+-------+------+
|     1 |  309 |
|     1 |  373 |
+-------+------+
2 rows in set (0.00 sec)


Переходим к настройкам Asterisk, отредактируем extensions.conf:


В контексте где обрабатывается набор внутренних номеров:

exten => _ZXX,1,Macro(jabb-personal-pickup,${EXTEN})
same => n,Dial(SIP/${EXTEN},120,t)
same => n,Hangup


Макрос для отправки уведомлений (в макрос передается одна переменная ${ARG1}, номер который набрали):

[macro-jabb-personal-pickup]
exten => s,1,Set(text=Входящий вызов от ${CALLERID(number)})  
same => n,MYSQL(Connect connid 127.0.0.1 root PASSWORD asteriskcdrdb)        
same => n,MYSQL(Query resultid ${connid} select pickup_message.pg_id from pickup_message inner join pickup_group where peer = '${ARG1}';) ; #в данном запросе ищем к какой группе относится номер который набрали
same => n,MYSQL(Fetch fetchid ${resultid} pg_id)
same => n,GotoIf($["${fetchid}"="1"]?yes:no) 
same => n(yes),MYSQL(Query resultid ${connid} update pickup_message set message ='${text}' where pg_id = '${pg_id}') ; #если номер есть в группе, то запишем в ячейку группы message переменную text
same => n(no),MYSQL(Clear ${resultid})
same => n,MYSQL(Query resultid ${connid} select jabb_id from jabber where number=${ARG1})
same => n,MYSQL(Fetch fetchid ${resultid} jabb_id)
same => n,GotoIf($["${fetchid}"="1"]?ok:bad)
same => n(ok),JabberSend(asterisk,${jabb_id},${text})
same => n(bad),MYSQL(Clear ${resultid})
same => n,MYSQL(Disconnect ${connid})


И собственно контекст при перехвате звонка (*8). Здесь мы проверяем к какой группе мы относимся и есть ли сообщения в нашей группе.
Т.е. при входящем звонке на внутренний номер, в ячейку группы записывается информация о звонящем, а перехватом мы эту информацию забираем.
В принципе все просто:
exten => *8,1,NoOp(pickup)
same => n,MYSQL(Connect connid 127.0.0.1 root PASSWORD asteriskcdrdb)
same => n,MYSQL(Query resultid ${connid} select pickup_message.message from pickup_message inner join pickup_group where peer = ${CALLERID(number)}) ; #запрос на проверку к какой группе перехвата мы относимся
same => n,MYSQL(Fetch fetchid ${resultid} message) 
same => n,GotoIf($["${fetchid}"="1"]?message:no)  ; #проверяем что в запросе есть результат         
same => n(message),Set(text=Перехват вызова. ${message}) ;# в переменную text запишем данные из ячейки нашей группы
same => n,MYSQL(Clear ${resultid})
same => n,MYSQL(Query resultid ${connid} select jabb_id from jabber where number=${CALLERID(number)})  ;# ищем id jabber для peer'a, т.к. не все его используют 
same => n,MYSQL(Fetch fetchid ${resultid} jabb_id) 
same => n,GotoIf($["${fetchid}"="1"]?yes:no)   ; # проверяем что в запросе есть результат
same => n(yes),JabberSend(asterisk,${jabb_id},${text})
same => n(no),MYSQL(Clear ${resultid})
same => n,MYSQL(Query resultid ${connid} update pickup_message set message ='NULL' where message = '${message}')
same => n,MYSQL(Disconnect ${connid})
same => n,PickUP()

В итоге, при перехвате вызова, в jabber приходят сообщения такого рода:
[15:09:07] <Office Manager> Перехват вызова. Персональный звонок. 302
[15:12:08] <Office Manager> Перехват вызова. Персональный звонок. 226
[15:25:47] <Office Manager> Перехват вызова. Персональный звонок. 106
[15:32:40] <Office Manager> Персональный звонок. 116

Надеюсь, для кого-то данная информация будет полезной.
Поделиться публикацией

Комментарии 12

    0
    А не проще использовать «sendrpid = yes»?
    Хотя он не всеми телефонами поддерживается.
      0
      Интересный параметр, честно как то даже не приходилось его применять, завтра попробую проверить. А так есть мысли, не много доработать выше описанный метод и отправлять уведомление тому у кого вызов был перехвачен. Выше я опустил момент, точнее намерено вырезал из контекста — при до наборе внутреннего номера, идет проверка входящего CALLER_ID в базе, при его наличии в jabber отправляется доп. информация о звонящем.
        0
        тогда понятно.
        У меня была такая проблема, и я уже начал думать о оповещении в jabber или почту, но добрые люди подсказали вот этот параметр. Теперь при перехвате отображается верный номер. НО, есть отзывы что некоторые телефоны просто виснут когда им его астериск передает, у меня на практике такого не было cisco spa502g его поддерживают, а вот simens gigaset просто игнорируют.
          0
          Ну думаю данный метод будет интересен, когда используется голосовой шлюз и обычный аналоговый телефон. А так действительно, одной строчкой решилась проблема. Как говорится век живи — век учись.
          0
          Объясните, пожалуйста, зачем нужен параметр sendrpid на пальцах?

          Defines whether a Remote-Party-ID SIP header should be sent. Defaults to no.
          This field is often used by wholesale VoIP providers to provide calling party identity regardless of the privacy settings (the From SIP header).
            0
            В sip-заголовках (INVITE (при входящем вызове), 200ОК (при перехвате)), добавляется поле Remote-Party-ID, в зависимости от модели (и прошивки) телефонного аппарата, он может поверять данные в этом поле, если нет то берет его из поля From (если не ошибаюсь).
          0
          Вопрос по смежной теме — почему odbc коннектор не используете?
            0
            Как раз сегодня утром пока ехал на работу, прочитал статью товарища albertxyc. Я так понял, с помощью odbc коннектор, мы избавимся от постоянных коннектов в базе, что должно положительно повлиять на работу системы в целом. Думаю на грядущих выходных попробую реализовать. А так знакомство с mysql у меня началось буквально неделю назад, начал читать книгу А. Бьюли «Изучаем sql».
              0
              Именно. Более того — там можно делать шаблонные функции и передавать параметры им как в макросах диалпланов. в общем очень удобно. Хотя при использовании lua диалплана, например, более удобно работать с коннектором mysql для lua, так как с odbc коннетором существуют некоторые проблемы.
            0
            Добавил сегодня параметр sendrpid=yes. По совету EvilMause. Протестировал на 2 аппаратах cisco spa942 и 502g, все работает.
            tcpdump'ом проверил, что передается в sip заголовках, добавился параметр Remote-Party-ID.
            Посмотрел в вики на asterisk.ru про параметр sendrpid: Отправлять или нет заголовок Remote-Party-Id этому SIP клиенту. Значения: yes/no, по умолчанию: yes.
              0
              старайтесь использовать не asterisk.ru как wiki, а wiki.asterisk.org. Там более свежая инфа. Ну это так. Лирика.
                0
                В версии 1,8 значение по умолчанию было «no». Иначе у меня вовсе не возникло бы проблемы, но так даже лучше получилось.
                Единственное, я так и не смог потом выключить эту функцию, rpid все равно передавался. Видно какой то глюк на моей системе был.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое