[СТАТЬЯ] Оценка работы оператора FreePBX+Asterisk | 2019

Asterisk, FreePBX

Оценка работы оператора FreePBX+Asterisk

ocenka-raboty-operatora-freepbxasterisk

ocenka-raboty-operatora-freepbxasterisk



Задача:

1) Есть группа операторов Call-центра, нужно сделать возможность после разговора, оценивать звонок.
2) Максимальная интеграция с FreePBX.



Решение:

В Интернете много вариантов, все они ориентированы на чистый Asterisk.
Примеры:
https://wiki.merionet.ru/ip-telephoniya/55/ocenka-raboty-operatora-posle-zvonka-na-asterisk/
https://habr.com/ru/post/147122/
http://asterisk-service.com/blog/asterisk-1/post/2-0-53
Моя же реализация заключается в том, что все настройки можно делать в Web-интерфейсе FreePBX.
Реализация тестировалась и работает на:
— версии Asterisk 1.8.10.1
— FreePBX версии 12.0.76.6
— PHP версии 5.3.10-1ubuntu3.26
— библиотека PHPAGI версии 2.20 2010/09/30 02:21:00 (качаем тут: phpagi.zip)

Первым делом нам нужно определить как генерируется постановка вызова в очередь. Выполняем на сервере Asterisk:
nano /etc/asterisk/extensions_additional.conf
Ищем контекст с названием [ext-queues]. Внутри должны быть строки вида

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[ext-queues]
include => ext-queues-custom
exten => 11,1,Macro(user-callerid,)
exten => 11,n,Answer
exten => 11,n,Macro(blkvm-set,reset)
exten => 11,n,ExecIf($["${REGEX("(M[(]auto-blkvm[)])" ${DIAL_OPTIONS})}" != "1"]?Set(_DIAL_OPTIONS=${DIAL_OPTIONS}M(auto-blkvm)))
exten => 11,n,Set(__NODEST=${EXTEN})
exten => 11,n,Set(QCIDPP=${IF($[${LEN(${VQ_CIDPP})}>0]?${VQ_CIDPP}: )})
exten => 11,n,Set(VQ_CIDPP=)
exten => 11,n,ExecIf($["${QCIDPP}"!=""]?Macro(prepend-cid,${QCIDPP}))
exten => 11,n,Set(QAINFO=${IF($[${LEN(${VQ_AINFO})}>0]?${VQ_AINFO}: )})
exten => 11,n,Set(VQ_AINFO=)
exten => 11,n,ExecIf($["${QAINFO}"!=""]?Set(__ALERT_INFO=${QAINFO}))
exten => 11,n,Set(QJOINMSG=${IF($[${LEN(${VQ_JOINMSG})}>0]?${IF($["${VQ_JOINMSG}"!="0"]?${VQ_JOINMSG}: )}:custom/zednannja-vstanovleno)})
exten => 11,n,Set(VQ_JOINMSG=)
exten => 11,n,Set(QRINGOPTS=r)
exten => 11,n,Set(QRETRY=${IF($[${LEN(${VQ_RETRY})}>0]?${VQ_RETRY}:n)})
exten => 11,n,Set(VQ_RETRY=)
exten => 11,n(qoptions),Set(QOPTIONS=${IF($[${LEN(${VQ_OPTIONS})}>0]?${VQ_OPTIONS}:t)}${QCANCELMISSED}${QRINGOPTS}${QRETRY})
exten => 11,n,Set(VQ_OPTIONS=)
exten => 11,n(qgosub),Set(QGOSUB=${IF($[${LEN(${VQ_GOSUB})}>0]?${VQ_GOSUB}:${QGOSUB})})
exten => 11,n,Set(VQ_GOSUB=)
exten => 11,n(qagi),Set(QAGI=${IF($[${LEN(${VQ_AGI})}>0]?${VQ_AGI}:${QAGI})})
exten => 11,n,Set(VQ_AGI=)
exten => 11,n(qrule),Set(QRULE=${IF($[${LEN(${VQ_RULE})}>0]?${IF($["${VQ_RULE}"!="0"]?${VQ_RULE}: )}:${QRULE})})
exten => 11,n,Set(VQ_RULE=)
exten => 11,n(qposition),Set(QPOSITION=${IF($[${LEN(${VQ_POSITION})}>0]?${VQ_POSITION}:${QPOSITION})})
exten => 11,n,Set(VQ_POSITION=)
exten => 11,n,Gosub(sub-record-check,s,1(q,11,dontcare))
exten => 11,n,ExecIf($["${QJOINMSG}"!=""]?Playback(${QJOINMSG}, ))
exten => 11,n,QueueLog(11,${UNIQUEID},NONE,DID,${FROM_DID})
exten => 11,n,Set(QAANNOUNCE=${IF($[${LEN(${VQ_AANNOUNCE})}>0]?${IF($["${VQ_AANNOUNCE}"!="0"]?${VQ_AANNOUNCE}: )}: )})
exten => 11,n,Set(VQ_AANNOUNCE=)
exten => 11,n,Set(QMOH=${IF($["${VQ_MOH}"!=""]?${VQ_MOH}: )})
exten => 11,n,Set(VQ_MOH=)
exten => 11,n,ExecIf($["${QMOH}"!=""]?Set(__MOHCLASS=${QMOH}))
exten => 11,n,ExecIf($["${MOHCLASS}"!=""]?Set(CHANNEL(musicclass)=${MOHCLASS}))
exten => 11,n,Set(QMAXWAIT=${IF($[${LEN(${VQ_MAXWAIT})}>0]?${VQ_MAXWAIT}: )})
exten => 11,n,Set(VQ_MAXWAIT=)
exten => 11,n,Set(QUEUENUM=11)
exten => 11,n,Set(QUEUEJOINTIME=${EPOCH})
exten => 11,n(qcall),Queue(11,${QOPTIONS},,${QAANNOUNCE},${QMAXWAIT},${QAGI},,${QGOSUB},${QRULE},${QPOSITION})
exten => 11,n,Macro(blkvm-clr,)
exten => 11,n,Gosub(sub-record-cancel,s,1())
exten => 11,n,Set(__NODEST=)
exten => 11,n,Set(_QUEUE_PRIO=0)
exten => 11,n,Set(QRINGOPTS=)
exten => 11,n,Set(QDEST=${VQ_DEST})
exten => 11,n,Set(VQ_DEST=)
exten => 11,n(gotodest),GotoIf($["${QDEST}"=""]?ext-group,505,1:${CUT(QDEST,^,1)},${CUT(QDEST,^,2)},${CUT(QDEST,^,3)})

здесь нас интересует строка: exten => 11,n(qcall),Queue(11,${QOPTIONS},,${QAANNOUNCE},${QMAXWAIT},${QAGI},,${QGOSUB},${QRULE},${QPOSITION})
Приложение Queue() генерирует постановку вызова в очередь. Как видим с примера — приложению передаются параметры, которые были сгенерированные перед выполнением приложения Queue(). Смотрим в документацию: https://asterisk-pbx.ru/wiki/asterisk/app/queue
Как видим по документации, если при выполнении приложения Queue(), добавить в аргумент «options» параметр «c», то диаплан продолжит свое выполнения, когда вызываемый (оператор) положил трубку. В нашем случае — диаплан перейдет на пункт «Fail Over Destination» в FreePBX.
По контексту определяем, что если перед поступлением звонка в очередь, мы установим значение «c» переменной VQ_OPTIONS, то приложение Queue() згенерирует постановку вызова в очередь с этим параметом.

Приступаем к выполнению

nano /etc/asterisk/extensions_custom.conf
Создаем собственный контекст с установкой значения переменной VQ_OPTIONS:

1
2
3
4
[queue-call-begin]
exten => s,1,Set(VQ_OPTIONS=tc) ;на первом приоритете, мы устанавливаем значение переменной. Параметром "t" - я разрешаю оператору переводить звонки
exten => s,n,System(php /var/www/call/call.php incall ${UNIQUEID} ${CALLERID(num)} ${CHANNEL} &) ;запуск фонового php скрипта на выполнения
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван


Также создаем контексты с оценками

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[assessment-1]
exten => s,1,Set(__OcenkaOper=1) ;выполняем необходимое действие
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван
 
[assessment-2]
exten => s,1,Set(__OcenkaOper=2) ;выполняем необходимое действие
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван
 
[assessment-3]
exten => s,1,Set(__OcenkaOper=3) ;выполняем необходимое действие
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван
 
[assessment-4]
exten => s,1,Set(__OcenkaOper=4) ;выполняем необходимое действие
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван
 
[assessment-5]
exten => s,1,Set(__OcenkaOper=5) ;выполняем необходимое действие
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван


После exten => s,1,Set(__OcenkaOper=X) можем выполнять еще команды. Например отправить сообщение в телеграмм:
exten => s,n,System(curl -s -X POST "https://api.telegram.org/bot545454443:AAAAAAAAAAAAAAAABBBBBBBBBBBCCC/sendmessage" -F chat_id="20202020" -F text="Оставлена оценка оператору: 5" &)
Или можно запустить php скрипт, который возвращает значение. Это значение присвоим переменной:
exten => s,n,Set(CallId=${SHELL(php /var/www/call/call.php inCallRegister ${CALLERID(num)})})

Логично, что если звонок не состоялся (оператор не взял трубку), то предлагать оценивать вызов не нужно. Для этого, создадим еще один контекст:

1
2
3
4
5
[queue-call-end]
exten => s,1,GotoIf($[${QUEUESTATUS}=TIMEOUT]?timeout:answered); очередь по завершению получает переменную QUEUESTATUS, от значения которого мы можем определить был ли принят звонок
exten => s,n(timeout),Goto(app-announcement-18,s,1) ; если звонок не был принят, направим его на app-announcement-18,s,1 - это приветствие, в котором говорим, что сейчас все операторы заняты и мы ему перезвоним. После, терминируем звонок (hangup) - обязательно. 
exten => s,n(answered),Noop(return to queue-call-end) ; если статус звонка отличается от "TIMEOUT", сделаем вывод, что звонок состоялся, и переходим на следующий приоритет
exten => s,n,Return ;возвращаемся на предыдущий контекст, откуда был вызван

Сохраняем изменения в файле /etc/asterisk/extensions_custom.conf и выходим с редактора nano — Ctrl+o, Ctrl+x.
Следующим этапом нам нужно зафиксировать созданные контексты в FreePBX.
Заходим в FreePBX → АДМИНИСТРАТОР (Admin) → Дополнительные назначения (Custom Destination)
Добавляем созданные ранее назначения:
Для примера опишу добавление контекста [queue-call-begin]
— в поле Спецназначение: указываем «queue-call-begin,s,1»
— в поле Описание: указываем «queue-call-begin» — название понятное Вам
— в поле Примечания: указываем описание для назначения понятное Вам
— Обязательно ставим галочку «Return», после чего появится выпадающий список дальнейших назначений — направляем в очередь (можно в другое место).

По аналогии, добавляем остальные назначения:
[assessment-1]
Спецназначение: assessment-1,s,1
Return: Приветствие → «Спасибо за оценку» → Терминовать звонок (Положить трубку).

[assessment-2]
Спецназначение: assessment-2,s,1
Return: Приветствие → «Спасибо за оценку» → Терминовать звонок (Положить трубку).

[assessment-3]
Спецназначение: assessment-3,s,1
Return: Приветствие → «Спасибо за оценку» → Терминовать звонок (Положить трубку).

[assessment-4]
Спецназначение: assessment-4,s,1
Return: Приветствие → «Спасибо за оценку» → Терминовать звонок (Положить трубку).

[assessment-5]
Спецназначение: assessment-5,s,1
Return: Приветствие → «Спасибо за оценку» → Терминовать звонок (Положить трубку).

[queue-call-end]
Спецназначение: queue-call-end,s,1
Return: IVR → «Оцените работу оператора».

Настройка Очереди:
Все настройки делаем на свое усмотрение, но в «Назначение при неответе», устанавливаем «Дополнительные назначения» → «queue-call-end».

Настройка IVR «Оцените работу оператора»:

Применяем настройки. В терминале сервера можно выполнить asterisk -rx "dialplan reload"

Что у нас получается на этот момент:
Поступает звонок. Первым делом — направляем его на «Дополнительные назначения» → «queue-call-begin», где присваиваем переменной VQ_OPTIONS значение «tc» (параметр c — продолжение выполнения диалплана после того, как оператор положил трубку). Далее звонок поступает в очередь, где генерируются вызовы агентам (операторам). Оператор поднял трубку → разговор → положил трубку. Звонок попадает в «Назначение при неответе» → «Дополнительные назначения» → «queue-call-end», где мы проверяем был ли отвечен звонок. Если звонок не был принят (TIMEOUT), направляем его на Приветствие app-announcement-18 (у Вас будет другое, ищите в nano /etc/asterisk/extensions_additional.conf).Если статус звонка (QUEUESTATUS) отличается от «TIMEOUT», продолжаем выполнение диалплана, где попадаем в Return Дополнительного назначения «queue-call-begin» → IVR «Оцените работу оператора». Здесь мы озвучиваем запись «Поставьте оценку от 1-го до 5-ти», ждем ввода. Если клиент ничего не ввел, либо ввел неверно, Терминируем звонок (Положить трубку). Если нажал одну с оценок, переходим в «Дополнительные назначение» → «assessment-X», где присваиваем переменной OcenkaOper определенное значение, и возвращаемся в поле Return Дополнительного назначения «assessment-X» → Приветствие «Спасибо за оценку». Приветствие «Спасибо за оценку» воспроизводит запись о благодарности за оценку и Терминирует звонок (Положить трубку).

Посмотреть логи прохождения звонка можно командой asterisk -rvvvv

Теперь нам нужно следить за звонком. Создаем каталог «call» в /var/www/, внутри него создаем php файл с именем call.php. Также внутри каталога call создаем каталог src и в корень его кладем файлы библиотеки PHPAGI
nano /var/www/call/call.php
Вставляем код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
 
require('/var/www/call/src/phpagi.php');
 
/*
следующие строки - подключение к asterisk AMI, доступы посмотреть можно здесь: /etc/asterisk/manager.conf, либо создать дополнительный доступ:  https://wiki.merionet.ru/ip-telephoniya/13/nastrojka-ami-v-freepbx-13/
*/
$service_port = "5038";
$address = "127.0.0.1";
$user_ami = "admin";
$pass_ami = "admin";
 
$token_telegram='44444444444:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-UaaUUUU';
$chat_id_telegram='222222222222';
 
$responsible=NULL;
$stat=false; //статус звонка (начат разговор=true, или нет=false). принимает значение true\false
$ocenka=NULL; //переменная, хранит в себе поставленную оценку
$Uniqueid1='0'; //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$Uniqueid2='0'; //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$Uniqueid='0';  //Глобальная переменная, которая НЕ будет изменятся, она статическая на все время работы скрипта (перевод звонка и т.п.)
$UniqueID='0';  //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$CallerID1='0';  //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$CallerID2='0';  //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$Channel1='0';  //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$Channel2='0';  //Глобальная переменная, которая будет изменятся по циклу работы скрипта (перевод звонка, и т.п.)
$i=true;  //Глобальная переменная, которая определяет цикл работы скрипта. true = продолжает работать скрипт, false = скрипт закончит работу
$redirekt=false; //Статус перевода звонка
$per=false; //временный статус перевода звонка
 
function telegram_message($TOKEN='',$CHAT_ID='',$MESSAGE=''){
$telegram_data = array (
    'text' => $MESSAGE,
    'chat_id' => $CHAT_ID,
    'parse_mode' => 'html'
);
file_get_contents("https://api.telegram.org/bot".$TOKEN."/sendMessage?".http_build_query($telegram_data));
}
 
function dump_incall($ecode,$data,$server,$port) {
//telegram_message($GLOBALS["token_telegram"],$GLOBALS["chat_id_telegram"],'перевод звонка '.json_encode($data));
if(((($data['Event']=='VarSet')&&($data['Value']=='tr'))&&($data['Variable']=='ARG2'))&&(($data['Channel']==$GLOBALS["Channel1"])||($data['Channel']==$GLOBALS["Channel2"])))
  $GLOBALS["per"]=true; //определяем перевод звонка
if(((($data['Event']=='VarSet')&&($GLOBALS["stat"]==true))&&($data['Variable']=='ARG3'))&&(($data['Channel']==$GLOBALS["Channel1"])||($data['Channel']==$GLOBALS["Channel2"]))){
  $GLOBALS["per"]=false;
  $GLOBALS["UniqueID"]=$data['Uniqueid'];
  $GLOBALS["stat"]=false;
  $GLOBALS["redirekt"]=true;
  //telegram_message($GLOBALS["token_telegram"],$GLOBALS["chat_id_telegram"],'перевод звонка '.json_encode($data));
}
 
if(($data['Event']=='Newstate')&&($GLOBALS["CallerIdNum"]==$data['ConnectedLineNum']))
  if(($data['ChannelStateDesc']=='Up')&&(preg_match("/^SIP/",$data['Channel']))) $GLOBALS["UniqueID"]=$data['Uniqueid'];
 
if(($GLOBALS["UniqueID"]==$data['Uniqueid2'])||($GLOBALS["UniqueID"]==$data['Uniqueid1'])||($GLOBALS["UniqueID"]==$data['Uniqueid'])||($GLOBALS["UniqueID"]==$data['UniqueID'])){
  if(($data['Event']=='Bridge')&&($data['Bridgestate']=='Link')){  //поднята трубка
    if($GLOBALS["stat"]==false){
      $GLOBALS["stat"]=true;
      $GLOBALS["responsible"]=$data['CallerID2'];       //определяем ответственного за звонок
      $GLOBALS["Uniqueid2"]=$data['Uniqueid2'];
      $GLOBALS["Uniqueid1"]=$data['Uniqueid1'];
      $GLOBALS["Channel1"]=$data['Channel1'];
      $GLOBALS["Channel2"]=$data['Channel2'];
      //telegram_message($GLOBALS["token_telegram"],$GLOBALS["chat_id_telegram"],'Поднята трубка. начат разговор '.json_encode($data));
    }
  }
  if((($data['Event']=='Dial')&&($data['SubEvent']=='Begin'))&&($GLOBALS["redirekt"]==true)){
      $GLOBALS["responsible"]=$data['Dialstring'];
      //telegram_message($GLOBALS["token_telegram"],$GLOBALS["chat_id_telegram"],'зафиксирован перевод звонка. Новые данные: CallerIDNum='.$data['CallerIDNum'].' Dialstring='.$data['Dialstring'].' '.json_encode($data));
      $GLOBALS["redirekt"]=false;
      $GLOBALS["Channel1"]=$data['Channel'];
      $GLOBALS["Channel2"]=$data['Destination'];
      $GLOBALS["UniqueID"]=$data['UniqueID'];
      $GLOBALS["Uniqueid1"]=$data['UniqueID'];
      $GLOBALS["Uniqueid2"]=$data['DestUniqueID'];
  }
}
if($GLOBALS["Uniqueid"]==$data['Uniqueid'])
  if($data['Event']=='Hangup') {
    telegram_message($GLOBALS["token_telegram"],$GLOBALS["chat_id_telegram"],'Завершена работа скрипта. выход из цыкла '.json_encode($data));
    $GLOBALS["i"]=false;
  }
}
 
if (isset($argv[1])) {
        $status=$argv[1];
}
else  echo "Введите параметры!";
if($status=='incall'){
    if ((isset($argv[2])&&isset($argv[3]))&&isset($argv[4])) {
                $Uniqueid=$argv[2];
                $CallerIdNum=$argv[3];
                $Channel=$argv[4];
                $manager = new AGI_AsteriskManager();
                $manager->connect($address, $user_ami, $pass_ami);
                //telegram_message($token_telegram,$chat_id_telegram,'Входящий звонок. id='.$Uniqueid.' caller='.$CallerIdNum.' channel='.$Channel);
                    while($i){
                      $manager->Events('on');
                      $manager->wait_response(true);
                      $manager->add_event_handler('*', 'dump_incall');
                      if(!$ocenka) {
                        $tmpOc=$manager->send_request('GetVar',array('Variable' => 'OcenkaOper', 'Channel' => $Channel));
                        if(isset($tmpOc['Value']) && ($tmpOc['Value']!='')){
                          $ocenka=$tmpOc['Value'];
                          //telegram_message($token_telegram,$chat_id_telegram,'ocenka='.json_encode($tmpOc));
                        }
                      }
                    }
                $manager->disconnect();
                if(isset($ocenka)) {
                  if($ocenka=='5') $smile="\xF0\x9F\x98\x8D";
                  if($ocenka=='4') $smile="\xF0\x9F\x98\x83";
                  if($ocenka=='3') $smile="\xF0\x9F\x98\x8F";
                  if($ocenka=='2') $smile="\xF0\x9F\x98\x96";
                  if($ocenka=='1') $smile="\xF0\x9F\x98\xA1";
                  telegram_message($token_telegram,$chat_id_telegram,$smile." Оценен входящий звонок от ".$CallerIdNum.". Ответственный оператор ".$responsible.". Оставлена оценка ".$ocenka);
                }
                //telegram_message($token_telegram,$chat_id_telegram,'Завершение скрипта по номеру канала '.$Uniqueid.'. ответственный='.$responsible);
    }
    else echo "Введите параметры!";
}
?>

Вносим свои изменения, сохраняем и выходим: CTRL+o, CTRL+x.
Что делает скрипт? Он запускается в контексте [queue-call-begin], и следит за звонком до самого его завершения. Он определяет кто поднят трубку, на кого звонок был перенапрвален, и была ли оставлена оценка. После чего — отправляет сообщение в телеграм. Вместо телеграма, можно отправлять оценку куда угодно (SQL, 1С, Битрикс24, и т.д.)
Делаем тестовый звонок, проверяем работоспособность, запускаем в продакшн.

Похожие статьи:

Доступ к Slave boards Openvox
Для того, чтобы выполнить запрос из консоли Asterisk (asterisk -rx ""), который установлен на шлюз, или через Web-интерфейс (Дополнительно→Asterisk CLI) то будет доступен только Master модуль. Чтобы работать со Slave модулями, нужно поднимать дополнительное соединение. Как же работает Web-интерфейс с Slave модулями? Так и работает! ...
Web CallBack FreePBX
Задача Создать кнопку "Перезвоните мне" на сайте, с максимальной интеграцией во FreePBX. Решение Для примера возьмем статью https://asterisk-pbx.ru/wiki/artikle/asterisk_web_callback. Принцип работы этой реализации заключается в том, что php скрипт генерирует (Originate) вызов. Первым делом отправляет вызов по каналу Channel. После того, как соединение установлено (вызов принят оператором), осуществляется ...
Мониторинг уровня сигнала SIM-карт в Openvox через Zabbix
При переходе по ссылке http://IP_OPENVOX/service?action=get_gsminfo, или http://IP_OPENVOX/X/service?action=get_gsminfo (где X - номер модуля, больше 1), можно увидеть в json-формате статус портов (span-нов). Если Web-сервер на Openvox, для авторизации использует метод Authorization: Basic, то мониторить статус портов (span-нов), можно средствами zabbix. Но на некоторых (более новых) Openvox-шлюзах ...
Интеграция звонков очереди Asterisk+FreePBX с Bitrix24
Задача Сделать интеграцию звонков с Bitrix24 всех агентов состоящих в очереди Asterisk. Максимальная интеграция с FreePBX. Решение За основу берем статью Оценка работы оператора FreePBX+Asterisk. Здесь мы при входящем звонке запускаем скрипт, который мониторит все события по созданному каналу. По этом же принципу мы и будем делать ...
«Умная» пересылка входящих СМС сообщений в OpenVox
Берем за пример статью Пересылка СМС с OpenVox в Telegram, здесь мы получаем сообщения с Opnevox, отсекаем только те сообщения, которые приходят на определённый порт, и отправляем сообщение в Telegram. В этой статье опишу как "умно" сортировать входящие СМС сообщения, и направлять их на определённые сервисы ...
Bitrix24 cоздание лида через API
Задача - создание лида через API запрос к облачному Bitrix24. Для решения этой задачи, будем использовать webhook. Для создания webhook переходи на портале Bitrix24 по пункту "Дополнения"→"Вебхуки" Нажимаем на кнопку "создать вебхук", из выпадающего списка выбираем "Входящий вебхук". На следующем окне нужно ввести имя вебхука ...
Мониторинг времени простоя компьютера
Чтобы реализовать мониторинг времени простоя компьютера, нужно учитывать тот факт, что пользователь обычно работает с мышкой, поэтому будем анализировать ее активность. Если мышь была не активной в течение N минут, сделаем вывод, что пользователь в настоящее время не работает с ПК. Всю статистику будем отправлять ...
Отправка сообщений в Telegram
Здесь описаны возможные способы отправки сообщений в Telegram Windows CMD Для удобства отправки с командной строки, написал консольную программу на языке Pascal. Среда разработки PascalABC.NET uses System.IO, System.Net; var i:integer; html : string; chat_id: string; {:='111111111';} token: string; {:= '0000000:AAAAAAAAAAAAAAAAAAAAAA';} parse_mode: string; {:= 'html';} message: string:=''; {:='Сообщение';} url : string; begin token := ParamStr(1); chat_id := ParamStr(2); parse_mode := ...
Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (6 оценок, среднее: 5,00 из 5)
Загрузка...

5 комментариев

  1. Alex

    Здравствуйте,
    я настроил по вашему мануалу, но у меня не работает.
    Я не получаю ответ в $tmpOc. В телеграме говорит $tmpOc={«Response»:»Error»,»Message»:»No such channel»}
    Я проверял через телнет, у меня ответ приходит.
    В чем может быть причина?

    • adminblog

      1) Скажите какая у Вас версия Asterisk-а и FreePBX-а?
      2) Вы создали контексты в файле /etc/asterisk/extensions_custom.conf? А именно [assessment-1],[assessment-2]…. и т.д.?
      3) После завершения разговора, Вам запрашивает поставить оценку?

      • Alex

        1. Версия Asterisk 13.32.0
        2. Да конечно создал контексты.
        3. Да, запрашивает поставить оценку.

        А после всего он просто ввесит в процессах
        root@freepbx /var/www/call # ps -aux | grep call
        asterisk 8921 1.4 0.9 478428 18960 ? S 13:44 0:00 php /var/www/call/call1.php incall 1587714242.4 7272500404 SIP/out_oktell-00000001

        • adminblog

          Скрипт разрабатывался под версию Астериска 1.8.10.1, к сожалению сейчас нет возможности проверить на Вашей версии.

  2. Alex

    Нашел проблему.
    В скрипте call.php переместите

    $manager->disconnect();

    после

    //telegram_message($token_telegram,$chat_id_telegram,’Завершение скрипта по номеру канала ‘.$Uniqueid.’. ответственный=’.$responsible);

    По тестам показывает, что после закрытия соединение не передается параметр оцененка

Оставить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.